rsoenc.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /*
  2. * RSO muxer
  3. * Copyright (c) 2001 Fabrice Bellard (original AU code)
  4. * Copyright (c) 2010 Rafael Carre
  5. *
  6. * This file is part of FFmpeg.
  7. *
  8. * FFmpeg is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * FFmpeg is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with FFmpeg; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. */
  22. #include "avformat.h"
  23. #include "internal.h"
  24. #include "riff.h"
  25. #include "rso.h"
  26. static int rso_write_header(AVFormatContext *s)
  27. {
  28. AVIOContext *pb = s->pb;
  29. AVCodecContext *enc = s->streams[0]->codec;
  30. if (!enc->codec_tag)
  31. return AVERROR_INVALIDDATA;
  32. if (enc->channels != 1) {
  33. av_log(s, AV_LOG_ERROR, "RSO only supports mono\n");
  34. return AVERROR_INVALIDDATA;
  35. }
  36. if (!s->pb->seekable) {
  37. av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n");
  38. return AVERROR_INVALIDDATA;
  39. }
  40. /* XXX: find legal sample rates (if any) */
  41. if (enc->sample_rate >= 1u<<16) {
  42. av_log(s, AV_LOG_ERROR, "Sample rate must be < 65536\n");
  43. return AVERROR_INVALIDDATA;
  44. }
  45. if (enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
  46. av_log(s, AV_LOG_ERROR, "ADPCM in RSO not implemented\n");
  47. return AVERROR_PATCHWELCOME;
  48. }
  49. /* format header */
  50. avio_wb16(pb, enc->codec_tag); /* codec ID */
  51. avio_wb16(pb, 0); /* data size, will be written at EOF */
  52. avio_wb16(pb, enc->sample_rate);
  53. avio_wb16(pb, 0x0000); /* play mode ? (0x0000 = don't loop) */
  54. avio_flush(pb);
  55. return 0;
  56. }
  57. static int rso_write_packet(AVFormatContext *s, AVPacket *pkt)
  58. {
  59. avio_write(s->pb, pkt->data, pkt->size);
  60. return 0;
  61. }
  62. static int rso_write_trailer(AVFormatContext *s)
  63. {
  64. AVIOContext *pb = s->pb;
  65. int64_t file_size;
  66. uint16_t coded_file_size;
  67. file_size = avio_tell(pb);
  68. if (file_size < 0)
  69. return file_size;
  70. if (file_size > 0xffff + RSO_HEADER_SIZE) {
  71. av_log(s, AV_LOG_WARNING,
  72. "Output file is too big (%"PRId64" bytes >= 64kB)\n", file_size);
  73. coded_file_size = 0xffff;
  74. } else {
  75. coded_file_size = file_size - RSO_HEADER_SIZE;
  76. }
  77. /* update file size */
  78. avio_seek(pb, 2, SEEK_SET);
  79. avio_wb16(pb, coded_file_size);
  80. avio_seek(pb, file_size, SEEK_SET);
  81. return 0;
  82. }
  83. AVOutputFormat ff_rso_muxer = {
  84. .name = "rso",
  85. .long_name = NULL_IF_CONFIG_SMALL("Lego Mindstorms RSO"),
  86. .extensions = "rso",
  87. .audio_codec = AV_CODEC_ID_PCM_U8,
  88. .video_codec = AV_CODEC_ID_NONE,
  89. .write_header = rso_write_header,
  90. .write_packet = rso_write_packet,
  91. .write_trailer = rso_write_trailer,
  92. .codec_tag = (const AVCodecTag* const []){ff_codec_rso_tags, 0},
  93. };