diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c index 9ba136dd70..13f989b10f 100644 --- a/libavcodec/hevc.c +++ b/libavcodec/hevc.c @@ -25,6 +25,7 @@ #include "libavutil/attributes.h" #include "libavutil/common.h" +#include "libavutil/display.h" #include "libavutil/internal.h" #include "libavutil/md5.h" #include "libavutil/opt.h" @@ -2457,6 +2458,20 @@ static int set_side_data(HEVCContext *s) stereo->flags = AV_STEREO3D_FLAG_INVERT; } + if (s->sei_display_orientation_present && + (s->sei_anticlockwise_rotation || s->sei_hflip || s->sei_vflip)) { + double angle = s->sei_anticlockwise_rotation * 360 / (double) (1 << 16); + AVFrameSideData *rotation = av_frame_new_side_data(out, + AV_FRAME_DATA_DISPLAYMATRIX, + sizeof(int32_t) * 9); + if (!rotation) + return AVERROR(ENOMEM); + + av_display_rotation_set((int32_t *)rotation->data, angle); + av_display_matrix_flip((int32_t *)rotation->data, + s->sei_vflip, s->sei_hflip); + } + return 0; } diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h index 4b8bcf8614..978681b586 100644 --- a/libavcodec/hevc.h +++ b/libavcodec/hevc.h @@ -859,6 +859,11 @@ typedef struct HEVCContext { int frame_packing_arrangement_type; int content_interpretation_type; int quincunx_subsampling; + + /** display orientation */ + int sei_display_orientation_present; + int sei_anticlockwise_rotation; + int sei_hflip, sei_vflip; } HEVCContext; int ff_hevc_decode_short_term_rps(HEVCContext *s, ShortTermRPS *rps, diff --git a/libavcodec/hevc_sei.c b/libavcodec/hevc_sei.c index b011596599..978a0e3878 100644 --- a/libavcodec/hevc_sei.c +++ b/libavcodec/hevc_sei.c @@ -71,6 +71,21 @@ static void decode_nal_sei_frame_packing_arrangement(HEVCContext *s) skip_bits1(gb); // upsampled_aspect_ratio_flag } +static void decode_nal_sei_display_orientation(HEVCContext *s) +{ + GetBitContext *gb = &s->HEVClc.gb; + + s->sei_display_orientation_present = !get_bits1(gb); + + if (s->sei_display_orientation_present) { + s->sei_hflip = get_bits1(gb); // hor_flip + s->sei_vflip = get_bits1(gb); // ver_flip + + s->sei_anticlockwise_rotation = get_bits(gb, 16); + skip_bits1(gb); // display_orientation_persistence_flag + } +} + static int decode_nal_sei_message(HEVCContext *s) { GetBitContext *gb = &s->HEVClc.gb; @@ -94,6 +109,8 @@ static int decode_nal_sei_message(HEVCContext *s) decode_nal_sei_decoded_picture_hash(s); else if (payload_type == 45) decode_nal_sei_frame_packing_arrangement(s); + else if (payload_type == 47) + decode_nal_sei_display_orientation(s); else { av_log(s->avctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", payload_type); skip_bits(gb, 8 * payload_size);