• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavformat/iff.c

Go to the documentation of this file.
00001 /*
00002  * IFF (.iff) file demuxer
00003  * Copyright (c) 2008 Jaikrishnan Menon <realityman@gmx.net>
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00030 #include "libavutil/intreadwrite.h"
00031 #include "avformat.h"
00032 
00033 #define ID_8SVX       MKTAG('8','S','V','X')
00034 #define ID_VHDR       MKTAG('V','H','D','R')
00035 #define ID_ATAK       MKTAG('A','T','A','K')
00036 #define ID_RLSE       MKTAG('R','L','S','E')
00037 #define ID_CHAN       MKTAG('C','H','A','N')
00038 
00039 #define ID_FORM       MKTAG('F','O','R','M')
00040 #define ID_ANNO       MKTAG('A','N','N','O')
00041 #define ID_AUTH       MKTAG('A','U','T','H')
00042 #define ID_CHRS       MKTAG('C','H','R','S')
00043 #define ID_COPYRIGHT  MKTAG('(','c',')',' ')
00044 #define ID_CSET       MKTAG('C','S','E','T')
00045 #define ID_FVER       MKTAG('F','V','E','R')
00046 #define ID_NAME       MKTAG('N','A','M','E')
00047 #define ID_TEXT       MKTAG('T','E','X','T')
00048 #define ID_BODY       MKTAG('B','O','D','Y')
00049 
00050 #define LEFT    2
00051 #define RIGHT   4
00052 #define STEREO  6
00053 
00054 #define PACKET_SIZE 1024
00055 
00056 typedef enum {COMP_NONE, COMP_FIB, COMP_EXP} svx8_compression_type;
00057 
00058 typedef struct {
00059     uint32_t  body_size;
00060     uint32_t  sent_bytes;
00061     uint32_t  audio_frame_count;
00062 } IffDemuxContext;
00063 
00064 
00065 static void interleave_stereo(const uint8_t *src, uint8_t *dest, int size)
00066 {
00067     uint8_t *end = dest + size;
00068     size = size>>1;
00069 
00070     while(dest < end) {
00071         *dest++ = *src;
00072         *dest++ = *(src+size);
00073         src++;
00074     }
00075 }
00076 
00077 static int iff_probe(AVProbeData *p)
00078 {
00079     const uint8_t *d = p->buf;
00080 
00081     if ( AV_RL32(d)   == ID_FORM &&
00082          AV_RL32(d+8) == ID_8SVX)
00083         return AVPROBE_SCORE_MAX;
00084     return 0;
00085 }
00086 
00087 static int iff_read_header(AVFormatContext *s,
00088                            AVFormatParameters *ap)
00089 {
00090     IffDemuxContext *iff = s->priv_data;
00091     ByteIOContext *pb = s->pb;
00092     AVStream *st;
00093     uint32_t chunk_id, data_size;
00094     int padding, done = 0;
00095 
00096     st = av_new_stream(s, 0);
00097     if (!st)
00098       return AVERROR(ENOMEM);
00099 
00100     st->codec->channels = 1;
00101     url_fskip(pb, 12);
00102 
00103     while(!done && !url_feof(pb)) {
00104         chunk_id = get_le32(pb);
00105         data_size = get_be32(pb);
00106         padding = data_size & 1;
00107 
00108         switch(chunk_id) {
00109         case ID_VHDR:
00110             url_fskip(pb, 12);
00111             st->codec->sample_rate = get_be16(pb);
00112             url_fskip(pb, 1);
00113             st->codec->codec_tag = get_byte(pb);
00114             url_fskip(pb, 4);
00115             break;
00116 
00117         case ID_BODY:
00118             iff->body_size = data_size;
00119             done = 1;
00120             break;
00121 
00122         case ID_CHAN:
00123             st->codec->channels = (get_be32(pb) < 6) ? 1 : 2;
00124             break;
00125 
00126         default:
00127             url_fseek(pb, data_size + padding, SEEK_CUR);
00128             break;
00129         }
00130     }
00131 
00132     if(!st->codec->sample_rate)
00133         return AVERROR_INVALIDDATA;
00134 
00135     av_set_pts_info(st, 32, 1, st->codec->sample_rate);
00136     st->codec->codec_type = CODEC_TYPE_AUDIO;
00137 
00138     switch(st->codec->codec_tag) {
00139     case COMP_NONE:
00140         st->codec->codec_id = CODEC_ID_PCM_S8;
00141         break;
00142     case COMP_FIB:
00143         st->codec->codec_id = CODEC_ID_8SVX_FIB;
00144         break;
00145     case COMP_EXP:
00146         st->codec->codec_id = CODEC_ID_8SVX_EXP;
00147         break;
00148     default:
00149         av_log(s, AV_LOG_ERROR, "iff: unknown compression method\n");
00150         return -1;
00151     }
00152 
00153     st->codec->bits_per_coded_sample = 8;
00154     st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * st->codec->bits_per_coded_sample;
00155     st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample;
00156 
00157     return 0;
00158 }
00159 
00160 static int iff_read_packet(AVFormatContext *s,
00161                            AVPacket *pkt)
00162 {
00163     IffDemuxContext *iff = s->priv_data;
00164     ByteIOContext *pb = s->pb;
00165     int ret;
00166 
00167     if(iff->sent_bytes > iff->body_size)
00168         return AVERROR(EIO);
00169 
00170     if(s->streams[0]->codec->channels == 2) {
00171         uint8_t sample_buffer[PACKET_SIZE];
00172 
00173         ret = get_buffer(pb, sample_buffer, PACKET_SIZE);
00174         if(av_new_packet(pkt, PACKET_SIZE) < 0) {
00175             av_log(s, AV_LOG_ERROR, "iff: cannot allocate packet \n");
00176             return AVERROR(ENOMEM);
00177         }
00178         interleave_stereo(sample_buffer, pkt->data, PACKET_SIZE);
00179     }
00180     else {
00181         ret = av_get_packet(pb, pkt, PACKET_SIZE);
00182     }
00183 
00184     if(iff->sent_bytes == 0)
00185         pkt->flags |= PKT_FLAG_KEY;
00186 
00187     iff->sent_bytes += PACKET_SIZE;
00188     pkt->stream_index = 0;
00189     pkt->pts = iff->audio_frame_count;
00190     iff->audio_frame_count += ret / s->streams[0]->codec->channels;
00191     return ret;
00192 }
00193 
00194 AVInputFormat iff_demuxer = {
00195     "IFF",
00196     NULL_IF_CONFIG_SMALL("IFF format"),
00197     sizeof(IffDemuxContext),
00198     iff_probe,
00199     iff_read_header,
00200     iff_read_packet,
00201 };

Generated on Sat Feb 16 2013 09:23:14 for ffmpeg by  doxygen 1.7.1