diff mbox series

[FFmpeg-devel] avformat/mov: get heif image rotation from irot box

Message ID 20240925001446.1905-1-jamrial@gmail.com
State New
Headers show
Series [FFmpeg-devel] avformat/mov: get heif image rotation from irot box | expand

Checks

Context Check Description
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

James Almer Sept. 25, 2024, 12:14 a.m. UTC
Based on a patch by Hacene Bouaroua.

Co-authored-by: Hacene Bouaroua <hbouaroua@freebox.fr>
Signed-off-by: James Almer <jamrial@gmail.com>
---
 libavformat/avformat.h |  6 +++++
 libavformat/isom.h     |  1 +
 libavformat/mov.c      | 54 ++++++++++++++++++++++++++++++++++++++----
 3 files changed, 57 insertions(+), 4 deletions(-)

Comments

James Almer Sept. 27, 2024, 3:47 p.m. UTC | #1
On 9/24/2024 9:14 PM, James Almer wrote:
> Based on a patch by Hacene Bouaroua.
> 
> Co-authored-by: Hacene Bouaroua <hbouaroua@freebox.fr>
> Signed-off-by: James Almer <jamrial@gmail.com>
> ---
>   libavformat/avformat.h |  6 +++++
>   libavformat/isom.h     |  1 +
>   libavformat/mov.c      | 54 ++++++++++++++++++++++++++++++++++++++----
>   3 files changed, 57 insertions(+), 4 deletions(-)

Will apply (with version bump and APIChanges entry) soon.
Anton Khirnov Sept. 27, 2024, 4:43 p.m. UTC | #2
Quoting James Almer (2024-09-25 02:14:46)
> Based on a patch by Hacene Bouaroua.
> 
> Co-authored-by: Hacene Bouaroua <hbouaroua@freebox.fr>
> Signed-off-by: James Almer <jamrial@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;

Should it not be a display matrix rather than just an angle?
James Almer Sept. 27, 2024, 5:07 p.m. UTC | #3
On 9/27/2024 1:43 PM, Anton Khirnov wrote:
> Quoting James Almer (2024-09-25 02:14:46)
>> Based on a patch by Hacene Bouaroua.
>>
>> Co-authored-by: Hacene Bouaroua <hbouaroua@freebox.fr>
>> Signed-off-by: James Almer <jamrial@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;
> 
> Should it not be a display matrix rather than just an angle?

What's the benefit? There's av_display_rotation_set() for that.
Anton Khirnov Sept. 27, 2024, 5:08 p.m. UTC | #4
Quoting James Almer (2024-09-27 19:07:42)
> On 9/27/2024 1:43 PM, Anton Khirnov wrote:
> > Quoting James Almer (2024-09-25 02:14:46)
> >> Based on a patch by Hacene Bouaroua.
> >>
> >> Co-authored-by: Hacene Bouaroua <hbouaroua@freebox.fr>
> >> Signed-off-by: James Almer <jamrial@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;
> > 
> > Should it not be a display matrix rather than just an angle?
> 
> What's the benefit?

A consistent interface.
diff mbox series

Patch

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);
         }