X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fcafdec.c;h=d97ca45ab8fe703ae6d088de89f97b389ecd8e93;hb=fe95a37144077d1f652088fcb25b2949e4a3da19;hp=7652d9e238597f1ca673b394d761f00c26a1d52d;hpb=8e789d244cc946bc350672eeb02453918b21a09f;p=ffmpeg diff --git a/libavformat/cafdec.c b/libavformat/cafdec.c index 7652d9e2385..d97ca45ab8f 100644 --- a/libavformat/cafdec.c +++ b/libavformat/cafdec.c @@ -48,7 +48,7 @@ typedef struct CafContext { 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; @@ -70,7 +70,7 @@ static int read_desc_chunk(AVFormatContext *s) /* 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); @@ -79,6 +79,9 @@ static int read_desc_chunk(AVFormatContext *s) 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 @@ -100,6 +103,7 @@ static int read_kuki_chunk(AVFormatContext *s, int64_t size) { AVIOContext *pb = s->pb; AVStream *st = s->streams[0]; + int ret; if (size < 0 || size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) return -1; @@ -134,9 +138,8 @@ static int read_kuki_chunk(AVFormatContext *s, int64_t size) 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 @@ -174,10 +177,8 @@ static int read_kuki_chunk(AVFormatContext *s, int64_t size) 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; @@ -191,6 +192,7 @@ static int read_pakt_chunk(AVFormatContext *s, int64_t size) CafContext *caf = s->priv_data; int64_t pos = 0, ccount, num_packets; int i; + int ret; ccount = avio_tell(pb); @@ -202,11 +204,20 @@ static int read_pakt_chunk(AVFormatContext *s, int64_t size) 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) { @@ -310,6 +321,8 @@ static int read_header(AVFormatContext *s) "skipping CAF chunk: %08"PRIX32" (%s), size %"PRId64"\n", tag, av_fourcc2str(av_bswap32(tag)), size); case MKBETAG('f','r','e','e'): + if (size < 0 && found_data) + goto found_data; if (size < 0) return AVERROR_INVALIDDATA; break; @@ -325,10 +338,11 @@ static int read_header(AVFormatContext *s) if (!found_data) return AVERROR_INVALIDDATA; +found_data: 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); @@ -381,13 +395,13 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) 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); } @@ -426,10 +440,10 @@ static int read_seek(AVFormatContext *s, int stream_index, 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; } @@ -451,5 +465,5 @@ AVInputFormat ff_caf_demuxer = { .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, };