Re: [FFmpeg-devel] [PATCH 1/4 v3] avformat/mov: ignore item boxes for animated heif
On 1/31/2024 3:06 PM, Andreas Rheinhardt wrote: James Almer: Fixes a regression since d9fed9df2a, where the single animated stream would be exported twice as two independent streams. Signed-off-by: James Almer --- libavformat/isom.h | 1 + libavformat/mov.c | 147 ++--- 2 files changed, 99 insertions(+), 49 deletions(-) diff --git a/libavformat/isom.h b/libavformat/isom.h index 2cf456fee1..21caaac256 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -280,6 +280,7 @@ typedef struct MOVContext { int64_t duration; ///< duration of the longest track int found_moov; ///< 'moov' atom has been found int found_iloc; ///< 'iloc' atom has been found +int found_iinf; ///< 'iinf' atom has been found int found_mdat; ///< 'mdat' atom has been found int found_hdlr_mdta; ///< 'hdlr' atom with type 'mdta' has been found int trak_index; ///< Index of the current 'trak' diff --git a/libavformat/mov.c b/libavformat/mov.c index cf931d4594..af95e1f662 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -81,6 +81,7 @@ typedef struct MOVParseTableEntry { static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom); static int mov_read_mfra(MOVContext *c, AVIOContext *f); +static void mov_free_stream_context(AVFormatContext *s, AVStream *st); static int64_t add_ctts_entry(MOVCtts** ctts_data, unsigned int* ctts_count, unsigned int* allocated_size, int count, int duration); @@ -4644,6 +4645,23 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom) MOVStreamContext *sc; int ret; +if (c->found_iinf) { +// * For animated heif, if the iinf box showed up before the moov +// box, we need to clear all the streams read in the former. +for (int i = c->heif_info_size - 1; i >= 0; i--) { +HEIFItem *item = &c->heif_info[i]; + +if (!item->st) +continue; + +mov_free_stream_context(c->fc, item->st); +ff_remove_stream(c->fc, item->st); +} +av_freep(&c->heif_info); +c->heif_info_size = 0; +c->found_iinf = c->found_iloc = 0; +} + st = avformat_new_stream(c->fc, NULL); if (!st) return AVERROR(ENOMEM); st->id = -1; @@ -7773,8 +7791,9 @@ static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom) uint64_t base_offset, extent_offset, extent_length; uint8_t value; -if (c->found_iloc) { -av_log(c->fc, AV_LOG_INFO, "Duplicate iloc box found\n"); +if (c->found_moov) { +// * For animated heif, we don't care about the iloc box as all the +// necessary information can be found in the moov box. return 0; } @@ -7896,6 +7915,16 @@ static int mov_read_iinf(MOVContext *c, AVIOContext *pb, MOVAtom atom) int entry_count; int version, ret; +if (c->found_iinf) { +av_log(c->fc, AV_LOG_WARNING, "Duplicate iinf box found\n"); +return 0; +} +if (c->found_moov) { +// * For animated heif, we don't care about the iinf box as all the +// necessary information can be found in the moov box. +return 0; +} + version = avio_r8(pb); avio_rb24(pb); // flags. entry_count = version ? avio_rb32(pb) : avio_rb16(pb); @@ -7919,6 +7948,7 @@ static int mov_read_iinf(MOVContext *c, AVIOContext *pb, MOVAtom atom) return ret; } +c->found_iinf = 1; return 0; } @@ -7932,6 +7962,13 @@ static int mov_read_iref(MOVContext *c, AVIOContext *pb, MOVAtom atom) static int mov_read_ispe(MOVContext *c, AVIOContext *pb, MOVAtom atom) { uint32_t width, height; + +if (c->found_moov) { +// * For animated heif, we don't care about the ispe box as all the +// necessary information can be found in the moov box. +return 0; +} + avio_r8(pb); /* version */ avio_rb24(pb); /* flags */ width = avio_rb32(pb); @@ -7966,6 +8003,12 @@ static int mov_read_iprp(MOVContext *c, AVIOContext *pb, MOVAtom atom) int version, flags; int ret; +if (c->found_moov) { +// * For animated heif, we don't care about the iprp box as all the +// necessary information can be found in the moov box. +return 0; +} + a.size = avio_rb32(pb); a.type = avio_rl32(pb); @@ -8587,6 +8630,58 @@ static void mov_free_encryption_index(MOVEncryptionIndex **index) { av_freep(index); } +static void mov_free_stream_context(AVFormatContext *s, AVStream *st) +{ +MOVStreamContext *sc = st->priv_data; + +if (!sc) +return; + +av_freep(&sc->ctts_data); +for (int i = 0; i < sc->drefs_count; i++) { +av_freep(&sc->drefs[i].path); +av_freep(&sc->drefs[i].dir); +} +av_freep(&sc->drefs); + +
Re: [FFmpeg-devel] [PATCH 1/4 v3] avformat/mov: ignore item boxes for animated heif
James Almer: > Fixes a regression since d9fed9df2a, where the single animated stream would > be exported twice as two independent streams. > > Signed-off-by: James Almer > --- > libavformat/isom.h | 1 + > libavformat/mov.c | 147 ++--- > 2 files changed, 99 insertions(+), 49 deletions(-) > > diff --git a/libavformat/isom.h b/libavformat/isom.h > index 2cf456fee1..21caaac256 100644 > --- a/libavformat/isom.h > +++ b/libavformat/isom.h > @@ -280,6 +280,7 @@ typedef struct MOVContext { > int64_t duration; ///< duration of the longest track > int found_moov; ///< 'moov' atom has been found > int found_iloc; ///< 'iloc' atom has been found > +int found_iinf; ///< 'iinf' atom has been found > int found_mdat; ///< 'mdat' atom has been found > int found_hdlr_mdta; ///< 'hdlr' atom with type 'mdta' has been found > int trak_index; ///< Index of the current 'trak' > diff --git a/libavformat/mov.c b/libavformat/mov.c > index cf931d4594..af95e1f662 100644 > --- a/libavformat/mov.c > +++ b/libavformat/mov.c > @@ -81,6 +81,7 @@ typedef struct MOVParseTableEntry { > > static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom); > static int mov_read_mfra(MOVContext *c, AVIOContext *f); > +static void mov_free_stream_context(AVFormatContext *s, AVStream *st); > static int64_t add_ctts_entry(MOVCtts** ctts_data, unsigned int* ctts_count, > unsigned int* allocated_size, >int count, int duration); > > @@ -4644,6 +4645,23 @@ static int mov_read_trak(MOVContext *c, AVIOContext > *pb, MOVAtom atom) > MOVStreamContext *sc; > int ret; > > +if (c->found_iinf) { > +// * For animated heif, if the iinf box showed up before the moov > +// box, we need to clear all the streams read in the former. > +for (int i = c->heif_info_size - 1; i >= 0; i--) { > +HEIFItem *item = &c->heif_info[i]; > + > +if (!item->st) > +continue; > + > +mov_free_stream_context(c->fc, item->st); > +ff_remove_stream(c->fc, item->st); > +} > +av_freep(&c->heif_info); > +c->heif_info_size = 0; > +c->found_iinf = c->found_iloc = 0; > +} > + > st = avformat_new_stream(c->fc, NULL); > if (!st) return AVERROR(ENOMEM); > st->id = -1; > @@ -7773,8 +7791,9 @@ static int mov_read_iloc(MOVContext *c, AVIOContext > *pb, MOVAtom atom) > uint64_t base_offset, extent_offset, extent_length; > uint8_t value; > > -if (c->found_iloc) { > -av_log(c->fc, AV_LOG_INFO, "Duplicate iloc box found\n"); > +if (c->found_moov) { > +// * For animated heif, we don't care about the iloc box as all the > +// necessary information can be found in the moov box. > return 0; > } > > @@ -7896,6 +7915,16 @@ static int mov_read_iinf(MOVContext *c, AVIOContext > *pb, MOVAtom atom) > int entry_count; > int version, ret; > > +if (c->found_iinf) { > +av_log(c->fc, AV_LOG_WARNING, "Duplicate iinf box found\n"); > +return 0; > +} > +if (c->found_moov) { > +// * For animated heif, we don't care about the iinf box as all the > +// necessary information can be found in the moov box. > +return 0; > +} > + > version = avio_r8(pb); > avio_rb24(pb); // flags. > entry_count = version ? avio_rb32(pb) : avio_rb16(pb); > @@ -7919,6 +7948,7 @@ static int mov_read_iinf(MOVContext *c, AVIOContext > *pb, MOVAtom atom) > return ret; > } > > +c->found_iinf = 1; > return 0; > } > > @@ -7932,6 +7962,13 @@ static int mov_read_iref(MOVContext *c, AVIOContext > *pb, MOVAtom atom) > static int mov_read_ispe(MOVContext *c, AVIOContext *pb, MOVAtom atom) > { > uint32_t width, height; > + > +if (c->found_moov) { > +// * For animated heif, we don't care about the ispe box as all the > +// necessary information can be found in the moov box. > +return 0; > +} > + > avio_r8(pb); /* version */ > avio_rb24(pb); /* flags */ > width = avio_rb32(pb); > @@ -7966,6 +8003,12 @@ static int mov_read_iprp(MOVContext *c, AVIOContext > *pb, MOVAtom atom) > int version, flags; > int ret; > > +if (c->found_moov) { > +// * For animated heif, we don't care about the iprp box as all the > +// necessary information can be found in the moov box. > +return 0; > +} > + > a.size = avio_rb32(pb); > a.type = avio_rl32(pb); > > @@ -8587,6 +8630,58 @@ static void > mov_free_encryption_index(MOVEncryptionIndex **index) { > av_freep(index); > } > > +static void mov_free_stream_context(AVFormatContext *s, AVStream *st) > +{ > +MOVStreamContext *sc = st->priv_data; > + > +if (!sc) > +return; > + > +av_freep(&sc->ctts_dat
[FFmpeg-devel] [PATCH 1/4 v3] avformat/mov: ignore item boxes for animated heif
Fixes a regression since d9fed9df2a, where the single animated stream would be exported twice as two independent streams. Signed-off-by: James Almer --- libavformat/isom.h | 1 + libavformat/mov.c | 147 ++--- 2 files changed, 99 insertions(+), 49 deletions(-) diff --git a/libavformat/isom.h b/libavformat/isom.h index 2cf456fee1..21caaac256 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -280,6 +280,7 @@ typedef struct MOVContext { int64_t duration; ///< duration of the longest track int found_moov; ///< 'moov' atom has been found int found_iloc; ///< 'iloc' atom has been found +int found_iinf; ///< 'iinf' atom has been found int found_mdat; ///< 'mdat' atom has been found int found_hdlr_mdta; ///< 'hdlr' atom with type 'mdta' has been found int trak_index; ///< Index of the current 'trak' diff --git a/libavformat/mov.c b/libavformat/mov.c index cf931d4594..af95e1f662 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -81,6 +81,7 @@ typedef struct MOVParseTableEntry { static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom); static int mov_read_mfra(MOVContext *c, AVIOContext *f); +static void mov_free_stream_context(AVFormatContext *s, AVStream *st); static int64_t add_ctts_entry(MOVCtts** ctts_data, unsigned int* ctts_count, unsigned int* allocated_size, int count, int duration); @@ -4644,6 +4645,23 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom) MOVStreamContext *sc; int ret; +if (c->found_iinf) { +// * For animated heif, if the iinf box showed up before the moov +// box, we need to clear all the streams read in the former. +for (int i = c->heif_info_size - 1; i >= 0; i--) { +HEIFItem *item = &c->heif_info[i]; + +if (!item->st) +continue; + +mov_free_stream_context(c->fc, item->st); +ff_remove_stream(c->fc, item->st); +} +av_freep(&c->heif_info); +c->heif_info_size = 0; +c->found_iinf = c->found_iloc = 0; +} + st = avformat_new_stream(c->fc, NULL); if (!st) return AVERROR(ENOMEM); st->id = -1; @@ -7773,8 +7791,9 @@ static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom) uint64_t base_offset, extent_offset, extent_length; uint8_t value; -if (c->found_iloc) { -av_log(c->fc, AV_LOG_INFO, "Duplicate iloc box found\n"); +if (c->found_moov) { +// * For animated heif, we don't care about the iloc box as all the +// necessary information can be found in the moov box. return 0; } @@ -7896,6 +7915,16 @@ static int mov_read_iinf(MOVContext *c, AVIOContext *pb, MOVAtom atom) int entry_count; int version, ret; +if (c->found_iinf) { +av_log(c->fc, AV_LOG_WARNING, "Duplicate iinf box found\n"); +return 0; +} +if (c->found_moov) { +// * For animated heif, we don't care about the iinf box as all the +// necessary information can be found in the moov box. +return 0; +} + version = avio_r8(pb); avio_rb24(pb); // flags. entry_count = version ? avio_rb32(pb) : avio_rb16(pb); @@ -7919,6 +7948,7 @@ static int mov_read_iinf(MOVContext *c, AVIOContext *pb, MOVAtom atom) return ret; } +c->found_iinf = 1; return 0; } @@ -7932,6 +7962,13 @@ static int mov_read_iref(MOVContext *c, AVIOContext *pb, MOVAtom atom) static int mov_read_ispe(MOVContext *c, AVIOContext *pb, MOVAtom atom) { uint32_t width, height; + +if (c->found_moov) { +// * For animated heif, we don't care about the ispe box as all the +// necessary information can be found in the moov box. +return 0; +} + avio_r8(pb); /* version */ avio_rb24(pb); /* flags */ width = avio_rb32(pb); @@ -7966,6 +8003,12 @@ static int mov_read_iprp(MOVContext *c, AVIOContext *pb, MOVAtom atom) int version, flags; int ret; +if (c->found_moov) { +// * For animated heif, we don't care about the iprp box as all the +// necessary information can be found in the moov box. +return 0; +} + a.size = avio_rb32(pb); a.type = avio_rl32(pb); @@ -8587,6 +8630,58 @@ static void mov_free_encryption_index(MOVEncryptionIndex **index) { av_freep(index); } +static void mov_free_stream_context(AVFormatContext *s, AVStream *st) +{ +MOVStreamContext *sc = st->priv_data; + +if (!sc) +return; + +av_freep(&sc->ctts_data); +for (int i = 0; i < sc->drefs_count; i++) { +av_freep(&sc->drefs[i].path); +av_freep(&sc->drefs[i].dir); +} +av_freep(&sc->drefs); + +sc->drefs_count = 0; + +if (!sc->pb_is_copied) +ff_format_io_close(s, &sc->pb); + +sc->pb = NULL; +av_fr