This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit 06af0fdbf72c917b80cffec4b06c49a5f882a512 Author: James Almer <[email protected]> AuthorDate: Fri Oct 9 15:15:41 2026 -0300 Commit: James Almer <[email protected]> CommitDate: Mon Oct 12 10:39:17 2026 -0300 avformat/mov: split parsing and applying Exif item metadata Signed-off-by: James Almer <[email protected]> --- libavformat/isom.h | 2 + libavformat/mov.c | 122 +++++++++++++++++++++++++++++++++-------------------- 2 files changed, 78 insertions(+), 46 deletions(-) diff --git a/libavformat/isom.h b/libavformat/isom.h index dad5acf961..97d41b567f 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -33,6 +33,7 @@ #include "libavutil/spherical.h" #include "libavutil/stereo3d.h" +#include "libavcodec/exif.h" #include "avio.h" #include "internal.h" #include "dv.h" @@ -312,6 +313,7 @@ typedef struct HEIFItem { int vflip; int type; int is_idat_relative; + AVExifMetadata ifd; uint8_t *icc_profile; size_t icc_profile_size; } HEIFItem; diff --git a/libavformat/mov.c b/libavformat/mov.c index 6d2f34ce00..9cec6255cd 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -10836,6 +10836,7 @@ static int mov_read_close(AVFormatContext *s) av_freep(&mov->heif_item[i]->name); av_freep(&mov->heif_item[i]->iref_list); av_freep(&mov->heif_item[i]->icc_profile); + av_exif_free(&mov->heif_item[i]->ifd); av_freep(&mov->heif_item[i]); } av_freep(&mov->heif_item); @@ -10986,6 +10987,38 @@ fail: return ret; } +static int set_exif_from_item(AVFormatContext *s, + AVPacketSideData **coded_side_data, int *nb_coded_side_data, + const HEIFItem *item) +{ + AVPacketSideData *sd; + const AVExifMetadata *ifd = &item->ifd; + AVBufferRef *buf = NULL; + int64_t offset; + int err; + + err = av_exif_write(s, ifd, &buf, AV_EXIF_T_OFF); + if (err < 0) + return err; + + offset = AV_RB32(buf->data) + 4; + if (offset >= buf->size) { + av_buffer_unref(&buf); + return AVERROR_INVALIDDATA; + } + sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data, + AV_PKT_DATA_EXIF, buf->size - offset, 0); + if (!sd) { + av_buffer_unref(&buf); + return AVERROR(ENOMEM); + } + memcpy(sd->data, buf->data + offset, buf->size - offset); + + av_buffer_unref(&buf); + + return 0; +} + static int set_icc_profile_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data, const HEIFItem *item) { @@ -11185,14 +11218,11 @@ fail: return ret; } -static int mov_parse_exif_item(AVFormatContext *s, - AVPacketSideData **coded_side_data, int *nb_coded_side_data, - const HEIFItem *ref) +static int mov_parse_exif_item(AVFormatContext *s, HEIFItem *item, const HEIFItem *ref) { MOVContext *c = s->priv_data; - AVPacketSideData *sd; - AVExifMetadata ifd = { 0 }; - AVBufferRef *buf; + AVExifMetadata *ifd = &item->ifd; + uint8_t *buf; int64_t offset = 0, pos = avio_tell(s->pb); unsigned orientation_id = av_exif_get_tag_id("Orientation"); int err; @@ -11209,7 +11239,7 @@ static int mov_parse_exif_item(AVFormatContext *s, offset = c->idat_offset; } - buf = av_buffer_alloc(ref->extent_length); + buf = av_malloc(ref->extent_length); if (!buf) return AVERROR(ENOMEM); @@ -11219,7 +11249,7 @@ static int mov_parse_exif_item(AVFormatContext *s, } avio_seek(s->pb, ref->extent_offset + offset, SEEK_SET); - err = avio_read(s->pb, buf->data, ref->extent_length); + err = avio_read(s->pb, buf, ref->extent_length); if (err != ref->extent_length) { if (err > 0) err = AVERROR_INVALIDDATA; @@ -11229,44 +11259,54 @@ static int mov_parse_exif_item(AVFormatContext *s, // HEIF spec states that Exif metadata is informative. The irot item property is // the normative source of rotation information. So we remove any Orientation tag // present in the Exif buffer. - err = av_exif_parse_buffer(s, buf->data, ref->extent_length, &ifd, AV_EXIF_T_OFF); + err = av_exif_parse_buffer(s, buf, ref->extent_length, ifd, AV_EXIF_T_OFF); if (err < 0) { av_log(s, AV_LOG_ERROR, "Unable to parse Exif metadata\n"); goto fail; } - err = av_exif_remove_entry(s, &ifd, orientation_id, 0); + err = av_exif_remove_entry(s, ifd, orientation_id, 0); if (err < 0) goto fail; - else if (!err) - goto finish; - av_buffer_unref(&buf); - err = av_exif_write(s, &ifd, &buf, AV_EXIF_T_OFF); + err = 0; +fail: + av_free(buf); if (err < 0) - goto fail; + av_exif_free(ifd); + avio_seek(s->pb, pos, SEEK_SET); -finish: - offset = AV_RB32(buf->data) + 4; - if (offset >= buf->size) { - err = AVERROR_INVALIDDATA; - goto fail; + return err; +} + +static int mov_apply_heif_item_references(AVFormatContext *s, HEIFItem *item, + AVPacketSideData **coded_side_data, + int *nb_coded_side_data) +{ + int err; + + /* exif */ + if (item->ifd.count) { + err = set_exif_from_item(s, coded_side_data, nb_coded_side_data, item); + if (err < 0) + return err; } - sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data, - AV_PKT_DATA_EXIF, buf->size - offset, 0); - if (!sd) { - err = AVERROR(ENOMEM); - goto fail; + + /* rotation */ + if (item->rotation || item->hflip || item->vflip) { + err = set_display_matrix_from_item(coded_side_data, nb_coded_side_data, item); + if (err < 0) + return err; } - memcpy(sd->data, buf->data + offset, buf->size - offset); - err = 0; -fail: - av_buffer_unref(&buf); - av_exif_free(&ifd); - avio_seek(s->pb, pos, SEEK_SET); + /* ICC profile */ + if (item->icc_profile_size) { + err = set_icc_profile_from_item(coded_side_data, nb_coded_side_data, item); + if (err < 0) + return err; + } - return err; + return 0; } static int mov_parse_heif_item_references(AVFormatContext *s, HEIFItem *item, @@ -11282,7 +11322,7 @@ static int mov_parse_heif_item_references(AVFormatContext *s, HEIFItem *item, av_assert0(ref); switch(ref->type) { case MKTAG('E','x','i','f'): - err = mov_parse_exif_item(s, coded_side_data, nb_coded_side_data, ref); + err = mov_parse_exif_item(s, item, ref); if (err < 0 && (s->error_recognition & AV_EF_EXPLODE)) return err; break; @@ -11291,19 +11331,9 @@ static int mov_parse_heif_item_references(AVFormatContext *s, HEIFItem *item, } } - /* rotation */ - if (item->rotation || item->hflip || item->vflip) { - err = set_display_matrix_from_item(coded_side_data, nb_coded_side_data, item); - if (err < 0) - return err; - } - - /* ICC profile */ - if (item->icc_profile_size) { - err = set_icc_profile_from_item(coded_side_data, nb_coded_side_data, item); - if (err < 0) - return err; - } + err = mov_apply_heif_item_references(s, item, coded_side_data, nb_coded_side_data); + if (err < 0) + return err; return 0; } -- To stop receiving notification emails like this one, please contact [email protected]. _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
