1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Core Audio Format demuxer 3cabdff1aSopenharmony_ci * Copyright (c) 2007 Justin Ruggles 4cabdff1aSopenharmony_ci * Copyright (c) 2009 Peter Ross 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * This file is part of FFmpeg. 7cabdff1aSopenharmony_ci * 8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 12cabdff1aSopenharmony_ci * 13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16cabdff1aSopenharmony_ci * Lesser General Public License for more details. 17cabdff1aSopenharmony_ci * 18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21cabdff1aSopenharmony_ci */ 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ci/** 24cabdff1aSopenharmony_ci * @file 25cabdff1aSopenharmony_ci * Core Audio Format demuxer 26cabdff1aSopenharmony_ci */ 27cabdff1aSopenharmony_ci 28cabdff1aSopenharmony_ci#include <inttypes.h> 29cabdff1aSopenharmony_ci 30cabdff1aSopenharmony_ci#include "avformat.h" 31cabdff1aSopenharmony_ci#include "demux.h" 32cabdff1aSopenharmony_ci#include "internal.h" 33cabdff1aSopenharmony_ci#include "isom.h" 34cabdff1aSopenharmony_ci#include "mov_chan.h" 35cabdff1aSopenharmony_ci#include "libavcodec/flac.h" 36cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 37cabdff1aSopenharmony_ci#include "libavutil/intfloat.h" 38cabdff1aSopenharmony_ci#include "libavutil/dict.h" 39cabdff1aSopenharmony_ci#include "caf.h" 40cabdff1aSopenharmony_ci 41cabdff1aSopenharmony_citypedef struct CafContext { 42cabdff1aSopenharmony_ci int bytes_per_packet; ///< bytes in a packet, or 0 if variable 43cabdff1aSopenharmony_ci int frames_per_packet; ///< frames in a packet, or 0 if variable 44cabdff1aSopenharmony_ci int64_t num_bytes; ///< total number of bytes in stream 45cabdff1aSopenharmony_ci 46cabdff1aSopenharmony_ci int64_t packet_cnt; ///< packet counter 47cabdff1aSopenharmony_ci int64_t frame_cnt; ///< frame counter 48cabdff1aSopenharmony_ci 49cabdff1aSopenharmony_ci int64_t data_start; ///< data start position, in bytes 50cabdff1aSopenharmony_ci int64_t data_size; ///< raw data size, in bytes 51cabdff1aSopenharmony_ci} CafContext; 52cabdff1aSopenharmony_ci 53cabdff1aSopenharmony_cistatic int probe(const AVProbeData *p) 54cabdff1aSopenharmony_ci{ 55cabdff1aSopenharmony_ci if (AV_RB32(p->buf) == MKBETAG('c','a','f','f') && AV_RB16(&p->buf[4]) == 1) 56cabdff1aSopenharmony_ci return AVPROBE_SCORE_MAX; 57cabdff1aSopenharmony_ci return 0; 58cabdff1aSopenharmony_ci} 59cabdff1aSopenharmony_ci 60cabdff1aSopenharmony_ci/** Read audio description chunk */ 61cabdff1aSopenharmony_cistatic int read_desc_chunk(AVFormatContext *s) 62cabdff1aSopenharmony_ci{ 63cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 64cabdff1aSopenharmony_ci CafContext *caf = s->priv_data; 65cabdff1aSopenharmony_ci AVStream *st; 66cabdff1aSopenharmony_ci int flags; 67cabdff1aSopenharmony_ci 68cabdff1aSopenharmony_ci /* new audio stream */ 69cabdff1aSopenharmony_ci st = avformat_new_stream(s, NULL); 70cabdff1aSopenharmony_ci if (!st) 71cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 72cabdff1aSopenharmony_ci 73cabdff1aSopenharmony_ci /* parse format description */ 74cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; 75cabdff1aSopenharmony_ci st->codecpar->sample_rate = av_clipd(av_int2double(avio_rb64(pb)), 0, INT_MAX); 76cabdff1aSopenharmony_ci st->codecpar->codec_tag = avio_rl32(pb); 77cabdff1aSopenharmony_ci flags = avio_rb32(pb); 78cabdff1aSopenharmony_ci caf->bytes_per_packet = avio_rb32(pb); 79cabdff1aSopenharmony_ci st->codecpar->block_align = caf->bytes_per_packet; 80cabdff1aSopenharmony_ci caf->frames_per_packet = avio_rb32(pb); 81cabdff1aSopenharmony_ci st->codecpar->ch_layout.nb_channels = avio_rb32(pb); 82cabdff1aSopenharmony_ci st->codecpar->bits_per_coded_sample = avio_rb32(pb); 83cabdff1aSopenharmony_ci 84cabdff1aSopenharmony_ci if (caf->bytes_per_packet < 0 || caf->frames_per_packet < 0 || st->codecpar->ch_layout.nb_channels < 0) 85cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 86cabdff1aSopenharmony_ci 87cabdff1aSopenharmony_ci /* calculate bit rate for constant size packets */ 88cabdff1aSopenharmony_ci if (caf->frames_per_packet > 0 && caf->bytes_per_packet > 0) { 89cabdff1aSopenharmony_ci st->codecpar->bit_rate = (uint64_t)st->codecpar->sample_rate * (uint64_t)caf->bytes_per_packet * 8 90cabdff1aSopenharmony_ci / (uint64_t)caf->frames_per_packet; 91cabdff1aSopenharmony_ci } else { 92cabdff1aSopenharmony_ci st->codecpar->bit_rate = 0; 93cabdff1aSopenharmony_ci } 94cabdff1aSopenharmony_ci 95cabdff1aSopenharmony_ci /* determine codec */ 96cabdff1aSopenharmony_ci if (st->codecpar->codec_tag == MKTAG('l','p','c','m')) 97cabdff1aSopenharmony_ci st->codecpar->codec_id = ff_mov_get_lpcm_codec_id(st->codecpar->bits_per_coded_sample, (flags ^ 0x2) | 0x4); 98cabdff1aSopenharmony_ci else 99cabdff1aSopenharmony_ci st->codecpar->codec_id = ff_codec_get_id(ff_codec_caf_tags, st->codecpar->codec_tag); 100cabdff1aSopenharmony_ci return 0; 101cabdff1aSopenharmony_ci} 102cabdff1aSopenharmony_ci 103cabdff1aSopenharmony_ci/** Read magic cookie chunk */ 104cabdff1aSopenharmony_cistatic int read_kuki_chunk(AVFormatContext *s, int64_t size) 105cabdff1aSopenharmony_ci{ 106cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 107cabdff1aSopenharmony_ci AVStream *st = s->streams[0]; 108cabdff1aSopenharmony_ci int ret; 109cabdff1aSopenharmony_ci 110cabdff1aSopenharmony_ci if (size < 0 || size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) 111cabdff1aSopenharmony_ci return -1; 112cabdff1aSopenharmony_ci 113cabdff1aSopenharmony_ci if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { 114cabdff1aSopenharmony_ci /* The magic cookie format for AAC is an mp4 esds atom. 115cabdff1aSopenharmony_ci The lavc AAC decoder requires the data from the codec specific 116cabdff1aSopenharmony_ci description as extradata input. */ 117cabdff1aSopenharmony_ci int strt, skip; 118cabdff1aSopenharmony_ci 119cabdff1aSopenharmony_ci strt = avio_tell(pb); 120cabdff1aSopenharmony_ci ff_mov_read_esds(s, pb); 121cabdff1aSopenharmony_ci skip = size - (avio_tell(pb) - strt); 122cabdff1aSopenharmony_ci if (skip < 0 || !st->codecpar->extradata || 123cabdff1aSopenharmony_ci st->codecpar->codec_id != AV_CODEC_ID_AAC) { 124cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "invalid AAC magic cookie\n"); 125cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 126cabdff1aSopenharmony_ci } 127cabdff1aSopenharmony_ci avio_skip(pb, skip); 128cabdff1aSopenharmony_ci } else if (st->codecpar->codec_id == AV_CODEC_ID_ALAC) { 129cabdff1aSopenharmony_ci#define ALAC_PREAMBLE 12 130cabdff1aSopenharmony_ci#define ALAC_HEADER 36 131cabdff1aSopenharmony_ci#define ALAC_NEW_KUKI 24 132cabdff1aSopenharmony_ci uint8_t preamble[12]; 133cabdff1aSopenharmony_ci if (size < ALAC_NEW_KUKI) { 134cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "invalid ALAC magic cookie\n"); 135cabdff1aSopenharmony_ci avio_skip(pb, size); 136cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 137cabdff1aSopenharmony_ci } 138cabdff1aSopenharmony_ci if (avio_read(pb, preamble, ALAC_PREAMBLE) != ALAC_PREAMBLE) { 139cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "failed to read preamble\n"); 140cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 141cabdff1aSopenharmony_ci } 142cabdff1aSopenharmony_ci 143cabdff1aSopenharmony_ci if ((ret = ff_alloc_extradata(st->codecpar, ALAC_HEADER)) < 0) 144cabdff1aSopenharmony_ci return ret; 145cabdff1aSopenharmony_ci 146cabdff1aSopenharmony_ci /* For the old style cookie, we skip 12 bytes, then read 36 bytes. 147cabdff1aSopenharmony_ci * The new style cookie only contains the last 24 bytes of what was 148cabdff1aSopenharmony_ci * 36 bytes in the old style cookie, so we fabricate the first 12 bytes 149cabdff1aSopenharmony_ci * in that case to maintain compatibility. */ 150cabdff1aSopenharmony_ci if (!memcmp(&preamble[4], "frmaalac", 8)) { 151cabdff1aSopenharmony_ci if (size < ALAC_PREAMBLE + ALAC_HEADER) { 152cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "invalid ALAC magic cookie\n"); 153cabdff1aSopenharmony_ci av_freep(&st->codecpar->extradata); 154cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 155cabdff1aSopenharmony_ci } 156cabdff1aSopenharmony_ci if (avio_read(pb, st->codecpar->extradata, ALAC_HEADER) != ALAC_HEADER) { 157cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "failed to read kuki header\n"); 158cabdff1aSopenharmony_ci av_freep(&st->codecpar->extradata); 159cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 160cabdff1aSopenharmony_ci } 161cabdff1aSopenharmony_ci avio_skip(pb, size - ALAC_PREAMBLE - ALAC_HEADER); 162cabdff1aSopenharmony_ci } else { 163cabdff1aSopenharmony_ci AV_WB32(st->codecpar->extradata, 36); 164cabdff1aSopenharmony_ci memcpy(&st->codecpar->extradata[4], "alac", 4); 165cabdff1aSopenharmony_ci AV_WB32(&st->codecpar->extradata[8], 0); 166cabdff1aSopenharmony_ci memcpy(&st->codecpar->extradata[12], preamble, 12); 167cabdff1aSopenharmony_ci if (avio_read(pb, &st->codecpar->extradata[24], ALAC_NEW_KUKI - 12) != ALAC_NEW_KUKI - 12) { 168cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "failed to read new kuki header\n"); 169cabdff1aSopenharmony_ci av_freep(&st->codecpar->extradata); 170cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 171cabdff1aSopenharmony_ci } 172cabdff1aSopenharmony_ci avio_skip(pb, size - ALAC_NEW_KUKI); 173cabdff1aSopenharmony_ci } 174cabdff1aSopenharmony_ci } else if (st->codecpar->codec_id == AV_CODEC_ID_FLAC) { 175cabdff1aSopenharmony_ci int last, type, flac_metadata_size; 176cabdff1aSopenharmony_ci uint8_t buf[4]; 177cabdff1aSopenharmony_ci /* The magic cookie format for FLAC consists mostly of an mp4 dfLa atom. */ 178cabdff1aSopenharmony_ci if (size < (16 + FLAC_STREAMINFO_SIZE)) { 179cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "invalid FLAC magic cookie\n"); 180cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 181cabdff1aSopenharmony_ci } 182cabdff1aSopenharmony_ci /* Check cookie version. */ 183cabdff1aSopenharmony_ci if (avio_r8(pb) != 0) { 184cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "unknown FLAC magic cookie\n"); 185cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 186cabdff1aSopenharmony_ci } 187cabdff1aSopenharmony_ci avio_rb24(pb); /* Flags */ 188cabdff1aSopenharmony_ci /* read dfLa fourcc */ 189cabdff1aSopenharmony_ci if (avio_read(pb, buf, 4) != 4) { 190cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "failed to read FLAC magic cookie\n"); 191cabdff1aSopenharmony_ci return pb->error < 0 ? pb->error : AVERROR_INVALIDDATA; 192cabdff1aSopenharmony_ci } 193cabdff1aSopenharmony_ci if (memcmp(buf, "dfLa", 4)) { 194cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "invalid FLAC magic cookie\n"); 195cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 196cabdff1aSopenharmony_ci } 197cabdff1aSopenharmony_ci /* Check dfLa version. */ 198cabdff1aSopenharmony_ci if (avio_r8(pb) != 0) { 199cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "unknown dfLa version\n"); 200cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 201cabdff1aSopenharmony_ci } 202cabdff1aSopenharmony_ci avio_rb24(pb); /* Flags */ 203cabdff1aSopenharmony_ci if (avio_read(pb, buf, sizeof(buf)) != sizeof(buf)) { 204cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "failed to read FLAC metadata block header\n"); 205cabdff1aSopenharmony_ci return pb->error < 0 ? pb->error : AVERROR_INVALIDDATA; 206cabdff1aSopenharmony_ci } 207cabdff1aSopenharmony_ci flac_parse_block_header(buf, &last, &type, &flac_metadata_size); 208cabdff1aSopenharmony_ci if (type != FLAC_METADATA_TYPE_STREAMINFO || flac_metadata_size != FLAC_STREAMINFO_SIZE) { 209cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "STREAMINFO must be first FLACMetadataBlock\n"); 210cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 211cabdff1aSopenharmony_ci } 212cabdff1aSopenharmony_ci ret = ff_get_extradata(s, st->codecpar, pb, FLAC_STREAMINFO_SIZE); 213cabdff1aSopenharmony_ci if (ret < 0) 214cabdff1aSopenharmony_ci return ret; 215cabdff1aSopenharmony_ci if (!last) 216cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, "non-STREAMINFO FLACMetadataBlock(s) ignored\n"); 217cabdff1aSopenharmony_ci } else if (st->codecpar->codec_id == AV_CODEC_ID_OPUS) { 218cabdff1aSopenharmony_ci // The data layout for Opus is currently unknown, so we do not export 219cabdff1aSopenharmony_ci // extradata at all. Multichannel streams are not supported. 220cabdff1aSopenharmony_ci if (st->codecpar->ch_layout.nb_channels > 2) { 221cabdff1aSopenharmony_ci avpriv_request_sample(s, "multichannel Opus in CAF"); 222cabdff1aSopenharmony_ci return AVERROR_PATCHWELCOME; 223cabdff1aSopenharmony_ci } 224cabdff1aSopenharmony_ci avio_skip(pb, size); 225cabdff1aSopenharmony_ci } else if ((ret = ff_get_extradata(s, st->codecpar, pb, size)) < 0) { 226cabdff1aSopenharmony_ci return ret; 227cabdff1aSopenharmony_ci } 228cabdff1aSopenharmony_ci 229cabdff1aSopenharmony_ci return 0; 230cabdff1aSopenharmony_ci} 231cabdff1aSopenharmony_ci 232cabdff1aSopenharmony_ci/** Read packet table chunk */ 233cabdff1aSopenharmony_cistatic int read_pakt_chunk(AVFormatContext *s, int64_t size) 234cabdff1aSopenharmony_ci{ 235cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 236cabdff1aSopenharmony_ci AVStream *st = s->streams[0]; 237cabdff1aSopenharmony_ci CafContext *caf = s->priv_data; 238cabdff1aSopenharmony_ci int64_t pos = 0, ccount, num_packets; 239cabdff1aSopenharmony_ci int i; 240cabdff1aSopenharmony_ci int ret; 241cabdff1aSopenharmony_ci 242cabdff1aSopenharmony_ci ccount = avio_tell(pb); 243cabdff1aSopenharmony_ci 244cabdff1aSopenharmony_ci num_packets = avio_rb64(pb); 245cabdff1aSopenharmony_ci if (num_packets < 0 || INT32_MAX / sizeof(AVIndexEntry) < num_packets) 246cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 247cabdff1aSopenharmony_ci 248cabdff1aSopenharmony_ci st->nb_frames = avio_rb64(pb); /* valid frames */ 249cabdff1aSopenharmony_ci st->nb_frames += avio_rb32(pb); /* priming frames */ 250cabdff1aSopenharmony_ci st->nb_frames += avio_rb32(pb); /* remainder frames */ 251cabdff1aSopenharmony_ci 252cabdff1aSopenharmony_ci if (caf->bytes_per_packet > 0 && caf->frames_per_packet > 0) { 253cabdff1aSopenharmony_ci st->duration = caf->frames_per_packet * num_packets; 254cabdff1aSopenharmony_ci pos = caf-> bytes_per_packet * num_packets; 255cabdff1aSopenharmony_ci } else { 256cabdff1aSopenharmony_ci st->duration = 0; 257cabdff1aSopenharmony_ci for (i = 0; i < num_packets; i++) { 258cabdff1aSopenharmony_ci if (avio_feof(pb)) 259cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 260cabdff1aSopenharmony_ci ret = av_add_index_entry(s->streams[0], pos, st->duration, 0, 0, AVINDEX_KEYFRAME); 261cabdff1aSopenharmony_ci if (ret < 0) 262cabdff1aSopenharmony_ci return ret; 263cabdff1aSopenharmony_ci pos += caf->bytes_per_packet ? caf->bytes_per_packet : ff_mp4_read_descr_len(pb); 264cabdff1aSopenharmony_ci st->duration += caf->frames_per_packet ? caf->frames_per_packet : ff_mp4_read_descr_len(pb); 265cabdff1aSopenharmony_ci } 266cabdff1aSopenharmony_ci } 267cabdff1aSopenharmony_ci 268cabdff1aSopenharmony_ci if (avio_tell(pb) - ccount > size) { 269cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "error reading packet table\n"); 270cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 271cabdff1aSopenharmony_ci } 272cabdff1aSopenharmony_ci avio_seek(pb, ccount + size, SEEK_SET); 273cabdff1aSopenharmony_ci 274cabdff1aSopenharmony_ci caf->num_bytes = pos; 275cabdff1aSopenharmony_ci return 0; 276cabdff1aSopenharmony_ci} 277cabdff1aSopenharmony_ci 278cabdff1aSopenharmony_ci/** Read information chunk */ 279cabdff1aSopenharmony_cistatic void read_info_chunk(AVFormatContext *s, int64_t size) 280cabdff1aSopenharmony_ci{ 281cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 282cabdff1aSopenharmony_ci unsigned int i; 283cabdff1aSopenharmony_ci unsigned int nb_entries = avio_rb32(pb); 284cabdff1aSopenharmony_ci for (i = 0; i < nb_entries && !avio_feof(pb); i++) { 285cabdff1aSopenharmony_ci char key[32]; 286cabdff1aSopenharmony_ci char value[1024]; 287cabdff1aSopenharmony_ci avio_get_str(pb, INT_MAX, key, sizeof(key)); 288cabdff1aSopenharmony_ci avio_get_str(pb, INT_MAX, value, sizeof(value)); 289cabdff1aSopenharmony_ci if (!*key) 290cabdff1aSopenharmony_ci continue; 291cabdff1aSopenharmony_ci av_dict_set(&s->metadata, key, value, 0); 292cabdff1aSopenharmony_ci } 293cabdff1aSopenharmony_ci} 294cabdff1aSopenharmony_ci 295cabdff1aSopenharmony_cistatic int read_header(AVFormatContext *s) 296cabdff1aSopenharmony_ci{ 297cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 298cabdff1aSopenharmony_ci CafContext *caf = s->priv_data; 299cabdff1aSopenharmony_ci AVStream *st; 300cabdff1aSopenharmony_ci uint32_t tag = 0; 301cabdff1aSopenharmony_ci int found_data, ret; 302cabdff1aSopenharmony_ci int64_t size, pos; 303cabdff1aSopenharmony_ci 304cabdff1aSopenharmony_ci avio_skip(pb, 8); /* magic, version, file flags */ 305cabdff1aSopenharmony_ci 306cabdff1aSopenharmony_ci /* audio description chunk */ 307cabdff1aSopenharmony_ci if (avio_rb32(pb) != MKBETAG('d','e','s','c')) { 308cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "desc chunk not present\n"); 309cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 310cabdff1aSopenharmony_ci } 311cabdff1aSopenharmony_ci size = avio_rb64(pb); 312cabdff1aSopenharmony_ci if (size != 32) 313cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 314cabdff1aSopenharmony_ci 315cabdff1aSopenharmony_ci ret = read_desc_chunk(s); 316cabdff1aSopenharmony_ci if (ret) 317cabdff1aSopenharmony_ci return ret; 318cabdff1aSopenharmony_ci st = s->streams[0]; 319cabdff1aSopenharmony_ci 320cabdff1aSopenharmony_ci /* parse each chunk */ 321cabdff1aSopenharmony_ci found_data = 0; 322cabdff1aSopenharmony_ci while (!avio_feof(pb)) { 323cabdff1aSopenharmony_ci 324cabdff1aSopenharmony_ci /* stop at data chunk if seeking is not supported or 325cabdff1aSopenharmony_ci data chunk size is unknown */ 326cabdff1aSopenharmony_ci if (found_data && (caf->data_size < 0 || !(pb->seekable & AVIO_SEEKABLE_NORMAL))) 327cabdff1aSopenharmony_ci break; 328cabdff1aSopenharmony_ci 329cabdff1aSopenharmony_ci tag = avio_rb32(pb); 330cabdff1aSopenharmony_ci size = avio_rb64(pb); 331cabdff1aSopenharmony_ci pos = avio_tell(pb); 332cabdff1aSopenharmony_ci if (avio_feof(pb)) 333cabdff1aSopenharmony_ci break; 334cabdff1aSopenharmony_ci 335cabdff1aSopenharmony_ci switch (tag) { 336cabdff1aSopenharmony_ci case MKBETAG('d','a','t','a'): 337cabdff1aSopenharmony_ci avio_skip(pb, 4); /* edit count */ 338cabdff1aSopenharmony_ci caf->data_start = avio_tell(pb); 339cabdff1aSopenharmony_ci caf->data_size = size < 0 ? -1 : size - 4; 340cabdff1aSopenharmony_ci if (caf->data_size > 0 && (pb->seekable & AVIO_SEEKABLE_NORMAL)) 341cabdff1aSopenharmony_ci avio_skip(pb, caf->data_size); 342cabdff1aSopenharmony_ci found_data = 1; 343cabdff1aSopenharmony_ci break; 344cabdff1aSopenharmony_ci 345cabdff1aSopenharmony_ci case MKBETAG('c','h','a','n'): 346cabdff1aSopenharmony_ci if ((ret = ff_mov_read_chan(s, s->pb, st, size)) < 0) 347cabdff1aSopenharmony_ci return ret; 348cabdff1aSopenharmony_ci break; 349cabdff1aSopenharmony_ci 350cabdff1aSopenharmony_ci /* magic cookie chunk */ 351cabdff1aSopenharmony_ci case MKBETAG('k','u','k','i'): 352cabdff1aSopenharmony_ci if (read_kuki_chunk(s, size)) 353cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 354cabdff1aSopenharmony_ci break; 355cabdff1aSopenharmony_ci 356cabdff1aSopenharmony_ci /* packet table chunk */ 357cabdff1aSopenharmony_ci case MKBETAG('p','a','k','t'): 358cabdff1aSopenharmony_ci if (read_pakt_chunk(s, size)) 359cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 360cabdff1aSopenharmony_ci break; 361cabdff1aSopenharmony_ci 362cabdff1aSopenharmony_ci case MKBETAG('i','n','f','o'): 363cabdff1aSopenharmony_ci read_info_chunk(s, size); 364cabdff1aSopenharmony_ci break; 365cabdff1aSopenharmony_ci 366cabdff1aSopenharmony_ci default: 367cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, 368cabdff1aSopenharmony_ci "skipping CAF chunk: %08"PRIX32" (%s), size %"PRId64"\n", 369cabdff1aSopenharmony_ci tag, av_fourcc2str(av_bswap32(tag)), size); 370cabdff1aSopenharmony_ci case MKBETAG('f','r','e','e'): 371cabdff1aSopenharmony_ci if (size < 0 && found_data) 372cabdff1aSopenharmony_ci goto found_data; 373cabdff1aSopenharmony_ci if (size < 0) 374cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 375cabdff1aSopenharmony_ci break; 376cabdff1aSopenharmony_ci } 377cabdff1aSopenharmony_ci 378cabdff1aSopenharmony_ci if (size > 0 && (pb->seekable & AVIO_SEEKABLE_NORMAL)) { 379cabdff1aSopenharmony_ci if (pos > INT64_MAX - size) 380cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 381cabdff1aSopenharmony_ci avio_seek(pb, pos + size, SEEK_SET); 382cabdff1aSopenharmony_ci } 383cabdff1aSopenharmony_ci } 384cabdff1aSopenharmony_ci 385cabdff1aSopenharmony_ci if (!found_data) 386cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 387cabdff1aSopenharmony_ci 388cabdff1aSopenharmony_cifound_data: 389cabdff1aSopenharmony_ci if (caf->bytes_per_packet > 0 && caf->frames_per_packet > 0) { 390cabdff1aSopenharmony_ci if (caf->data_size > 0 && caf->data_size / caf->bytes_per_packet < INT64_MAX / caf->frames_per_packet) 391cabdff1aSopenharmony_ci st->nb_frames = (caf->data_size / caf->bytes_per_packet) * caf->frames_per_packet; 392cabdff1aSopenharmony_ci } else if (ffstream(st)->nb_index_entries && st->duration > 0) { 393cabdff1aSopenharmony_ci if (st->codecpar->sample_rate && caf->data_size / st->duration > INT64_MAX / st->codecpar->sample_rate / 8) { 394cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Overflow during bit rate calculation %d * 8 * %"PRId64"\n", 395cabdff1aSopenharmony_ci st->codecpar->sample_rate, caf->data_size / st->duration); 396cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 397cabdff1aSopenharmony_ci } 398cabdff1aSopenharmony_ci st->codecpar->bit_rate = st->codecpar->sample_rate * 8LL * 399cabdff1aSopenharmony_ci (caf->data_size / st->duration); 400cabdff1aSopenharmony_ci } else { 401cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Missing packet table. It is required when " 402cabdff1aSopenharmony_ci "block size or frame size are variable.\n"); 403cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 404cabdff1aSopenharmony_ci } 405cabdff1aSopenharmony_ci 406cabdff1aSopenharmony_ci avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); 407cabdff1aSopenharmony_ci st->start_time = 0; 408cabdff1aSopenharmony_ci 409cabdff1aSopenharmony_ci /* position the stream at the start of data */ 410cabdff1aSopenharmony_ci if (caf->data_size >= 0) 411cabdff1aSopenharmony_ci avio_seek(pb, caf->data_start, SEEK_SET); 412cabdff1aSopenharmony_ci 413cabdff1aSopenharmony_ci return 0; 414cabdff1aSopenharmony_ci} 415cabdff1aSopenharmony_ci 416cabdff1aSopenharmony_ci#define CAF_MAX_PKT_SIZE 4096 417cabdff1aSopenharmony_ci 418cabdff1aSopenharmony_cistatic int read_packet(AVFormatContext *s, AVPacket *pkt) 419cabdff1aSopenharmony_ci{ 420cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 421cabdff1aSopenharmony_ci AVStream *st = s->streams[0]; 422cabdff1aSopenharmony_ci FFStream *const sti = ffstream(st); 423cabdff1aSopenharmony_ci CafContext *caf = s->priv_data; 424cabdff1aSopenharmony_ci int res, pkt_size = 0, pkt_frames = 0; 425cabdff1aSopenharmony_ci int64_t left = CAF_MAX_PKT_SIZE; 426cabdff1aSopenharmony_ci 427cabdff1aSopenharmony_ci if (avio_feof(pb)) 428cabdff1aSopenharmony_ci return AVERROR_EOF; 429cabdff1aSopenharmony_ci 430cabdff1aSopenharmony_ci /* don't read past end of data chunk */ 431cabdff1aSopenharmony_ci if (caf->data_size > 0) { 432cabdff1aSopenharmony_ci left = (caf->data_start + caf->data_size) - avio_tell(pb); 433cabdff1aSopenharmony_ci if (!left) 434cabdff1aSopenharmony_ci return AVERROR_EOF; 435cabdff1aSopenharmony_ci if (left < 0) 436cabdff1aSopenharmony_ci return AVERROR(EIO); 437cabdff1aSopenharmony_ci } 438cabdff1aSopenharmony_ci 439cabdff1aSopenharmony_ci pkt_frames = caf->frames_per_packet; 440cabdff1aSopenharmony_ci pkt_size = caf->bytes_per_packet; 441cabdff1aSopenharmony_ci 442cabdff1aSopenharmony_ci if (pkt_size > 0 && pkt_frames == 1) { 443cabdff1aSopenharmony_ci pkt_size = (CAF_MAX_PKT_SIZE / pkt_size) * pkt_size; 444cabdff1aSopenharmony_ci pkt_size = FFMIN(pkt_size, left); 445cabdff1aSopenharmony_ci pkt_frames = pkt_size / caf->bytes_per_packet; 446cabdff1aSopenharmony_ci } else if (sti->nb_index_entries) { 447cabdff1aSopenharmony_ci if (caf->packet_cnt < sti->nb_index_entries - 1) { 448cabdff1aSopenharmony_ci pkt_size = sti->index_entries[caf->packet_cnt + 1].pos - sti->index_entries[caf->packet_cnt].pos; 449cabdff1aSopenharmony_ci pkt_frames = sti->index_entries[caf->packet_cnt + 1].timestamp - sti->index_entries[caf->packet_cnt].timestamp; 450cabdff1aSopenharmony_ci } else if (caf->packet_cnt == sti->nb_index_entries - 1) { 451cabdff1aSopenharmony_ci pkt_size = caf->num_bytes - sti->index_entries[caf->packet_cnt].pos; 452cabdff1aSopenharmony_ci pkt_frames = st->duration - sti->index_entries[caf->packet_cnt].timestamp; 453cabdff1aSopenharmony_ci } else { 454cabdff1aSopenharmony_ci return AVERROR(EIO); 455cabdff1aSopenharmony_ci } 456cabdff1aSopenharmony_ci } 457cabdff1aSopenharmony_ci 458cabdff1aSopenharmony_ci if (pkt_size == 0 || pkt_frames == 0 || pkt_size > left) 459cabdff1aSopenharmony_ci return AVERROR(EIO); 460cabdff1aSopenharmony_ci 461cabdff1aSopenharmony_ci res = av_get_packet(pb, pkt, pkt_size); 462cabdff1aSopenharmony_ci if (res < 0) 463cabdff1aSopenharmony_ci return res; 464cabdff1aSopenharmony_ci 465cabdff1aSopenharmony_ci pkt->size = res; 466cabdff1aSopenharmony_ci pkt->stream_index = 0; 467cabdff1aSopenharmony_ci pkt->dts = pkt->pts = caf->frame_cnt; 468cabdff1aSopenharmony_ci 469cabdff1aSopenharmony_ci caf->packet_cnt++; 470cabdff1aSopenharmony_ci caf->frame_cnt += pkt_frames; 471cabdff1aSopenharmony_ci 472cabdff1aSopenharmony_ci return 0; 473cabdff1aSopenharmony_ci} 474cabdff1aSopenharmony_ci 475cabdff1aSopenharmony_cistatic int read_seek(AVFormatContext *s, int stream_index, 476cabdff1aSopenharmony_ci int64_t timestamp, int flags) 477cabdff1aSopenharmony_ci{ 478cabdff1aSopenharmony_ci AVStream *st = s->streams[0]; 479cabdff1aSopenharmony_ci FFStream *const sti = ffstream(st); 480cabdff1aSopenharmony_ci CafContext *caf = s->priv_data; 481cabdff1aSopenharmony_ci int64_t pos, packet_cnt, frame_cnt; 482cabdff1aSopenharmony_ci 483cabdff1aSopenharmony_ci timestamp = FFMAX(timestamp, 0); 484cabdff1aSopenharmony_ci 485cabdff1aSopenharmony_ci if (caf->frames_per_packet > 0 && caf->bytes_per_packet > 0) { 486cabdff1aSopenharmony_ci /* calculate new byte position based on target frame position */ 487cabdff1aSopenharmony_ci pos = caf->bytes_per_packet * (timestamp / caf->frames_per_packet); 488cabdff1aSopenharmony_ci if (caf->data_size > 0) 489cabdff1aSopenharmony_ci pos = FFMIN(pos, caf->data_size); 490cabdff1aSopenharmony_ci packet_cnt = pos / caf->bytes_per_packet; 491cabdff1aSopenharmony_ci frame_cnt = caf->frames_per_packet * packet_cnt; 492cabdff1aSopenharmony_ci } else if (sti->nb_index_entries) { 493cabdff1aSopenharmony_ci packet_cnt = av_index_search_timestamp(st, timestamp, flags); 494cabdff1aSopenharmony_ci frame_cnt = sti->index_entries[packet_cnt].timestamp; 495cabdff1aSopenharmony_ci pos = sti->index_entries[packet_cnt].pos; 496cabdff1aSopenharmony_ci } else { 497cabdff1aSopenharmony_ci return -1; 498cabdff1aSopenharmony_ci } 499cabdff1aSopenharmony_ci 500cabdff1aSopenharmony_ci if (avio_seek(s->pb, pos + caf->data_start, SEEK_SET) < 0) 501cabdff1aSopenharmony_ci return -1; 502cabdff1aSopenharmony_ci 503cabdff1aSopenharmony_ci caf->packet_cnt = packet_cnt; 504cabdff1aSopenharmony_ci caf->frame_cnt = frame_cnt; 505cabdff1aSopenharmony_ci 506cabdff1aSopenharmony_ci return 0; 507cabdff1aSopenharmony_ci} 508cabdff1aSopenharmony_ci 509cabdff1aSopenharmony_ciconst AVInputFormat ff_caf_demuxer = { 510cabdff1aSopenharmony_ci .name = "caf", 511cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("Apple CAF (Core Audio Format)"), 512cabdff1aSopenharmony_ci .priv_data_size = sizeof(CafContext), 513cabdff1aSopenharmony_ci .read_probe = probe, 514cabdff1aSopenharmony_ci .read_header = read_header, 515cabdff1aSopenharmony_ci .read_packet = read_packet, 516cabdff1aSopenharmony_ci .read_seek = read_seek, 517cabdff1aSopenharmony_ci .codec_tag = ff_caf_codec_tags_list, 518cabdff1aSopenharmony_ci}; 519