diff options
author | James Almer <jamrial@gmail.com> | 2024-09-30 10:46:02 -0300 |
---|---|---|
committer | James Almer <jamrial@gmail.com> | 2024-10-02 12:38:24 -0300 |
commit | ba6eeb2c65e8d3fb33ce53aa63310e657389d4b8 (patch) | |
tree | 3c56c4e7dfee6b261a30b7173d5c70b0a0b297e1 | |
parent | 58c265d956f4ce2efb0004c398e2c1f030f9398a (diff) | |
download | ffmpeg-ba6eeb2c65e8d3fb33ce53aa63310e657389d4b8.tar.gz |
avformat/mov: parse colr boxes that reference tile grids
Signed-off-by: James Almer <jamrial@gmail.com>
-rw-r--r-- | libavformat/isom.h | 2 | ||||
-rw-r--r-- | libavformat/mov.c | 70 |
2 files changed, 61 insertions, 11 deletions
diff --git a/libavformat/isom.h b/libavformat/isom.h index 204addbab2..bc208772f9 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -286,6 +286,8 @@ typedef struct HEIFItem { int rotation; int type; int is_idat_relative; + uint8_t *icc_profile; + size_t icc_profile_size; } HEIFItem; typedef struct HEIFGrid { diff --git a/libavformat/mov.c b/libavformat/mov.c index 14e8dab2e6..33158ac4dd 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2031,13 +2031,17 @@ static int mov_read_pcmc(MOVContext *c, AVIOContext *pb, MOVAtom atom) static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom) { AVStream *st; + HEIFItem *item = NULL; char color_parameter_type[5] = { 0 }; uint16_t color_primaries, color_trc, color_matrix; int ret; st = get_curr_st(c); - if (!st) - return 0; + if (!st) { + item = heif_cur_item(c); + if (!item) + return 0; + } ret = ffio_read_size(pb, color_parameter_type, 4); if (ret < 0) @@ -2051,16 +2055,29 @@ static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom) } if (!strncmp(color_parameter_type, "prof", 4)) { - AVPacketSideData *sd = av_packet_side_data_new(&st->codecpar->coded_side_data, - &st->codecpar->nb_coded_side_data, - AV_PKT_DATA_ICC_PROFILE, - atom.size - 4, 0); - if (!sd) - return AVERROR(ENOMEM); - ret = ffio_read_size(pb, sd->data, atom.size - 4); + AVPacketSideData *sd; + uint8_t *icc_profile; + if (st) { + sd = av_packet_side_data_new(&st->codecpar->coded_side_data, + &st->codecpar->nb_coded_side_data, + AV_PKT_DATA_ICC_PROFILE, + atom.size - 4, 0); + if (!sd) + return AVERROR(ENOMEM); + icc_profile = sd->data; + } else { + av_freep(&item->icc_profile); + icc_profile = item->icc_profile = av_malloc(atom.size - 4); + if (!icc_profile) { + item->icc_profile_size = 0; + return AVERROR(ENOMEM); + } + item->icc_profile_size = atom.size - 4; + } + ret = ffio_read_size(pb, icc_profile, atom.size - 4); if (ret < 0) return ret; - } else { + } else if (st) { color_primaries = avio_rb16(pb); color_trc = avio_rb16(pb); color_matrix = avio_rb16(pb); @@ -9714,8 +9731,10 @@ static int mov_read_close(AVFormatContext *s) av_freep(&mov->aes_decrypt); av_freep(&mov->chapter_tracks); - for (i = 0; i < mov->nb_heif_item; i++) + for (i = 0; i < mov->nb_heif_item; i++) { av_freep(&mov->heif_item[i].name); + av_freep(&mov->heif_item[i].icc_profile); + } av_freep(&mov->heif_item); for (i = 0; i < mov->nb_heif_grid; i++) { av_freep(&mov->heif_grid[i].tile_id_list); @@ -9861,6 +9880,20 @@ fail: return ret; } +static int set_icc_profile_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data, + const HEIFItem *item) +{ + AVPacketSideData *sd = av_packet_side_data_new(coded_side_data, nb_coded_side_data, + AV_PKT_DATA_ICC_PROFILE, + item->icc_profile_size, 0); + if (!sd) + return AVERROR(ENOMEM); + + memcpy(sd->data, item->icc_profile, item->icc_profile_size); + + return 0; +} + static int set_display_matrix_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data, const HEIFItem *item) { @@ -9914,6 +9947,13 @@ static int read_image_grid(AVFormatContext *s, const HEIFGrid *grid, tile_grid->width = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb); tile_grid->height = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb); + /* ICC profile */ + if (item->icc_profile_size) { + int ret = set_icc_profile_from_item(&tile_grid->coded_side_data, + &tile_grid->nb_coded_side_data, item); + if (ret < 0) + return ret; + } /* rotation */ if (item->rotation) { int ret = set_display_matrix_from_item(&tile_grid->coded_side_data, @@ -10021,6 +10061,14 @@ static int read_image_iovl(AVFormatContext *s, const HEIFGrid *grid, return ret; } + /* ICC profile */ + if (item->icc_profile_size) { + int ret = set_icc_profile_from_item(&tile_grid->coded_side_data, + &tile_grid->nb_coded_side_data, item); + if (ret < 0) + return ret; + } + av_log(c->fc, AV_LOG_TRACE, "iovl: output_width %d, output_height %d\n", tile_grid->width, tile_grid->height); |