iff.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. * IFF (.iff) file demuxer
  3. * Copyright (c) 2008 Jaikrishnan Menon <realityman@gmx.net>
  4. *
  5. * This file is part of FFmpeg.
  6. *
  7. * FFmpeg is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * FFmpeg is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with FFmpeg; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. /**
  22. * @file libavformat/iff.c
  23. * IFF file demuxer
  24. * by Jaikrishnan Menon
  25. * for more information on the .iff file format, visit:
  26. * http://wiki.multimedia.cx/index.php?title=IFF
  27. */
  28. #include "libavutil/intreadwrite.h"
  29. #include "avformat.h"
  30. #define ID_8SVX MKTAG('8','S','V','X')
  31. #define ID_VHDR MKTAG('V','H','D','R')
  32. #define ID_ATAK MKTAG('A','T','A','K')
  33. #define ID_RLSE MKTAG('R','L','S','E')
  34. #define ID_CHAN MKTAG('C','H','A','N')
  35. #define ID_FORM MKTAG('F','O','R','M')
  36. #define ID_ANNO MKTAG('A','N','N','O')
  37. #define ID_AUTH MKTAG('A','U','T','H')
  38. #define ID_CHRS MKTAG('C','H','R','S')
  39. #define ID_COPYRIGHT MKTAG('(','c',')',' ')
  40. #define ID_CSET MKTAG('C','S','E','T')
  41. #define ID_FVER MKTAG('F','V','E','R')
  42. #define ID_NAME MKTAG('N','A','M','E')
  43. #define ID_TEXT MKTAG('T','E','X','T')
  44. #define ID_BODY MKTAG('B','O','D','Y')
  45. #define LEFT 2
  46. #define RIGHT 4
  47. #define STEREO 6
  48. #define PACKET_SIZE 1024
  49. typedef enum {COMP_NONE, COMP_FIB, COMP_EXP} svx8_compression_type;
  50. typedef struct {
  51. uint32_t body_size;
  52. uint32_t sent_bytes;
  53. uint32_t audio_frame_count;
  54. } IffDemuxContext;
  55. static void interleave_stereo(const uint8_t *src, uint8_t *dest, int size)
  56. {
  57. uint8_t *end = dest + size;
  58. size = size>>1;
  59. while(dest < end) {
  60. *dest++ = *src;
  61. *dest++ = *(src+size);
  62. src++;
  63. }
  64. }
  65. static int iff_probe(AVProbeData *p)
  66. {
  67. const uint8_t *d = p->buf;
  68. if ( AV_RL32(d) == ID_FORM &&
  69. AV_RL32(d+8) == ID_8SVX)
  70. return AVPROBE_SCORE_MAX;
  71. return 0;
  72. }
  73. static int iff_read_header(AVFormatContext *s,
  74. AVFormatParameters *ap)
  75. {
  76. IffDemuxContext *iff = s->priv_data;
  77. ByteIOContext *pb = s->pb;
  78. AVStream *st;
  79. uint32_t chunk_id, data_size;
  80. int padding, done = 0;
  81. st = av_new_stream(s, 0);
  82. if (!st)
  83. return AVERROR(ENOMEM);
  84. st->codec->channels = 1;
  85. url_fskip(pb, 12);
  86. while(!done && !url_feof(pb)) {
  87. chunk_id = get_le32(pb);
  88. data_size = get_be32(pb);
  89. padding = data_size & 1;
  90. switch(chunk_id) {
  91. case ID_VHDR:
  92. url_fskip(pb, 12);
  93. st->codec->sample_rate = get_be16(pb);
  94. url_fskip(pb, 1);
  95. st->codec->codec_tag = get_byte(pb);
  96. url_fskip(pb, 4);
  97. break;
  98. case ID_BODY:
  99. iff->body_size = data_size;
  100. done = 1;
  101. break;
  102. case ID_CHAN:
  103. st->codec->channels = (get_be32(pb) < 6) ? 1 : 2;
  104. break;
  105. default:
  106. url_fseek(pb, data_size + padding, SEEK_CUR);
  107. break;
  108. }
  109. }
  110. if(!st->codec->sample_rate)
  111. return AVERROR_INVALIDDATA;
  112. av_set_pts_info(st, 32, 1, st->codec->sample_rate);
  113. st->codec->codec_type = CODEC_TYPE_AUDIO;
  114. switch(st->codec->codec_tag) {
  115. case COMP_NONE:
  116. st->codec->codec_id = CODEC_ID_PCM_S8;
  117. break;
  118. case COMP_FIB:
  119. st->codec->codec_id = CODEC_ID_8SVX_FIB;
  120. break;
  121. case COMP_EXP:
  122. st->codec->codec_id = CODEC_ID_8SVX_EXP;
  123. break;
  124. default:
  125. av_log(s, AV_LOG_ERROR, "iff: unknown compression method\n");
  126. return -1;
  127. }
  128. st->codec->bits_per_coded_sample = 8;
  129. st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * st->codec->bits_per_coded_sample;
  130. st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample;
  131. return 0;
  132. }
  133. static int iff_read_packet(AVFormatContext *s,
  134. AVPacket *pkt)
  135. {
  136. IffDemuxContext *iff = s->priv_data;
  137. ByteIOContext *pb = s->pb;
  138. int ret;
  139. if(iff->sent_bytes > iff->body_size)
  140. return AVERROR(EIO);
  141. if(s->streams[0]->codec->channels == 2) {
  142. uint8_t sample_buffer[PACKET_SIZE];
  143. ret = get_buffer(pb, sample_buffer, PACKET_SIZE);
  144. if(av_new_packet(pkt, PACKET_SIZE) < 0) {
  145. av_log(s, AV_LOG_ERROR, "iff: cannot allocate packet \n");
  146. return AVERROR(ENOMEM);
  147. }
  148. interleave_stereo(sample_buffer, pkt->data, PACKET_SIZE);
  149. }
  150. else {
  151. ret = av_get_packet(pb, pkt, PACKET_SIZE);
  152. }
  153. if(iff->sent_bytes == 0)
  154. pkt->flags |= PKT_FLAG_KEY;
  155. iff->sent_bytes += PACKET_SIZE;
  156. pkt->stream_index = 0;
  157. pkt->pts = iff->audio_frame_count;
  158. iff->audio_frame_count += ret / s->streams[0]->codec->channels;
  159. return ret;
  160. }
  161. AVInputFormat iff_demuxer = {
  162. "IFF",
  163. NULL_IF_CONFIG_SMALL("IFF format"),
  164. sizeof(IffDemuxContext),
  165. iff_probe,
  166. iff_read_header,
  167. iff_read_packet,
  168. };