Based on a patch by Hacene Bouaroua. Fixes ticket #11171.
Unified · Split
| @@ -283,6 +283,7 @@ typedef struct HEIFItem { · 282 unmodified lines | |||
| 283 | int64_t extent_offset; | 283 | int64_t extent_offset; |
| 284 | int width; | 284 | int width; |
| 285 | int height; | 285 | int height; |
| 286 | int rotation; | ||
| 286 | int type; | 287 | int type; |
| 287 | int is_idat_relative; | 288 | int is_idat_relative; |
| 288 | } HEIFItem; | 289 | } HEIFItem; |
| @@ -40,6 +40,7 @@ · 39 unmodified lines | |||
| 40 | #include "libavutil/avassert.h" | 40 | #include "libavutil/avassert.h" |
| 41 | #include "libavutil/avstring.h" | 41 | #include "libavutil/avstring.h" |
| 42 | #include "libavutil/dict.h" | 42 | #include "libavutil/dict.h" |
| 43 | #include "libavutil/display.h" | ||
| 43 | #include "libavutil/mem.h" | 44 | #include "libavutil/mem.h" |
| 44 | #include "libavutil/opt.h" | 45 | #include "libavutil/opt.h" |
| 45 | #include "libavutil/aes.h" | 46 | #include "libavutil/aes.h" |
| @@ -8933,6 +8934,27 @@ static int mov_read_ispe(MOVContext *c, AVIOContext *pb, MOVAtom atom) · 8887 unmodified lines | |||
| 8933 | return 0; | 8934 | return 0; |
| 8934 | } | 8935 | } |
| 8935 | 8936 | ||
| 8937 | static int mov_read_irot(MOVContext *c, AVIOContext *pb, MOVAtom atom) | ||
| 8938 | { | ||
| 8939 | int angle; | ||
| 8940 | |||
| 8941 | angle = avio_r8(pb) & 0x3; | ||
| 8942 | |||
| 8943 | av_log(c->fc, AV_LOG_TRACE, "irot: item_id %d, angle %u\n", | ||
| 8944 | c->cur_item_id, angle); | ||
| 8945 | |||
| 8946 | for (int i = 0; i < c->nb_heif_item; i++) { | ||
| 8947 | if (c->heif_item[i].item_id == c->cur_item_id) { | ||
| 8948 | // angle * 90 specifies the angle (in anti-clockwise direction) | ||
| 8949 | // in units of degrees. | ||
| 8950 | c->heif_item[i].rotation = angle * 90; | ||
| 8951 | break; | ||
| 8952 | } | ||
| 8953 | } | ||
| 8954 | |||
| 8955 | return 0; | ||
| 8956 | } | ||
| 8957 | |||
| 8936 | static int mov_read_iprp(MOVContext *c, AVIOContext *pb, MOVAtom atom) | 8958 | static int mov_read_iprp(MOVContext *c, AVIOContext *pb, MOVAtom atom) |
| 8937 | { | 8959 | { |
| 8938 | typedef struct MOVAtoms { | 8960 | typedef struct MOVAtoms { |
| @@ -9159,6 +9181,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = { · 220 unmodified lines | |||
| 9159 | { MKTAG('i','d','a','t'), mov_read_idat }, | 9181 | { MKTAG('i','d','a','t'), mov_read_idat }, |
| 9160 | { MKTAG('i','r','e','f'), mov_read_iref }, | 9182 | { MKTAG('i','r','e','f'), mov_read_iref }, |
| 9161 | { MKTAG('i','s','p','e'), mov_read_ispe }, | 9183 | { MKTAG('i','s','p','e'), mov_read_ispe }, |
| 9184 | { MKTAG('i','r','o','t'), mov_read_irot }, | ||
| 9162 | { MKTAG('i','p','r','p'), mov_read_iprp }, | 9185 | { MKTAG('i','p','r','p'), mov_read_iprp }, |
| 9163 | { MKTAG('i','i','n','f'), mov_read_iinf }, | 9186 | { MKTAG('i','i','n','f'), mov_read_iinf }, |
| 9164 | { MKTAG('a','m','v','e'), mov_read_amve }, /* ambient viewing environment box */ | 9187 | { MKTAG('a','m','v','e'), mov_read_amve }, /* ambient viewing environment box */ |
| @@ -9828,6 +9851,26 @@ fail: · 663 unmodified lines | |||
| 9828 | return ret; | 9851 | return ret; |
| 9829 | } | 9852 | } |
| 9830 | 9853 | ||
| 9854 | static int set_display_matrix_from_item(AVPacketSideData **coded_side_data, int *nb_coded_side_data, | ||
| 9855 | const HEIFItem *item) | ||
| 9856 | { | ||
| 9857 | int32_t *matrix; | ||
| 9858 | AVPacketSideData *sd = av_packet_side_data_new(coded_side_data, | ||
| 9859 | nb_coded_side_data, | ||
| 9860 | AV_PKT_DATA_DISPLAYMATRIX, | ||
| 9861 | 9 * sizeof(*matrix), 0); | ||
| 9862 | if (!sd) | ||
| 9863 | return AVERROR(ENOMEM); | ||
| 9864 | |||
| 9865 | matrix = (int32_t*)sd->data; | ||
| 9866 | /* rotation is in the counter-clockwise direction whereas | ||
| 9867 | * av_display_rotation_set() expects its argument to be | ||
| 9868 | * oriented clockwise, so we need to negate it. */ | ||
| 9869 | av_display_rotation_set(matrix, -item->rotation); | ||
| 9870 | |||
| 9871 | return 0; | ||
| 9872 | } | ||
| 9873 | |||
| 9831 | static int read_image_grid(AVFormatContext *s, const HEIFGrid *grid, | 9874 | static int read_image_grid(AVFormatContext *s, const HEIFGrid *grid, |
| 9832 | AVStreamGroupTileGrid *tile_grid) | 9875 | AVStreamGroupTileGrid *tile_grid) |
| 9833 | { | 9876 | { |
| @@ -9861,6 +9904,14 @@ static int read_image_grid(AVFormatContext *s, const HEIFGrid *grid, · 27 unmodified lines | |||
| 9861 | tile_grid->width = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb); | 9904 | tile_grid->width = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb); |
| 9862 | tile_grid->height = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb); | 9905 | tile_grid->height = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb); |
| 9863 | 9906 | ||
| 9907 | /* rotation */ | ||
| 9908 | if (item->rotation) { | ||
| 9909 | int ret = set_display_matrix_from_item(&tile_grid->coded_side_data, | ||
| 9910 | &tile_grid->nb_coded_side_data, item); | ||
| 9911 | if (ret < 0) | ||
| 9912 | return ret; | ||
| 9913 | } | ||
| 9914 | |||
| 9864 | av_log(c->fc, AV_LOG_TRACE, "grid: grid_rows %d grid_cols %d output_width %d output_height %d\n", | 9915 | av_log(c->fc, AV_LOG_TRACE, "grid: grid_rows %d grid_cols %d output_width %d output_height %d\n", |
| 9865 | tile_rows, tile_cols, tile_grid->width, tile_grid->height); | 9916 | tile_rows, tile_cols, tile_grid->width, tile_grid->height); |
| 9866 | 9917 | ||
| @@ -9951,6 +10002,15 @@ static int read_image_iovl(AVFormatContext *s, const HEIFGrid *grid, · 84 unmodified lines | |||
| 9951 | tile_grid->coded_width = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb); | 10002 | tile_grid->coded_width = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb); |
| 9952 | tile_grid->height = | 10003 | tile_grid->height = |
| 9953 | tile_grid->coded_height = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb); | 10004 | tile_grid->coded_height = (flags & 1) ? avio_rb32(s->pb) : avio_rb16(s->pb); |
| 10005 | |||
| 10006 | /* rotation */ | ||
| 10007 | if (item->rotation) { | ||
| 10008 | int ret = set_display_matrix_from_item(&tile_grid->coded_side_data, | ||
| 10009 | &tile_grid->nb_coded_side_data, item); | ||
| 10010 | if (ret < 0) | ||
| 10011 | return ret; | ||
| 10012 | } | ||
| 10013 | |||
| 9954 | av_log(c->fc, AV_LOG_TRACE, "iovl: output_width %d, output_height %d\n", | 10014 | av_log(c->fc, AV_LOG_TRACE, "iovl: output_width %d, output_height %d\n", |
| 9955 | tile_grid->width, tile_grid->height); | 10015 | tile_grid->width, tile_grid->height); |
| 9956 | 10016 | ||
| @@ -10153,6 +10213,13 @@ static int mov_read_header(AVFormatContext *s) · 196 unmodified lines | |||
| 10153 | if (item->item_id == mov->primary_item_id) | 10213 | if (item->item_id == mov->primary_item_id) |
| 10154 | st->disposition |= AV_DISPOSITION_DEFAULT; | 10214 | st->disposition |= AV_DISPOSITION_DEFAULT; |
| 10155 | 10215 | ||
| 10216 | if (item->rotation) { | ||
| 10217 | int ret = set_display_matrix_from_item(&st->codecpar->coded_side_data, | ||
| 10218 | &st->codecpar->nb_coded_side_data, item); | ||
| 10219 | if (ret < 0) | ||
| 10220 | return ret; | ||
| 10221 | } | ||
| 10222 | |||
| 10156 | mov_build_index(mov, st); | 10223 | mov_build_index(mov, st); |
| 10157 | } | 10224 | } |
| 10158 | 10225 | ||