Libav 0.7.1
|
00001 /* 00002 * AIFF/AIFF-C demuxer 00003 * Copyright (c) 2006 Patrick Guimond 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav 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 * Libav 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 Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00022 #include "libavutil/intfloat_readwrite.h" 00023 #include "libavutil/dict.h" 00024 #include "avformat.h" 00025 #include "pcm.h" 00026 #include "aiff.h" 00027 00028 #define AIFF 0 00029 #define AIFF_C_VERSION1 0xA2805140 00030 00031 typedef struct { 00032 int64_t data_end; 00033 } AIFFInputContext; 00034 00035 static enum CodecID aiff_codec_get_id(int bps) 00036 { 00037 if (bps <= 8) 00038 return CODEC_ID_PCM_S8; 00039 if (bps <= 16) 00040 return CODEC_ID_PCM_S16BE; 00041 if (bps <= 24) 00042 return CODEC_ID_PCM_S24BE; 00043 if (bps <= 32) 00044 return CODEC_ID_PCM_S32BE; 00045 00046 /* bigger than 32 isn't allowed */ 00047 return CODEC_ID_NONE; 00048 } 00049 00050 /* returns the size of the found tag */ 00051 static int get_tag(AVIOContext *pb, uint32_t * tag) 00052 { 00053 int size; 00054 00055 if (pb->eof_reached) 00056 return AVERROR(EIO); 00057 00058 *tag = avio_rl32(pb); 00059 size = avio_rb32(pb); 00060 00061 if (size < 0) 00062 size = 0x7fffffff; 00063 00064 return size; 00065 } 00066 00067 /* Metadata string read */ 00068 static void get_meta(AVFormatContext *s, const char *key, int size) 00069 { 00070 uint8_t *str = av_malloc(size+1); 00071 int res; 00072 00073 if (!str) { 00074 avio_skip(s->pb, size); 00075 return; 00076 } 00077 00078 res = avio_read(s->pb, str, size); 00079 if (res < 0) 00080 return; 00081 00082 str[res] = 0; 00083 av_dict_set(&s->metadata, key, str, AV_DICT_DONT_STRDUP_VAL); 00084 } 00085 00086 /* Returns the number of sound data frames or negative on error */ 00087 static unsigned int get_aiff_header(AVIOContext *pb, AVCodecContext *codec, 00088 int size, unsigned version) 00089 { 00090 AVExtFloat ext; 00091 double sample_rate; 00092 unsigned int num_frames; 00093 00094 if (size & 1) 00095 size++; 00096 codec->codec_type = AVMEDIA_TYPE_AUDIO; 00097 codec->channels = avio_rb16(pb); 00098 num_frames = avio_rb32(pb); 00099 codec->bits_per_coded_sample = avio_rb16(pb); 00100 00101 avio_read(pb, (uint8_t*)&ext, sizeof(ext));/* Sample rate is in */ 00102 sample_rate = av_ext2dbl(ext); /* 80 bits BE IEEE extended float */ 00103 codec->sample_rate = sample_rate; 00104 size -= 18; 00105 00106 /* Got an AIFF-C? */ 00107 if (version == AIFF_C_VERSION1) { 00108 codec->codec_tag = avio_rl32(pb); 00109 codec->codec_id = ff_codec_get_id(ff_codec_aiff_tags, codec->codec_tag); 00110 00111 switch (codec->codec_id) { 00112 case CODEC_ID_PCM_S16BE: 00113 codec->codec_id = aiff_codec_get_id(codec->bits_per_coded_sample); 00114 codec->bits_per_coded_sample = av_get_bits_per_sample(codec->codec_id); 00115 break; 00116 case CODEC_ID_ADPCM_IMA_QT: 00117 codec->block_align = 34*codec->channels; 00118 codec->frame_size = 64; 00119 break; 00120 case CODEC_ID_MACE3: 00121 codec->block_align = 2*codec->channels; 00122 codec->frame_size = 6; 00123 break; 00124 case CODEC_ID_MACE6: 00125 codec->block_align = 1*codec->channels; 00126 codec->frame_size = 6; 00127 break; 00128 case CODEC_ID_GSM: 00129 codec->block_align = 33; 00130 codec->frame_size = 160; 00131 break; 00132 case CODEC_ID_QCELP: 00133 codec->block_align = 35; 00134 codec->frame_size= 160; 00135 break; 00136 default: 00137 break; 00138 } 00139 size -= 4; 00140 } else { 00141 /* Need the codec type */ 00142 codec->codec_id = aiff_codec_get_id(codec->bits_per_coded_sample); 00143 codec->bits_per_coded_sample = av_get_bits_per_sample(codec->codec_id); 00144 } 00145 00146 /* Block align needs to be computed in all cases, as the definition 00147 * is specific to applications -> here we use the WAVE format definition */ 00148 if (!codec->block_align) 00149 codec->block_align = (codec->bits_per_coded_sample * codec->channels) >> 3; 00150 00151 codec->bit_rate = (codec->frame_size ? codec->sample_rate/codec->frame_size : 00152 codec->sample_rate) * (codec->block_align << 3); 00153 00154 /* Chunk is over */ 00155 if (size) 00156 avio_skip(pb, size); 00157 00158 return num_frames; 00159 } 00160 00161 static int aiff_probe(AVProbeData *p) 00162 { 00163 /* check file header */ 00164 if (p->buf[0] == 'F' && p->buf[1] == 'O' && 00165 p->buf[2] == 'R' && p->buf[3] == 'M' && 00166 p->buf[8] == 'A' && p->buf[9] == 'I' && 00167 p->buf[10] == 'F' && (p->buf[11] == 'F' || p->buf[11] == 'C')) 00168 return AVPROBE_SCORE_MAX; 00169 else 00170 return 0; 00171 } 00172 00173 /* aiff input */ 00174 static int aiff_read_header(AVFormatContext *s, 00175 AVFormatParameters *ap) 00176 { 00177 int size, filesize; 00178 int64_t offset = 0; 00179 uint32_t tag; 00180 unsigned version = AIFF_C_VERSION1; 00181 AVIOContext *pb = s->pb; 00182 AVStream * st; 00183 AIFFInputContext *aiff = s->priv_data; 00184 00185 /* check FORM header */ 00186 filesize = get_tag(pb, &tag); 00187 if (filesize < 0 || tag != MKTAG('F', 'O', 'R', 'M')) 00188 return AVERROR_INVALIDDATA; 00189 00190 /* AIFF data type */ 00191 tag = avio_rl32(pb); 00192 if (tag == MKTAG('A', 'I', 'F', 'F')) /* Got an AIFF file */ 00193 version = AIFF; 00194 else if (tag != MKTAG('A', 'I', 'F', 'C')) /* An AIFF-C file then */ 00195 return AVERROR_INVALIDDATA; 00196 00197 filesize -= 4; 00198 00199 st = av_new_stream(s, 0); 00200 if (!st) 00201 return AVERROR(ENOMEM); 00202 00203 while (filesize > 0) { 00204 /* parse different chunks */ 00205 size = get_tag(pb, &tag); 00206 if (size < 0) 00207 return size; 00208 00209 filesize -= size + 8; 00210 00211 switch (tag) { 00212 case MKTAG('C', 'O', 'M', 'M'): /* Common chunk */ 00213 /* Then for the complete header info */ 00214 st->nb_frames = get_aiff_header(pb, st->codec, size, version); 00215 if (st->nb_frames < 0) 00216 return st->nb_frames; 00217 if (offset > 0) // COMM is after SSND 00218 goto got_sound; 00219 break; 00220 case MKTAG('F', 'V', 'E', 'R'): /* Version chunk */ 00221 version = avio_rb32(pb); 00222 break; 00223 case MKTAG('N', 'A', 'M', 'E'): /* Sample name chunk */ 00224 get_meta(s, "title" , size); 00225 break; 00226 case MKTAG('A', 'U', 'T', 'H'): /* Author chunk */ 00227 get_meta(s, "author" , size); 00228 break; 00229 case MKTAG('(', 'c', ')', ' '): /* Copyright chunk */ 00230 get_meta(s, "copyright", size); 00231 break; 00232 case MKTAG('A', 'N', 'N', 'O'): /* Annotation chunk */ 00233 get_meta(s, "comment" , size); 00234 break; 00235 case MKTAG('S', 'S', 'N', 'D'): /* Sampled sound chunk */ 00236 aiff->data_end = avio_tell(pb) + size; 00237 offset = avio_rb32(pb); /* Offset of sound data */ 00238 avio_rb32(pb); /* BlockSize... don't care */ 00239 offset += avio_tell(pb); /* Compute absolute data offset */ 00240 if (st->codec->block_align) /* Assume COMM already parsed */ 00241 goto got_sound; 00242 if (!pb->seekable) { 00243 av_log(s, AV_LOG_ERROR, "file is not seekable\n"); 00244 return -1; 00245 } 00246 avio_skip(pb, size - 8); 00247 break; 00248 case MKTAG('w', 'a', 'v', 'e'): 00249 if ((uint64_t)size > (1<<30)) 00250 return -1; 00251 st->codec->extradata = av_mallocz(size + FF_INPUT_BUFFER_PADDING_SIZE); 00252 if (!st->codec->extradata) 00253 return AVERROR(ENOMEM); 00254 st->codec->extradata_size = size; 00255 avio_read(pb, st->codec->extradata, size); 00256 break; 00257 default: /* Jump */ 00258 if (size & 1) /* Always even aligned */ 00259 size++; 00260 avio_skip(pb, size); 00261 } 00262 } 00263 00264 if (!st->codec->block_align) { 00265 av_log(s, AV_LOG_ERROR, "could not find COMM tag\n"); 00266 return -1; 00267 } 00268 00269 got_sound: 00270 /* Now positioned, get the sound data start and end */ 00271 if (st->nb_frames) 00272 s->file_size = st->nb_frames * st->codec->block_align; 00273 00274 av_set_pts_info(st, 64, 1, st->codec->sample_rate); 00275 st->start_time = 0; 00276 st->duration = st->codec->frame_size ? 00277 st->nb_frames * st->codec->frame_size : st->nb_frames; 00278 00279 /* Position the stream at the first block */ 00280 avio_seek(pb, offset, SEEK_SET); 00281 00282 return 0; 00283 } 00284 00285 #define MAX_SIZE 4096 00286 00287 static int aiff_read_packet(AVFormatContext *s, 00288 AVPacket *pkt) 00289 { 00290 AVStream *st = s->streams[0]; 00291 AIFFInputContext *aiff = s->priv_data; 00292 int64_t max_size; 00293 int res, size; 00294 00295 /* calculate size of remaining data */ 00296 max_size = aiff->data_end - avio_tell(s->pb); 00297 if (max_size <= 0) 00298 return AVERROR_EOF; 00299 00300 /* Now for that packet */ 00301 if (st->codec->block_align >= 33) // GSM, QCLP, IMA4 00302 size = st->codec->block_align; 00303 else 00304 size = (MAX_SIZE / st->codec->block_align) * st->codec->block_align; 00305 size = FFMIN(max_size, size); 00306 res = av_get_packet(s->pb, pkt, size); 00307 if (res < 0) 00308 return res; 00309 00310 /* Only one stream in an AIFF file */ 00311 pkt->stream_index = 0; 00312 return 0; 00313 } 00314 00315 AVInputFormat ff_aiff_demuxer = { 00316 "aiff", 00317 NULL_IF_CONFIG_SMALL("Audio IFF"), 00318 sizeof(AIFFInputContext), 00319 aiff_probe, 00320 aiff_read_header, 00321 aiff_read_packet, 00322 NULL, 00323 pcm_read_seek, 00324 .codec_tag= (const AVCodecTag* const []){ff_codec_aiff_tags, 0}, 00325 };