Libav 0.7.1
|
00001 /* 00002 * Core Audio Format demuxer 00003 * Copyright (c) 2007 Justin Ruggles 00004 * Copyright (c) 2009 Peter Ross 00005 * 00006 * This file is part of Libav. 00007 * 00008 * Libav is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * Libav is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with Libav; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 */ 00022 00028 #include "avformat.h" 00029 #include "riff.h" 00030 #include "isom.h" 00031 #include "libavutil/intreadwrite.h" 00032 #include "libavutil/dict.h" 00033 #include "caf.h" 00034 00035 typedef struct { 00036 int bytes_per_packet; 00037 int frames_per_packet; 00038 int64_t num_bytes; 00039 00040 int64_t packet_cnt; 00041 int64_t frame_cnt; 00042 00043 int64_t data_start; 00044 int64_t data_size; 00045 } CaffContext; 00046 00047 static int probe(AVProbeData *p) 00048 { 00049 if (AV_RB32(p->buf) == MKBETAG('c','a','f','f') && AV_RB16(&p->buf[4]) == 1) 00050 return AVPROBE_SCORE_MAX; 00051 return 0; 00052 } 00053 00055 static int read_desc_chunk(AVFormatContext *s) 00056 { 00057 AVIOContext *pb = s->pb; 00058 CaffContext *caf = s->priv_data; 00059 AVStream *st; 00060 int flags; 00061 00062 /* new audio stream */ 00063 st = av_new_stream(s, 0); 00064 if (!st) 00065 return AVERROR(ENOMEM); 00066 00067 /* parse format description */ 00068 st->codec->codec_type = AVMEDIA_TYPE_AUDIO; 00069 st->codec->sample_rate = av_int2dbl(avio_rb64(pb)); 00070 st->codec->codec_tag = avio_rb32(pb); 00071 flags = avio_rb32(pb); 00072 caf->bytes_per_packet = avio_rb32(pb); 00073 st->codec->block_align = caf->bytes_per_packet; 00074 caf->frames_per_packet = avio_rb32(pb); 00075 st->codec->channels = avio_rb32(pb); 00076 st->codec->bits_per_coded_sample = avio_rb32(pb); 00077 00078 /* calculate bit rate for constant size packets */ 00079 if (caf->frames_per_packet > 0 && caf->bytes_per_packet > 0) { 00080 st->codec->bit_rate = (uint64_t)st->codec->sample_rate * (uint64_t)caf->bytes_per_packet * 8 00081 / (uint64_t)caf->frames_per_packet; 00082 } else { 00083 st->codec->bit_rate = 0; 00084 } 00085 00086 /* determine codec */ 00087 if (st->codec->codec_tag == MKBETAG('l','p','c','m')) 00088 st->codec->codec_id = ff_mov_get_lpcm_codec_id(st->codec->bits_per_coded_sample, (flags ^ 0x2) | 0x4); 00089 else 00090 st->codec->codec_id = ff_codec_get_id(ff_codec_caf_tags, st->codec->codec_tag); 00091 return 0; 00092 } 00093 00095 static int read_kuki_chunk(AVFormatContext *s, int64_t size) 00096 { 00097 AVIOContext *pb = s->pb; 00098 AVStream *st = s->streams[0]; 00099 00100 if (size < 0 || size > INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE) 00101 return -1; 00102 00103 if (st->codec->codec_id == CODEC_ID_AAC) { 00104 /* The magic cookie format for AAC is an mp4 esds atom. 00105 The lavc AAC decoder requires the data from the codec specific 00106 description as extradata input. */ 00107 int strt, skip; 00108 MOVAtom atom; 00109 00110 strt = avio_tell(pb); 00111 ff_mov_read_esds(s, pb, atom); 00112 skip = size - (avio_tell(pb) - strt); 00113 if (skip < 0 || !st->codec->extradata || 00114 st->codec->codec_id != CODEC_ID_AAC) { 00115 av_log(s, AV_LOG_ERROR, "invalid AAC magic cookie\n"); 00116 return AVERROR_INVALIDDATA; 00117 } 00118 avio_skip(pb, skip); 00119 } else if (st->codec->codec_id == CODEC_ID_ALAC) { 00120 #define ALAC_PREAMBLE 12 00121 #define ALAC_HEADER 36 00122 if (size < ALAC_PREAMBLE + ALAC_HEADER) { 00123 av_log(s, AV_LOG_ERROR, "invalid ALAC magic cookie\n"); 00124 avio_skip(pb, size); 00125 return AVERROR_INVALIDDATA; 00126 } 00127 avio_skip(pb, ALAC_PREAMBLE); 00128 st->codec->extradata = av_mallocz(ALAC_HEADER + FF_INPUT_BUFFER_PADDING_SIZE); 00129 if (!st->codec->extradata) 00130 return AVERROR(ENOMEM); 00131 avio_read(pb, st->codec->extradata, ALAC_HEADER); 00132 st->codec->extradata_size = ALAC_HEADER; 00133 avio_skip(pb, size - ALAC_PREAMBLE - ALAC_HEADER); 00134 } else { 00135 st->codec->extradata = av_mallocz(size + FF_INPUT_BUFFER_PADDING_SIZE); 00136 if (!st->codec->extradata) 00137 return AVERROR(ENOMEM); 00138 avio_read(pb, st->codec->extradata, size); 00139 st->codec->extradata_size = size; 00140 } 00141 00142 return 0; 00143 } 00144 00146 static int read_pakt_chunk(AVFormatContext *s, int64_t size) 00147 { 00148 AVIOContext *pb = s->pb; 00149 AVStream *st = s->streams[0]; 00150 CaffContext *caf = s->priv_data; 00151 int64_t pos = 0, ccount; 00152 int num_packets, i; 00153 00154 ccount = avio_tell(pb); 00155 00156 num_packets = avio_rb64(pb); 00157 if (num_packets < 0 || INT32_MAX / sizeof(AVIndexEntry) < num_packets) 00158 return AVERROR_INVALIDDATA; 00159 00160 st->nb_frames = avio_rb64(pb); /* valid frames */ 00161 st->nb_frames += avio_rb32(pb); /* priming frames */ 00162 st->nb_frames += avio_rb32(pb); /* remainder frames */ 00163 00164 st->duration = 0; 00165 for (i = 0; i < num_packets; i++) { 00166 av_add_index_entry(s->streams[0], pos, st->duration, 0, 0, AVINDEX_KEYFRAME); 00167 pos += caf->bytes_per_packet ? caf->bytes_per_packet : ff_mp4_read_descr_len(pb); 00168 st->duration += caf->frames_per_packet ? caf->frames_per_packet : ff_mp4_read_descr_len(pb); 00169 } 00170 00171 if (avio_tell(pb) - ccount != size) { 00172 av_log(s, AV_LOG_ERROR, "error reading packet table\n"); 00173 return -1; 00174 } 00175 00176 caf->num_bytes = pos; 00177 return 0; 00178 } 00179 00181 static void read_info_chunk(AVFormatContext *s, int64_t size) 00182 { 00183 AVIOContext *pb = s->pb; 00184 unsigned int i; 00185 unsigned int nb_entries = avio_rb32(pb); 00186 for (i = 0; i < nb_entries; i++) { 00187 char key[32]; 00188 char value[1024]; 00189 avio_get_str(pb, INT_MAX, key, sizeof(key)); 00190 avio_get_str(pb, INT_MAX, value, sizeof(value)); 00191 av_dict_set(&s->metadata, key, value, 0); 00192 } 00193 } 00194 00195 static int read_header(AVFormatContext *s, 00196 AVFormatParameters *ap) 00197 { 00198 AVIOContext *pb = s->pb; 00199 CaffContext *caf = s->priv_data; 00200 AVStream *st; 00201 uint32_t tag = 0; 00202 int found_data, ret; 00203 int64_t size; 00204 00205 avio_skip(pb, 8); /* magic, version, file flags */ 00206 00207 /* audio description chunk */ 00208 if (avio_rb32(pb) != MKBETAG('d','e','s','c')) { 00209 av_log(s, AV_LOG_ERROR, "desc chunk not present\n"); 00210 return AVERROR_INVALIDDATA; 00211 } 00212 size = avio_rb64(pb); 00213 if (size != 32) 00214 return AVERROR_INVALIDDATA; 00215 00216 ret = read_desc_chunk(s); 00217 if (ret) 00218 return ret; 00219 st = s->streams[0]; 00220 00221 /* parse each chunk */ 00222 found_data = 0; 00223 while (!pb->eof_reached) { 00224 00225 /* stop at data chunk if seeking is not supported or 00226 data chunk size is unknown */ 00227 if (found_data && (caf->data_size < 0 || !pb->seekable)) 00228 break; 00229 00230 tag = avio_rb32(pb); 00231 size = avio_rb64(pb); 00232 if (pb->eof_reached) 00233 break; 00234 00235 switch (tag) { 00236 case MKBETAG('d','a','t','a'): 00237 avio_skip(pb, 4); /* edit count */ 00238 caf->data_start = avio_tell(pb); 00239 caf->data_size = size < 0 ? -1 : size - 4; 00240 if (caf->data_size > 0 && pb->seekable) 00241 avio_skip(pb, caf->data_size); 00242 found_data = 1; 00243 break; 00244 00245 /* magic cookie chunk */ 00246 case MKBETAG('k','u','k','i'): 00247 if (read_kuki_chunk(s, size)) 00248 return AVERROR_INVALIDDATA; 00249 break; 00250 00251 /* packet table chunk */ 00252 case MKBETAG('p','a','k','t'): 00253 if (read_pakt_chunk(s, size)) 00254 return AVERROR_INVALIDDATA; 00255 break; 00256 00257 case MKBETAG('i','n','f','o'): 00258 read_info_chunk(s, size); 00259 break; 00260 00261 default: 00262 #define _(x) ((x) >= ' ' ? (x) : ' ') 00263 av_log(s, AV_LOG_WARNING, "skipping CAF chunk: %08X (%c%c%c%c)\n", 00264 tag, _(tag>>24), _((tag>>16)&0xFF), _((tag>>8)&0xFF), _(tag&0xFF)); 00265 #undef _ 00266 case MKBETAG('f','r','e','e'): 00267 if (size < 0) 00268 return AVERROR_INVALIDDATA; 00269 avio_skip(pb, size); 00270 break; 00271 } 00272 } 00273 00274 if (!found_data) 00275 return AVERROR_INVALIDDATA; 00276 00277 if (caf->bytes_per_packet > 0 && caf->frames_per_packet > 0) { 00278 if (caf->data_size > 0) 00279 st->nb_frames = (caf->data_size / caf->bytes_per_packet) * caf->frames_per_packet; 00280 } else if (st->nb_index_entries) { 00281 st->codec->bit_rate = st->codec->sample_rate * caf->data_size * 8 / 00282 st->duration; 00283 } else { 00284 av_log(s, AV_LOG_ERROR, "Missing packet table. It is required when " 00285 "block size or frame size are variable.\n"); 00286 return AVERROR_INVALIDDATA; 00287 } 00288 s->file_size = avio_size(pb); 00289 s->file_size = FFMAX(0, s->file_size); 00290 00291 av_set_pts_info(st, 64, 1, st->codec->sample_rate); 00292 st->start_time = 0; 00293 00294 /* position the stream at the start of data */ 00295 if (caf->data_size >= 0) 00296 avio_seek(pb, caf->data_start, SEEK_SET); 00297 00298 return 0; 00299 } 00300 00301 #define CAF_MAX_PKT_SIZE 4096 00302 00303 static int read_packet(AVFormatContext *s, AVPacket *pkt) 00304 { 00305 AVIOContext *pb = s->pb; 00306 AVStream *st = s->streams[0]; 00307 CaffContext *caf = s->priv_data; 00308 int res, pkt_size = 0, pkt_frames = 0; 00309 int64_t left = CAF_MAX_PKT_SIZE; 00310 00311 if (pb->eof_reached) 00312 return AVERROR(EIO); 00313 00314 /* don't read past end of data chunk */ 00315 if (caf->data_size > 0) { 00316 left = (caf->data_start + caf->data_size) - avio_tell(pb); 00317 if (left <= 0) 00318 return AVERROR(EIO); 00319 } 00320 00321 pkt_frames = caf->frames_per_packet; 00322 pkt_size = caf->bytes_per_packet; 00323 00324 if (pkt_size > 0 && pkt_frames == 1) { 00325 pkt_size = (CAF_MAX_PKT_SIZE / pkt_size) * pkt_size; 00326 pkt_size = FFMIN(pkt_size, left); 00327 pkt_frames = pkt_size / caf->bytes_per_packet; 00328 } else if (st->nb_index_entries) { 00329 if (caf->packet_cnt < st->nb_index_entries - 1) { 00330 pkt_size = st->index_entries[caf->packet_cnt + 1].pos - st->index_entries[caf->packet_cnt].pos; 00331 pkt_frames = st->index_entries[caf->packet_cnt + 1].timestamp - st->index_entries[caf->packet_cnt].timestamp; 00332 } else if (caf->packet_cnt == st->nb_index_entries - 1) { 00333 pkt_size = caf->num_bytes - st->index_entries[caf->packet_cnt].pos; 00334 pkt_frames = st->duration - st->index_entries[caf->packet_cnt].timestamp; 00335 } else { 00336 return AVERROR(EIO); 00337 } 00338 } 00339 00340 if (pkt_size == 0 || pkt_frames == 0 || pkt_size > left) 00341 return AVERROR(EIO); 00342 00343 res = av_get_packet(pb, pkt, pkt_size); 00344 if (res < 0) 00345 return res; 00346 00347 pkt->size = res; 00348 pkt->stream_index = 0; 00349 pkt->dts = pkt->pts = caf->frame_cnt; 00350 00351 caf->packet_cnt++; 00352 caf->frame_cnt += pkt_frames; 00353 00354 return 0; 00355 } 00356 00357 static int read_seek(AVFormatContext *s, int stream_index, 00358 int64_t timestamp, int flags) 00359 { 00360 AVStream *st = s->streams[0]; 00361 CaffContext *caf = s->priv_data; 00362 int64_t pos; 00363 00364 timestamp = FFMAX(timestamp, 0); 00365 00366 if (caf->frames_per_packet > 0 && caf->bytes_per_packet > 0) { 00367 /* calculate new byte position based on target frame position */ 00368 pos = caf->bytes_per_packet * timestamp / caf->frames_per_packet; 00369 if (caf->data_size > 0) 00370 pos = FFMIN(pos, caf->data_size); 00371 caf->packet_cnt = pos / caf->bytes_per_packet; 00372 caf->frame_cnt = caf->frames_per_packet * caf->packet_cnt; 00373 } else if (st->nb_index_entries) { 00374 caf->packet_cnt = av_index_search_timestamp(st, timestamp, flags); 00375 caf->frame_cnt = st->index_entries[caf->packet_cnt].timestamp; 00376 pos = st->index_entries[caf->packet_cnt].pos; 00377 } else { 00378 return -1; 00379 } 00380 00381 avio_seek(s->pb, pos + caf->data_start, SEEK_SET); 00382 return 0; 00383 } 00384 00385 AVInputFormat ff_caf_demuxer = { 00386 "caf", 00387 NULL_IF_CONFIG_SMALL("Apple Core Audio Format"), 00388 sizeof(CaffContext), 00389 probe, 00390 read_header, 00391 read_packet, 00392 NULL, 00393 read_seek, 00394 .codec_tag = (const AVCodecTag*[]){ff_codec_caf_tags, 0}, 00395 };