1/* 2 * AIFF/AIFF-C demuxer 3 * Copyright (c) 2006 Patrick Guimond 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#include "libavutil/intfloat_readwrite.h" 23#include "avformat.h" 24#include "raw.h" 25#include "aiff.h" 26 27#define AIFF 0 28#define AIFF_C_VERSION1 0xA2805140 29 30typedef struct { 31 int64_t data_end; 32} AIFFInputContext; 33 34static enum CodecID aiff_codec_get_id(int bps) 35{ 36 if (bps <= 8) 37 return CODEC_ID_PCM_S8; 38 if (bps <= 16) 39 return CODEC_ID_PCM_S16BE; 40 if (bps <= 24) 41 return CODEC_ID_PCM_S24BE; 42 if (bps <= 32) 43 return CODEC_ID_PCM_S32BE; 44 45 /* bigger than 32 isn't allowed */ 46 return CODEC_ID_NONE; 47} 48 49/* returns the size of the found tag */ 50static int get_tag(ByteIOContext *pb, uint32_t * tag) 51{ 52 int size; 53 54 if (url_feof(pb)) 55 return AVERROR(EIO); 56 57 *tag = get_le32(pb); 58 size = get_be32(pb); 59 60 if (size < 0) 61 size = 0x7fffffff; 62 63 return size; 64} 65 66/* Metadata string read */ 67static void get_meta(AVFormatContext *s, const char *key, int size) 68{ 69 uint8_t *str = av_malloc(size+1); 70 int res; 71 72 if (!str) { 73 url_fskip(s->pb, size); 74 return; 75 } 76 77 res = get_buffer(s->pb, str, size); 78 if (res < 0) 79 return; 80 81 str[res] = 0; 82 av_metadata_set2(&s->metadata, key, str, AV_METADATA_DONT_STRDUP_VAL); 83} 84 85/* Returns the number of sound data frames or negative on error */ 86static unsigned int get_aiff_header(ByteIOContext *pb, AVCodecContext *codec, 87 int size, unsigned version) 88{ 89 AVExtFloat ext; 90 double sample_rate; 91 unsigned int num_frames; 92 93 if (size & 1) 94 size++; 95 codec->codec_type = AVMEDIA_TYPE_AUDIO; 96 codec->channels = get_be16(pb); 97 num_frames = get_be32(pb); 98 codec->bits_per_coded_sample = get_be16(pb); 99 100 get_buffer(pb, (uint8_t*)&ext, sizeof(ext));/* Sample rate is in */ 101 sample_rate = av_ext2dbl(ext); /* 80 bits BE IEEE extended float */ 102 codec->sample_rate = sample_rate; 103 size -= 18; 104 105 /* Got an AIFF-C? */ 106 if (version == AIFF_C_VERSION1) { 107 codec->codec_tag = get_le32(pb); 108 codec->codec_id = ff_codec_get_id(ff_codec_aiff_tags, codec->codec_tag); 109 110 switch (codec->codec_id) { 111 case CODEC_ID_PCM_S16BE: 112 codec->codec_id = aiff_codec_get_id(codec->bits_per_coded_sample); 113 codec->bits_per_coded_sample = av_get_bits_per_sample(codec->codec_id); 114 break; 115 case CODEC_ID_ADPCM_IMA_QT: 116 codec->block_align = 34*codec->channels; 117 codec->frame_size = 64; 118 break; 119 case CODEC_ID_MACE3: 120 codec->block_align = 2*codec->channels; 121 codec->frame_size = 6; 122 break; 123 case CODEC_ID_MACE6: 124 codec->block_align = 1*codec->channels; 125 codec->frame_size = 6; 126 break; 127 case CODEC_ID_GSM: 128 codec->block_align = 33; 129 codec->frame_size = 160; 130 break; 131 case CODEC_ID_QCELP: 132 codec->block_align = 35; 133 codec->frame_size= 160; 134 break; 135 default: 136 break; 137 } 138 size -= 4; 139 } else { 140 /* Need the codec type */ 141 codec->codec_id = aiff_codec_get_id(codec->bits_per_coded_sample); 142 codec->bits_per_coded_sample = av_get_bits_per_sample(codec->codec_id); 143 } 144 145 /* Block align needs to be computed in all cases, as the definition 146 * is specific to applications -> here we use the WAVE format definition */ 147 if (!codec->block_align) 148 codec->block_align = (codec->bits_per_coded_sample * codec->channels) >> 3; 149 150 codec->bit_rate = (codec->frame_size ? codec->sample_rate/codec->frame_size : 151 codec->sample_rate) * (codec->block_align << 3); 152 153 /* Chunk is over */ 154 if (size) 155 url_fseek(pb, size, SEEK_CUR); 156 157 return num_frames; 158} 159 160static int aiff_probe(AVProbeData *p) 161{ 162 /* check file header */ 163 if (p->buf[0] == 'F' && p->buf[1] == 'O' && 164 p->buf[2] == 'R' && p->buf[3] == 'M' && 165 p->buf[8] == 'A' && p->buf[9] == 'I' && 166 p->buf[10] == 'F' && (p->buf[11] == 'F' || p->buf[11] == 'C')) 167 return AVPROBE_SCORE_MAX; 168 else 169 return 0; 170} 171 172/* aiff input */ 173static int aiff_read_header(AVFormatContext *s, 174 AVFormatParameters *ap) 175{ 176 int size, filesize; 177 int64_t offset = 0; 178 uint32_t tag; 179 unsigned version = AIFF_C_VERSION1; 180 ByteIOContext *pb = s->pb; 181 AVStream * st; 182 AIFFInputContext *aiff = s->priv_data; 183 184 /* check FORM header */ 185 filesize = get_tag(pb, &tag); 186 if (filesize < 0 || tag != MKTAG('F', 'O', 'R', 'M')) 187 return AVERROR_INVALIDDATA; 188 189 /* AIFF data type */ 190 tag = get_le32(pb); 191 if (tag == MKTAG('A', 'I', 'F', 'F')) /* Got an AIFF file */ 192 version = AIFF; 193 else if (tag != MKTAG('A', 'I', 'F', 'C')) /* An AIFF-C file then */ 194 return AVERROR_INVALIDDATA; 195 196 filesize -= 4; 197 198 st = av_new_stream(s, 0); 199 if (!st) 200 return AVERROR(ENOMEM); 201 202 while (filesize > 0) { 203 /* parse different chunks */ 204 size = get_tag(pb, &tag); 205 if (size < 0) 206 return size; 207 208 filesize -= size + 8; 209 210 switch (tag) { 211 case MKTAG('C', 'O', 'M', 'M'): /* Common chunk */ 212 /* Then for the complete header info */ 213 st->nb_frames = get_aiff_header(pb, st->codec, size, version); 214 if (st->nb_frames < 0) 215 return st->nb_frames; 216 if (offset > 0) // COMM is after SSND 217 goto got_sound; 218 break; 219 case MKTAG('F', 'V', 'E', 'R'): /* Version chunk */ 220 version = get_be32(pb); 221 break; 222 case MKTAG('N', 'A', 'M', 'E'): /* Sample name chunk */ 223 get_meta(s, "title" , size); 224 break; 225 case MKTAG('A', 'U', 'T', 'H'): /* Author chunk */ 226 get_meta(s, "author" , size); 227 break; 228 case MKTAG('(', 'c', ')', ' '): /* Copyright chunk */ 229 get_meta(s, "copyright", size); 230 break; 231 case MKTAG('A', 'N', 'N', 'O'): /* Annotation chunk */ 232 get_meta(s, "comment" , size); 233 break; 234 case MKTAG('S', 'S', 'N', 'D'): /* Sampled sound chunk */ 235 aiff->data_end = url_ftell(pb) + size; 236 offset = get_be32(pb); /* Offset of sound data */ 237 get_be32(pb); /* BlockSize... don't care */ 238 offset += url_ftell(pb); /* Compute absolute data offset */ 239 if (st->codec->block_align) /* Assume COMM already parsed */ 240 goto got_sound; 241 if (url_is_streamed(pb)) { 242 av_log(s, AV_LOG_ERROR, "file is not seekable\n"); 243 return -1; 244 } 245 url_fskip(pb, size - 8); 246 break; 247 case MKTAG('w', 'a', 'v', 'e'): 248 if ((uint64_t)size > (1<<30)) 249 return -1; 250 st->codec->extradata = av_mallocz(size + FF_INPUT_BUFFER_PADDING_SIZE); 251 if (!st->codec->extradata) 252 return AVERROR(ENOMEM); 253 st->codec->extradata_size = size; 254 get_buffer(pb, st->codec->extradata, size); 255 break; 256 default: /* Jump */ 257 if (size & 1) /* Always even aligned */ 258 size++; 259 url_fskip (pb, size); 260 } 261 } 262 263 if (!st->codec->block_align) { 264 av_log(s, AV_LOG_ERROR, "could not find COMM tag\n"); 265 return -1; 266 } 267 268got_sound: 269 /* Now positioned, get the sound data start and end */ 270 if (st->nb_frames) 271 s->file_size = st->nb_frames * st->codec->block_align; 272 273 av_set_pts_info(st, 64, 1, st->codec->sample_rate); 274 st->start_time = 0; 275 st->duration = st->codec->frame_size ? 276 st->nb_frames * st->codec->frame_size : st->nb_frames; 277 278 /* Position the stream at the first block */ 279 url_fseek(pb, offset, SEEK_SET); 280 281 return 0; 282} 283 284#define MAX_SIZE 4096 285 286static int aiff_read_packet(AVFormatContext *s, 287 AVPacket *pkt) 288{ 289 AVStream *st = s->streams[0]; 290 AIFFInputContext *aiff = s->priv_data; 291 int64_t max_size; 292 int res, size; 293 294 /* calculate size of remaining data */ 295 max_size = aiff->data_end - url_ftell(s->pb); 296 if (max_size <= 0) 297 return AVERROR_EOF; 298 299 /* Now for that packet */ 300 if (st->codec->block_align >= 33) // GSM, QCLP, IMA4 301 size = st->codec->block_align; 302 else 303 size = (MAX_SIZE / st->codec->block_align) * st->codec->block_align; 304 size = FFMIN(max_size, size); 305 res = av_get_packet(s->pb, pkt, size); 306 if (res < 0) 307 return res; 308 309 /* Only one stream in an AIFF file */ 310 pkt->stream_index = 0; 311 return 0; 312} 313 314AVInputFormat aiff_demuxer = { 315 "aiff", 316 NULL_IF_CONFIG_SMALL("Audio IFF"), 317 sizeof(AIFFInputContext), 318 aiff_probe, 319 aiff_read_header, 320 aiff_read_packet, 321 NULL, 322 pcm_read_seek, 323 .codec_tag= (const AVCodecTag* const []){ff_codec_aiff_tags, 0}, 324}; 325