diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c index f00667c6ff..6b935b6dba 100644 --- a/libavcodec/hevc.c +++ b/libavcodec/hevc.c @@ -29,6 +29,7 @@ #include "libavutil/md5.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" +#include "libavutil/stereo3d.h" #include "bytestream.h" #include "cabac_functions.h" @@ -2347,6 +2348,41 @@ static void restore_tqb_pixels(HEVCContext *s) } } +static int set_side_data(HEVCContext *s) +{ + AVFrame *out = s->ref->frame; + + if (s->sei_frame_packing_present && + s->frame_packing_arrangement_type >= 3 && + s->frame_packing_arrangement_type <= 5 && + s->content_interpretation_type > 0 && + s->content_interpretation_type < 3) { + AVStereo3D *stereo = av_stereo3d_create_side_data(out); + if (!stereo) + return AVERROR(ENOMEM); + + switch (s->frame_packing_arrangement_type) { + case 3: + if (s->quincunx_subsampling) + stereo->type = AV_STEREO3D_SIDEBYSIDE_QUINCUNX; + else + stereo->type = AV_STEREO3D_SIDEBYSIDE; + break; + case 4: + stereo->type = AV_STEREO3D_TOPBOTTOM; + break; + case 5: + stereo->type = AV_STEREO3D_FRAMESEQUENCE; + break; + } + + if (s->content_interpretation_type == 2) + stereo->flags = AV_STEREO3D_FLAG_INVERT; + } + + return 0; +} + static int hevc_frame_start(HEVCContext *s) { HEVCLocalContext *lc = &s->HEVClc; @@ -2381,6 +2417,10 @@ static int hevc_frame_start(HEVCContext *s) goto fail; } + ret = set_side_data(s); + if (ret < 0) + goto fail; + av_frame_unref(s->output_frame); ret = ff_hevc_output_frame(s, s->output_frame, 0); if (ret < 0) diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h index ab95035dda..d19f3122f5 100644 --- a/libavcodec/hevc.h +++ b/libavcodec/hevc.h @@ -920,6 +920,12 @@ typedef struct HEVCContext { int nal_length_size; ///< Number of bytes used for nal length (1, 2 or 4) int nuh_layer_id; + + /** frame packing arrangement variables */ + int sei_frame_packing_present; + int frame_packing_arrangement_type; + int content_interpretation_type; + int quincunx_subsampling; } 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 1cf698bd9d..eed7b335f8 100644 --- a/libavcodec/hevc_sei.c +++ b/libavcodec/hevc_sei.c @@ -46,17 +46,17 @@ static void decode_nal_sei_decoded_picture_hash(HEVCContext *s) } } -static void decode_nal_sei_frame_packing_arrangement(HEVCLocalContext *lc) +static void decode_nal_sei_frame_packing_arrangement(HEVCContext *s) { - GetBitContext *gb = &lc->gb; - int cancel, type, quincunx; + GetBitContext *gb = &s->HEVClc.gb; + int cancel, type, quincunx, content; get_ue_golomb(gb); // frame_packing_arrangement_id cancel = get_bits1(gb); // frame_packing_cancel_flag if (cancel == 0) { type = get_bits(gb, 7); // frame_packing_arrangement_type quincunx = get_bits1(gb); // quincunx_sampling_flag - skip_bits(gb, 6); // content_interpretation_type + content = get_bits(gb, 6); // content_interpretation_type // the following skips spatial_flipping_flag frame0_flipped_flag // field_views_flag current_frame_is_frame0_flag @@ -69,6 +69,11 @@ static void decode_nal_sei_frame_packing_arrangement(HEVCLocalContext *lc) skip_bits1(gb); // frame_packing_arrangement_persistance_flag } skip_bits1(gb); // upsampled_aspect_ratio_flag + + s->sei_frame_packing_present = (cancel == 0); + s->frame_packing_arrangement_type = type; + s->content_interpretation_type = content; + s->quincunx_subsampling = quincunx; } static int decode_nal_sei_message(HEVCContext *s) @@ -93,7 +98,7 @@ static int decode_nal_sei_message(HEVCContext *s) if (payload_type == 256) decode_nal_sei_decoded_picture_hash(s); else if (payload_type == 45) - decode_nal_sei_frame_packing_arrangement(&s->HEVClc); + decode_nal_sei_frame_packing_arrangement(s); else { av_log(s->avctx, AV_LOG_DEBUG, "Skipped PREFIX SEI %d\n", payload_type); skip_bits(gb, 8 * payload_size);