Based on a patch by Hacene Bouaroua. Co-authored-by: Hacene Bouaroua <hbouar...@freebox.fr> Signed-off-by: James Almer <jamr...@gmail.com> --- libavformat/avformat.h | 6 +++++ libavformat/isom.h | 1 + libavformat/mov.c | 54 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 57 insertions(+), 4 deletions(-)
diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 56c1c80289..a54aac0f3a 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -1082,6 +1082,12 @@ typedef struct AVStreamGroupTileGrid { * final image before presentation. */ int height; + + /** + * The angle in which the reconstructed image is rotated (in anti-clockwise + * direction) before presentation, in units of degrees. + */ + AVRational rotation; } AVStreamGroupTileGrid; /** diff --git a/libavformat/isom.h b/libavformat/isom.h index 4723397048..204addbab2 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -283,6 +283,7 @@ typedef struct HEIFItem { int64_t extent_offset; int width; int height; + int rotation; int type; int is_idat_relative; } HEIFItem; diff --git a/libavformat/mov.c b/libavformat/mov.c index a2333ac1fd..480e6c81a5 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -40,6 +40,7 @@ #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/dict.h" +#include "libavutil/display.h" #include "libavutil/mem.h" #include "libavutil/opt.h" #include "libavutil/aes.h" @@ -8929,6 +8930,27 @@ static int mov_read_ispe(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; } +static int mov_read_irot(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + int angle; + + angle = avio_r8(pb) & 0x3; + + av_log(c->fc, AV_LOG_TRACE, "irot: item_id %d, angle %u\n", + c->cur_item_id, angle); + + for (int i = 0; i < c->nb_heif_item; i++) { + if (c->heif_item[i].item_id == c->cur_item_id) { + // angle * 90 specifies the angle (in anti-clockwise direction) + // in units of degrees. + c->heif_item[i].rotation = angle * 90; + break; + } + } + + return 0; +} + static int mov_read_iprp(MOVContext *c, AVIOContext *pb, MOVAtom atom) { typedef struct MOVAtoms { @@ -9155,6 +9177,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('i','d','a','t'), mov_read_idat }, { MKTAG('i','r','e','f'), mov_read_iref }, { MKTAG('i','s','p','e'), mov_read_ispe }, +{ MKTAG('i','r','o','t'), mov_read_irot }, { MKTAG('i','p','r','p'), mov_read_iprp }, { MKTAG('i','i','n','f'), mov_read_iinf }, { MKTAG('a','m','v','e'), mov_read_amve }, /* ambient viewing environment box */ @@ -9857,8 +9880,12 @@ 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); - av_log(c->fc, AV_LOG_TRACE, "grid: grid_rows %d grid_cols %d output_width %d output_height %d\n", - tile_rows, tile_cols, tile_grid->width, tile_grid->height); + /* rotation */ + tile_grid->rotation = av_make_q(item->rotation, 1); + + av_log(c->fc, AV_LOG_TRACE, "grid: grid_rows %d grid_cols %d output_width %d output_height %d " + "rotation %f\n", + tile_rows, tile_cols, tile_grid->width, tile_grid->height, av_q2d(tile_grid->rotation)); avio_seek(s->pb, pos, SEEK_SET); @@ -9947,8 +9974,12 @@ static int read_image_iovl(AVFormatContext *s, const HEIFGrid *grid, tile_grid->coded_width = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb); tile_grid->height = tile_grid->coded_height = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb); - av_log(c->fc, AV_LOG_TRACE, "iovl: output_width %d, output_height %d\n", - tile_grid->width, tile_grid->height); + + /* rotation */ + tile_grid->rotation = av_make_q(item->rotation, 1); + + av_log(c->fc, AV_LOG_TRACE, "iovl: output_width %d, output_height %d, rotation %f\n", + tile_grid->width, tile_grid->height, av_q2d(tile_grid->rotation)); tile_grid->nb_tiles = grid->nb_tiles; tile_grid->offsets = av_malloc_array(tile_grid->nb_tiles, sizeof(*tile_grid->offsets)); @@ -10149,6 +10180,21 @@ static int mov_read_header(AVFormatContext *s) if (item->item_id == mov->primary_item_id) st->disposition |= AV_DISPOSITION_DEFAULT; + if (item->rotation) { + int32_t *matrix; + AVPacketSideData *sd = av_packet_side_data_new(&st->codecpar->coded_side_data, + &st->codecpar->nb_coded_side_data, + AV_PKT_DATA_DISPLAYMATRIX, + 9 * sizeof(*matrix), 0); + if (!sd) + return AVERROR(ENOMEM); + matrix = (int32_t*)sd->data; + + /* rotation is in the counter-clockwise direction whereas + * av_display_rotation_set() expects its argument to be + * oriented clockwise, so we need to negate it. */ + av_display_rotation_set(matrix, -item->rotation); + } mov_build_index(mov, st); } -- 2.46.0 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".