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