summaryrefslogtreecommitdiff
path: root/libavformat/mov.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavformat/mov.c')
-rw-r--r--libavformat/mov.c143
1 files changed, 86 insertions, 57 deletions
diff --git a/libavformat/mov.c b/libavformat/mov.c
index a09a762d91..6ee6ed0950 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -4698,6 +4698,69 @@ static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom)
return ret;
}
+static int avif_add_stream(MOVContext *c, int item_id)
+{
+ MOVStreamContext *sc;
+ AVStream *st;
+ int item_index = -1;
+ for (int i = 0; i < c->avif_info_size; i++)
+ if (c->avif_info[i].item_id == item_id) {
+ item_index = i;
+ break;
+ }
+ if (item_index < 0)
+ return AVERROR_INVALIDDATA;
+ st = avformat_new_stream(c->fc, NULL);
+ if (!st)
+ return AVERROR(ENOMEM);
+ st->id = c->fc->nb_streams;
+ sc = av_mallocz(sizeof(MOVStreamContext));
+ if (!sc)
+ return AVERROR(ENOMEM);
+
+ st->priv_data = sc;
+ st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+ st->codecpar->codec_id = AV_CODEC_ID_AV1;
+ sc->ffindex = st->index;
+ c->trak_index = st->index;
+ st->avg_frame_rate.num = st->avg_frame_rate.den = 1;
+ st->time_base.num = st->time_base.den = 1;
+ st->nb_frames = 1;
+ sc->time_scale = 1;
+ sc = st->priv_data;
+ sc->pb = c->fc->pb;
+ sc->pb_is_copied = 1;
+
+ // Populate the necessary fields used by mov_build_index.
+ sc->stsc_count = 1;
+ sc->stsc_data = av_malloc_array(1, sizeof(*sc->stsc_data));
+ if (!sc->stsc_data)
+ return AVERROR(ENOMEM);
+ sc->stsc_data[0].first = 1;
+ sc->stsc_data[0].count = 1;
+ sc->stsc_data[0].id = 1;
+ sc->chunk_count = 1;
+ sc->chunk_offsets = av_malloc_array(1, sizeof(*sc->chunk_offsets));
+ if (!sc->chunk_offsets)
+ return AVERROR(ENOMEM);
+ sc->sample_count = 1;
+ sc->sample_sizes = av_malloc_array(1, sizeof(*sc->sample_sizes));
+ if (!sc->sample_sizes)
+ return AVERROR(ENOMEM);
+ sc->stts_count = 1;
+ sc->stts_data = av_malloc_array(1, sizeof(*sc->stts_data));
+ if (!sc->stts_data)
+ return AVERROR(ENOMEM);
+ sc->stts_data[0].count = 1;
+ // Not used for still images. But needed by mov_build_index.
+ sc->stts_data[0].duration = 0;
+ sc->sample_sizes[0] = c->avif_info[item_index].extent_length;
+ sc->chunk_offsets[0] = c->avif_info[item_index].extent_offset;
+
+ mov_build_index(c, st);
+ return 0;
+}
+
static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{
while (atom.size > 8) {
@@ -4707,9 +4770,23 @@ static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
tag = avio_rl32(pb);
atom.size -= 4;
if (tag == MKTAG('h','d','l','r')) {
+ int ret;
avio_seek(pb, -8, SEEK_CUR);
atom.size += 8;
- return mov_read_default(c, pb, atom);
+ if ((ret = mov_read_default(c, pb, atom)) < 0)
+ return ret;
+ if (c->is_still_picture_avif) {
+ int ret;
+ // Add a stream for the YUV planes (primary item).
+ if ((ret = avif_add_stream(c, c->primary_item_id)) < 0)
+ return ret;
+ // For still AVIF images, the meta box contains all the
+ // necessary information that would generally be provided by the
+ // moov box. So simply mark that we have found the moov box so
+ // that parsing can continue.
+ c->found_moov = 1;
+ }
+ return ret;
}
}
return 0;
@@ -7478,8 +7555,6 @@ static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
int item_count, extent_count;
uint64_t base_offset, extent_offset, extent_length;
uint8_t value;
- AVStream *st;
- MOVStreamContext *sc;
if (!c->is_still_picture_avif) {
// * For non-avif, we simply ignore the iloc box.
@@ -7493,27 +7568,6 @@ static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
return 0;
}
- st = avformat_new_stream(c->fc, NULL);
- if (!st)
- return AVERROR(ENOMEM);
- st->id = c->fc->nb_streams;
- sc = av_mallocz(sizeof(MOVStreamContext));
- if (!sc)
- return AVERROR(ENOMEM);
-
- st->priv_data = sc;
- st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
- st->codecpar->codec_id = AV_CODEC_ID_AV1;
- sc->ffindex = st->index;
- c->trak_index = st->index;
- st->avg_frame_rate.num = st->avg_frame_rate.den = 1;
- st->time_base.num = st->time_base.den = 1;
- st->nb_frames = 1;
- sc->time_scale = 1;
- sc = st->priv_data;
- sc->pb = c->fc->pb;
- sc->pb_is_copied = 1;
-
version = avio_r8(pb);
avio_rb24(pb); // flags.
@@ -7529,34 +7583,17 @@ static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
}
item_count = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
- // Populate the necessary fields used by mov_build_index.
- sc->stsc_count = 1;
- sc->stsc_data = av_malloc_array(1, sizeof(*sc->stsc_data));
- if (!sc->stsc_data)
- return AVERROR(ENOMEM);
- sc->stsc_data[0].first = 1;
- sc->stsc_data[0].count = 1;
- sc->stsc_data[0].id = 1;
- sc->chunk_count = 1;
- sc->chunk_offsets = av_malloc_array(1, sizeof(*sc->chunk_offsets));
- if (!sc->chunk_offsets)
+ c->avif_info = av_malloc_array(item_count, sizeof(*c->avif_info));
+ if (!c->avif_info)
return AVERROR(ENOMEM);
- sc->sample_count = 1;
- sc->sample_sizes = av_malloc_array(1, sizeof(*sc->sample_sizes));
- if (!sc->sample_sizes)
- return AVERROR(ENOMEM);
- sc->stts_count = 1;
- sc->stts_data = av_malloc_array(1, sizeof(*sc->stts_data));
- if (!sc->stts_data)
- return AVERROR(ENOMEM);
- sc->stts_data[0].count = 1;
- // Not used for still images. But needed by mov_build_index.
- sc->stts_data[0].duration = 0;
+ c->avif_info_size = item_count;
for (int i = 0; i < item_count; i++) {
int item_id = (version < 2) ? avio_rb16(pb) : avio_rb32(pb);
if (avio_feof(pb))
return AVERROR_INVALIDDATA;
+ c->avif_info[i].item_id = item_id;
+
if (version > 0)
avio_rb16(pb); // construction_method.
avio_rb16(pb); // data_reference_index.
@@ -7572,20 +7609,11 @@ static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
if (rb_size(pb, &extent_offset, offset_size) < 0 ||
rb_size(pb, &extent_length, length_size) < 0)
return AVERROR_INVALIDDATA;
- if (item_id == c->primary_item_id) {
- sc->sample_sizes[0] = extent_length;
- sc->chunk_offsets[0] = base_offset + extent_offset;
- }
+ c->avif_info[i].extent_length = extent_length;
+ c->avif_info[i].extent_offset = base_offset + extent_offset;
}
}
- mov_build_index(c, st);
-
- // For still AVIF images, the iloc box contains all the necessary
- // information that would generally be provided by the moov box. So simply
- // mark that we have found the moov box so that parsing can continue.
- c->found_moov = 1;
-
return atom.size;
}
@@ -8189,6 +8217,7 @@ static int mov_read_close(AVFormatContext *s)
av_freep(&mov->aes_decrypt);
av_freep(&mov->chapter_tracks);
+ av_freep(&mov->avif_info);
return 0;
}