| @@ -27,6 +27,7 @@ | |||||
| #include "libavutil/avassert.h" | #include "libavutil/avassert.h" | ||||
| #include "libavutil/imgutils.h" | #include "libavutil/imgutils.h" | ||||
| #include "libavutil/stereo3d.h" | |||||
| #include "internal.h" | #include "internal.h" | ||||
| #include "cabac.h" | #include "cabac.h" | ||||
| #include "cabac_functions.h" | #include "cabac_functions.h" | ||||
| @@ -2029,6 +2030,46 @@ static void decode_postinit(H264Context *h, int setup_finished) | |||||
| } | } | ||||
| } | } | ||||
| if (h->sei_frame_packing_present && | |||||
| h->frame_packing_arrangement_type >= 0 && | |||||
| h->frame_packing_arrangement_type <= 6 && | |||||
| h->content_interpretation_type > 0 && | |||||
| h->content_interpretation_type < 3) { | |||||
| AVStereo3D *stereo = av_stereo3d_create_side_data(&cur->f); | |||||
| if (!stereo) | |||||
| return; | |||||
| switch (h->frame_packing_arrangement_type) { | |||||
| case 0: | |||||
| stereo->type = AV_STEREO3D_CHECKERBOARD; | |||||
| break; | |||||
| case 1: | |||||
| stereo->type = AV_STEREO3D_LINES; | |||||
| break; | |||||
| case 2: | |||||
| stereo->type = AV_STEREO3D_COLUMNS; | |||||
| break; | |||||
| case 3: | |||||
| if (h->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; | |||||
| case 6: | |||||
| stereo->type = AV_STEREO3D_2D; | |||||
| break; | |||||
| } | |||||
| if (h->content_interpretation_type == 2) | |||||
| stereo->flags = AV_STEREO3D_FLAG_INVERT; | |||||
| } | |||||
| // FIXME do something with unavailable reference frames | // FIXME do something with unavailable reference frames | ||||
| /* Sort B-frames into display order */ | /* Sort B-frames into display order */ | ||||
| @@ -123,7 +123,8 @@ typedef enum { | |||||
| SEI_BUFFERING_PERIOD = 0, ///< buffering period (H.264, D.1.1) | SEI_BUFFERING_PERIOD = 0, ///< buffering period (H.264, D.1.1) | ||||
| SEI_TYPE_PIC_TIMING = 1, ///< picture timing | SEI_TYPE_PIC_TIMING = 1, ///< picture timing | ||||
| SEI_TYPE_USER_DATA_UNREGISTERED = 5, ///< unregistered user data | SEI_TYPE_USER_DATA_UNREGISTERED = 5, ///< unregistered user data | ||||
| SEI_TYPE_RECOVERY_POINT = 6 ///< recovery point (frame # to decoder sync) | |||||
| SEI_TYPE_RECOVERY_POINT = 6, ///< recovery point (frame # to decoder sync) | |||||
| SEI_TYPE_FRAME_PACKING = 45, ///< frame packing arrangement | |||||
| } SEI_Type; | } SEI_Type; | ||||
| /** | /** | ||||
| @@ -585,6 +586,14 @@ typedef struct H264Context { | |||||
| */ | */ | ||||
| int prev_interlaced_frame; | int prev_interlaced_frame; | ||||
| /** | |||||
| * frame_packing_arrangment SEI message | |||||
| */ | |||||
| int sei_frame_packing_present; | |||||
| int frame_packing_arrangement_type; | |||||
| int content_interpretation_type; | |||||
| int quincunx_subsampling; | |||||
| /** | /** | ||||
| * Bit set of clock types for fields/frames in picture timing SEI message. | * Bit set of clock types for fields/frames in picture timing SEI message. | ||||
| * For each found ct_type, appropriate bit is set (e.g., bit 1 for | * For each found ct_type, appropriate bit is set (e.g., bit 1 for | ||||
| @@ -42,6 +42,7 @@ void ff_h264_reset_sei(H264Context *h) | |||||
| h->sei_dpb_output_delay = 0; | h->sei_dpb_output_delay = 0; | ||||
| h->sei_cpb_removal_delay = -1; | h->sei_cpb_removal_delay = -1; | ||||
| h->sei_buffering_period_present = 0; | h->sei_buffering_period_present = 0; | ||||
| h->sei_frame_packing_present = 0; | |||||
| } | } | ||||
| static int decode_picture_timing(H264Context *h) | static int decode_picture_timing(H264Context *h) | ||||
| @@ -175,6 +176,40 @@ static int decode_buffering_period(H264Context *h) | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| static int decode_frame_packing_arrangement(H264Context *h) | |||||
| { | |||||
| int cancel; | |||||
| int quincunx = 0; | |||||
| int content = -1; | |||||
| int type = -1; | |||||
| get_ue_golomb(&h->gb); // frame_packing_arrangement_id | |||||
| cancel = get_bits1(&h->gb); // frame_packing_arrangement_cancel_flag | |||||
| if (cancel == 0) { | |||||
| type = get_bits(&h->gb, 7); // frame_packing_arrangement_type | |||||
| quincunx = get_bits1(&h->gb); // quincunx_sampling_flag | |||||
| content = get_bits(&h->gb, 6); // content_interpretation_type | |||||
| // the following skips: spatial_flipping_flag, frame0_flipped_flag, | |||||
| // field_views_flag, current_frame_is_frame0_flag, | |||||
| // frame0_self_contained_flag, frame1_self_contained_flag | |||||
| skip_bits(&h->gb, 6); | |||||
| if (quincunx == 0 && type != 5) | |||||
| skip_bits(&h->gb, 16); // frame[01]_grid_position_[xy] | |||||
| skip_bits(&h->gb, 8); // frame_packing_arrangement_reserved_byte | |||||
| get_ue_golomb(&h->gb); // frame_packing_arrangement_repetition_period | |||||
| } | |||||
| skip_bits1(&h->gb); // frame_packing_arrangement_extension_flag | |||||
| h->sei_frame_packing_present = (cancel == 0); | |||||
| h->frame_packing_arrangement_type = type; | |||||
| h->content_interpretation_type = content; | |||||
| h->quincunx_subsampling = quincunx; | |||||
| return 0; | |||||
| } | |||||
| int ff_h264_decode_sei(H264Context *h) | int ff_h264_decode_sei(H264Context *h) | ||||
| { | { | ||||
| while (get_bits_left(&h->gb) > 16) { | while (get_bits_left(&h->gb) > 16) { | ||||
| @@ -217,6 +252,11 @@ int ff_h264_decode_sei(H264Context *h) | |||||
| if (ret < 0) | if (ret < 0) | ||||
| return ret; | return ret; | ||||
| break; | break; | ||||
| case SEI_TYPE_FRAME_PACKING: | |||||
| ret = decode_frame_packing_arrangement(h); | |||||
| if (ret < 0) | |||||
| return ret; | |||||
| break; | |||||
| default: | default: | ||||
| av_log(h->avctx, AV_LOG_DEBUG, "unknown SEI type %d\n", type); | av_log(h->avctx, AV_LOG_DEBUG, "unknown SEI type %d\n", type); | ||||
| skip_bits(&h->gb, 8 * size); | skip_bits(&h->gb, 8 * size); | ||||