int64_t data_size; ///< raw data size, in bytes
} CafContext;
-static int probe(AVProbeData *p)
+static int probe(const AVProbeData *p)
{
if (AV_RB32(p->buf) == MKBETAG('c','a','f','f') && AV_RB16(&p->buf[4]) == 1)
return AVPROBE_SCORE_MAX;
/* parse format description */
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
- st->codecpar->sample_rate = av_int2double(avio_rb64(pb));
+ st->codecpar->sample_rate = av_clipd(av_int2double(avio_rb64(pb)), 0, INT_MAX);
st->codecpar->codec_tag = avio_rl32(pb);
flags = avio_rb32(pb);
caf->bytes_per_packet = avio_rb32(pb);
st->codecpar->channels = avio_rb32(pb);
st->codecpar->bits_per_coded_sample = avio_rb32(pb);
+ if (caf->bytes_per_packet < 0 || caf->frames_per_packet < 0 || st->codecpar->channels < 0)
+ return AVERROR_INVALIDDATA;
+
/* calculate bit rate for constant size packets */
if (caf->frames_per_packet > 0 && caf->bytes_per_packet > 0) {
st->codecpar->bit_rate = (uint64_t)st->codecpar->sample_rate * (uint64_t)caf->bytes_per_packet * 8
{
AVIOContext *pb = s->pb;
AVStream *st = s->streams[0];
+ int ret;
if (size < 0 || size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
return -1;
return AVERROR_INVALIDDATA;
}
- av_freep(&st->codecpar->extradata);
- if (ff_alloc_extradata(st->codecpar, ALAC_HEADER))
- return AVERROR(ENOMEM);
+ if ((ret = ff_alloc_extradata(st->codecpar, ALAC_HEADER)) < 0)
+ return ret;
/* For the old style cookie, we skip 12 bytes, then read 36 bytes.
* The new style cookie only contains the last 24 bytes of what was
return AVERROR_PATCHWELCOME;
}
avio_skip(pb, size);
- } else {
- av_freep(&st->codecpar->extradata);
- if (ff_get_extradata(s, st->codecpar, pb, size) < 0)
- return AVERROR(ENOMEM);
+ } else if ((ret = ff_get_extradata(s, st->codecpar, pb, size)) < 0) {
+ return ret;
}
return 0;
CafContext *caf = s->priv_data;
int64_t pos = 0, ccount, num_packets;
int i;
+ int ret;
ccount = avio_tell(pb);
st->nb_frames += avio_rb32(pb); /* priming frames */
st->nb_frames += avio_rb32(pb); /* remainder frames */
- st->duration = 0;
- for (i = 0; i < num_packets; i++) {
- av_add_index_entry(s->streams[0], pos, st->duration, 0, 0, AVINDEX_KEYFRAME);
- pos += caf->bytes_per_packet ? caf->bytes_per_packet : ff_mp4_read_descr_len(pb);
- st->duration += caf->frames_per_packet ? caf->frames_per_packet : ff_mp4_read_descr_len(pb);
+ if (caf->bytes_per_packet > 0 && caf->frames_per_packet > 0) {
+ st->duration = caf->frames_per_packet * num_packets;
+ pos = caf-> bytes_per_packet * num_packets;
+ } else {
+ st->duration = 0;
+ for (i = 0; i < num_packets; i++) {
+ if (avio_feof(pb))
+ return AVERROR_INVALIDDATA;
+ ret = av_add_index_entry(s->streams[0], pos, st->duration, 0, 0, AVINDEX_KEYFRAME);
+ if (ret < 0)
+ return ret;
+ pos += caf->bytes_per_packet ? caf->bytes_per_packet : ff_mp4_read_descr_len(pb);
+ st->duration += caf->frames_per_packet ? caf->frames_per_packet : ff_mp4_read_descr_len(pb);
+ }
}
if (avio_tell(pb) - ccount > size) {
if (caf->bytes_per_packet > 0 && caf->frames_per_packet > 0) {
if (caf->data_size > 0)
st->nb_frames = (caf->data_size / caf->bytes_per_packet) * caf->frames_per_packet;
- } else if (st->nb_index_entries && st->duration > 0) {
+ } else if (st->internal->nb_index_entries && st->duration > 0) {
if (st->codecpar->sample_rate && caf->data_size / st->duration > INT64_MAX / st->codecpar->sample_rate / 8) {
av_log(s, AV_LOG_ERROR, "Overflow during bit rate calculation %d * 8 * %"PRId64"\n",
st->codecpar->sample_rate, caf->data_size / st->duration);
pkt_size = (CAF_MAX_PKT_SIZE / pkt_size) * pkt_size;
pkt_size = FFMIN(pkt_size, left);
pkt_frames = pkt_size / caf->bytes_per_packet;
- } else if (st->nb_index_entries) {
- if (caf->packet_cnt < st->nb_index_entries - 1) {
- pkt_size = st->index_entries[caf->packet_cnt + 1].pos - st->index_entries[caf->packet_cnt].pos;
- pkt_frames = st->index_entries[caf->packet_cnt + 1].timestamp - st->index_entries[caf->packet_cnt].timestamp;
- } else if (caf->packet_cnt == st->nb_index_entries - 1) {
- pkt_size = caf->num_bytes - st->index_entries[caf->packet_cnt].pos;
- pkt_frames = st->duration - st->index_entries[caf->packet_cnt].timestamp;
+ } else if (st->internal->nb_index_entries) {
+ if (caf->packet_cnt < st->internal->nb_index_entries - 1) {
+ pkt_size = st->internal->index_entries[caf->packet_cnt + 1].pos - st->internal->index_entries[caf->packet_cnt].pos;
+ pkt_frames = st->internal->index_entries[caf->packet_cnt + 1].timestamp - st->internal->index_entries[caf->packet_cnt].timestamp;
+ } else if (caf->packet_cnt == st->internal->nb_index_entries - 1) {
+ pkt_size = caf->num_bytes - st->internal->index_entries[caf->packet_cnt].pos;
+ pkt_frames = st->duration - st->internal->index_entries[caf->packet_cnt].timestamp;
} else {
return AVERROR(EIO);
}
pos = FFMIN(pos, caf->data_size);
packet_cnt = pos / caf->bytes_per_packet;
frame_cnt = caf->frames_per_packet * packet_cnt;
- } else if (st->nb_index_entries) {
+ } else if (st->internal->nb_index_entries) {
packet_cnt = av_index_search_timestamp(st, timestamp, flags);
- frame_cnt = st->index_entries[packet_cnt].timestamp;
- pos = st->index_entries[packet_cnt].pos;
+ frame_cnt = st->internal->index_entries[packet_cnt].timestamp;
+ pos = st->internal->index_entries[packet_cnt].pos;
} else {
return -1;
}
return 0;
}
-AVInputFormat ff_caf_demuxer = {
+const AVInputFormat ff_caf_demuxer = {
.name = "caf",
.long_name = NULL_IF_CONFIG_SMALL("Apple CAF (Core Audio Format)"),
.priv_data_size = sizeof(CafContext),
.read_header = read_header,
.read_packet = read_packet,
.read_seek = read_seek,
- .codec_tag = (const AVCodecTag* const []){ ff_codec_caf_tags, 0 },
+ .codec_tag = ff_caf_codec_tags_list,
};