| @@ -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) | |||
| @@ -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, | |||
| @@ -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); | |||