00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00046 return CODEC_ID_NONE;
00047 }
00048
00049
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
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
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));
00101 sample_rate = av_ext2dbl(ext);
00102 codec->sample_rate = sample_rate;
00103 size -= 18;
00104
00105
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
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
00146
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
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
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
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
00185 filesize = get_tag(pb, &tag);
00186 if (filesize < 0 || tag != MKTAG('F', 'O', 'R', 'M'))
00187 return AVERROR_INVALIDDATA;
00188
00189
00190 tag = get_le32(pb);
00191 if (tag == MKTAG('A', 'I', 'F', 'F'))
00192 version = AIFF;
00193 else if (tag != MKTAG('A', 'I', 'F', 'C'))
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
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'):
00212
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)
00217 goto got_sound;
00218 break;
00219 case MKTAG('F', 'V', 'E', 'R'):
00220 version = get_be32(pb);
00221 break;
00222 case MKTAG('N', 'A', 'M', 'E'):
00223 get_meta(s, "title" , size);
00224 break;
00225 case MKTAG('A', 'U', 'T', 'H'):
00226 get_meta(s, "author" , size);
00227 break;
00228 case MKTAG('(', 'c', ')', ' '):
00229 get_meta(s, "copyright", size);
00230 break;
00231 case MKTAG('A', 'N', 'N', 'O'):
00232 get_meta(s, "comment" , size);
00233 break;
00234 case MKTAG('S', 'S', 'N', 'D'):
00235 aiff->data_end = url_ftell(pb) + size;
00236 offset = get_be32(pb);
00237 get_be32(pb);
00238 offset += url_ftell(pb);
00239 if (st->codec->block_align)
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:
00257 if (size & 1)
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
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
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
00295 max_size = aiff->data_end - url_ftell(s->pb);
00296 if (max_size <= 0)
00297 return AVERROR_EOF;
00298
00299
00300 if (st->codec->block_align >= 33)
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
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 };