vlc | branch: master | Francois Cartegnie <[email protected]> | Tue Mar 14 12:20:41 2017 +0100| [9d5db4502a0dee44d90a19fe60048c147b897c49] | committer: Francois Cartegnie
packetizer: h264: decode and compute POC > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=9d5db4502a0dee44d90a19fe60048c147b897c49 --- modules/packetizer/h264_slice.c | 245 ++++++++++++++++++++++++++++++++++++++++ modules/packetizer/h264_slice.h | 29 +++++ 2 files changed, 274 insertions(+) diff --git a/modules/packetizer/h264_slice.c b/modules/packetizer/h264_slice.c index 8c583f9..1b14382 100644 --- a/modules/packetizer/h264_slice.c +++ b/modules/packetizer/h264_slice.c @@ -118,5 +118,250 @@ bool h264_decode_slice( const uint8_t *p_buffer, size_t i_buffer, p_slice->i_delta_pic_order_cnt1 = bs_read_se( &s ); } + if( p_pps->i_redundant_pic_present_flag ) + bs_read_ue( &s ); /* redudant_pic_count */ + + unsigned num_ref_idx_l01_active_minus1[2] = {0 , 0}; + + if( i_slice_type == 1 || i_slice_type == 6 ) /* B slices */ + bs_read1( &s ); /* direct_spatial_mv_pred_flag */ + if( i_slice_type == 0 || i_slice_type == 5 || + i_slice_type == 3 || i_slice_type == 8 || + i_slice_type == 1 || i_slice_type == 6 ) /* P SP B slices */ + { + if( bs_read1( &s ) ) /* num_ref_idx_active_override_flag */ + { + num_ref_idx_l01_active_minus1[0] = bs_read_ue( &s ); + if( i_slice_type == 1 || i_slice_type == 6 ) /* B slices */ + num_ref_idx_l01_active_minus1[1] = bs_read_ue( &s ); + } + } + + /* BELOW, Further processing up to assert MMCO 5 presence for POC */ + if( p_slice->i_nal_type == 5 || p_slice->i_nal_ref_idc == 0 ) + { + /* Early END, don't waste parsing below */ + p_slice->has_mmco5 = false; + return true; + } + + /* ref_pic_list_[mvc_]modification() */ + const bool b_mvc = (p_slice->i_nal_type == 20 || p_slice->i_nal_type == 21 ); + unsigned i = 0; + if( i_slice_type % 5 != 2 && i_slice_type % 5 != 4 ) + i++; + if( i_slice_type % 5 == 1 ) + i++; + + for( ; i>0; i-- ) + { + if( bs_read1( &s ) ) /* ref_pic_list_modification_flag_l{0,1} */ + { + uint32_t mod; + do + { + mod = bs_read_ue( &s ); + if( mod < 3 || ( b_mvc && (mod == 4 || mod == 5) ) ) + bs_read_ue( &s ); /* abs_diff_pic_num_minus1, long_term_pic_num, abs_diff_view_idx_min1 */ + } + while( mod != 3 && bs_remain( &s ) ); + } + } + + /* pred_weight_table() */ + if( ( p_pps->weighted_pred_flag && ( i_slice_type == 0 || i_slice_type == 5 || /* P, SP */ + i_slice_type == 3 || i_slice_type == 8 ) ) || + ( p_pps->weighted_bipred_idc == 1 && ( i_slice_type == 1 || i_slice_type == 6 ) /* B */ ) ) + { + bs_read_ue( &s ); /* luma_log2_weight_denom */ + if( !p_sps->b_separate_colour_planes_flag ) /* ChromaArrayType != 0 */ + bs_read_ue( &s ); /* chroma_log2_weight_denom */ + + const unsigned i_num_layers = ( i_slice_type % 5 == 1 ) ? 2 : 1; + for( unsigned j=0; j < i_num_layers; j++ ) + { + for( unsigned i=0; i<=num_ref_idx_l01_active_minus1[j]; i++ ) + { + if( bs_read1( &s ) ) /* luma_weight_l{0,1}_flag */ + { + bs_read_se( &s ); + bs_read_se( &s ); + } + if( !p_sps->b_separate_colour_planes_flag ) /* ChromaArrayType != 0 */ + { + if( bs_read1( &s ) ) /* chroma_weight_l{0,1}_flag */ + { + bs_read_se( &s ); + bs_read_se( &s ); + bs_read_se( &s ); + bs_read_se( &s ); + } + } + } + } + } + + /* dec_ref_pic_marking() */ + if( p_slice->i_nal_type != 5 ) /* IdrFlag */ + { + if( bs_read1( &s ) ) /* adaptive_ref_pic_marking_mode_flag */ + { + uint32_t mmco; + do + { + mmco = bs_read_ue( &s ); + if( mmco == 1 || mmco == 3 ) + bs_read_ue( &s ); /* diff_pics_minus1 */ + if( mmco == 2 ) + bs_read_ue( &s ); /* long_term_pic_num */ + if( mmco == 3 || mmco == 6 ) + bs_read_ue( &s ); /* long_term_frame_idx */ + if( mmco == 4 ) + bs_read_ue( &s ); /* max_long_term_frame_idx_plus1 */ + if( mmco == 5 ) + { + p_slice->has_mmco5 = true; + break; /* Early END */ + } + } + while( mmco > 0 ); + } + } + + /* If you need to store anything else than MMCO presence above, care of "Early END" cases */ + return true; } + + +void h264_compute_poc( const h264_sequence_parameter_set_t *p_sps, + const h264_slice_t *p_slice, poc_context_t *p_ctx, + int *p_PictureOrderCount, int *p_tFOC, int *p_bFOC ) +{ + *p_tFOC = *p_bFOC = 0; + + if( p_sps->i_pic_order_cnt_type == 0 ) + { + unsigned maxPocLSB = 1U << (p_sps->i_log2_max_pic_order_cnt_lsb + 4); + + /* POC reference */ + if( p_slice->i_nal_type == H264_NAL_SLICE_IDR ) + { + p_ctx->prevPicOrderCnt.lsb = 0; + p_ctx->prevPicOrderCnt.msb = 0; + } + else if( p_ctx->prevRefPictureHasMMCO5 ) + { + p_ctx->prevPicOrderCnt.msb = 0; + if( !p_ctx->prevRefPictureIsBottomField ) + p_ctx->prevPicOrderCnt.lsb = p_ctx->prevRefPictureTFOC; + else + p_ctx->prevPicOrderCnt.lsb = 0; + } + + /* 8.2.1.1 */ + int pocMSB = p_ctx->prevPicOrderCnt.msb; + int64_t orderDiff = p_slice->i_pic_order_cnt_lsb - p_ctx->prevPicOrderCnt.lsb; + if( orderDiff < 0 && -orderDiff >= maxPocLSB / 2 ) + pocMSB += maxPocLSB; + else if( orderDiff > maxPocLSB / 2 ) + pocMSB -= maxPocLSB; + + *p_tFOC = *p_bFOC = pocMSB + p_slice->i_pic_order_cnt_lsb; + if( p_slice->i_field_pic_flag ) + *p_bFOC += p_slice->i_delta_pic_order_cnt_bottom; + + /* Save from ref picture */ + if( p_slice->i_nal_ref_idc /* Is reference */ ) + { + p_ctx->prevRefPictureIsBottomField = (p_slice->i_field_pic_flag && + p_slice->i_bottom_field_flag); + p_ctx->prevRefPictureHasMMCO5 = p_slice->has_mmco5; + p_ctx->prevRefPictureTFOC = *p_tFOC; + p_ctx->prevPicOrderCnt.lsb = p_slice->i_pic_order_cnt_lsb; + p_ctx->prevPicOrderCnt.msb = pocMSB; + } + } + else + { + unsigned maxFrameNum = 1 << (p_sps->i_log2_max_frame_num + 4); + unsigned frameNumOffset; + unsigned expectedPicOrderCnt = 0; + + if( p_slice->i_nal_type == H264_NAL_SLICE_IDR ) + frameNumOffset = 0; + else if( p_ctx->prevFrameNum > (unsigned) p_slice->i_frame_num ) + frameNumOffset = p_ctx->prevFrameNumOffset + maxFrameNum; + else + frameNumOffset = p_ctx->prevFrameNumOffset; + + if( p_sps->i_pic_order_cnt_type == 1 ) + { + unsigned absFrameNum; + + if( p_sps->i_num_ref_frames_in_pic_order_cnt_cycle > 0 ) + absFrameNum = frameNumOffset + p_slice->i_frame_num; + else + absFrameNum = 0; + + if( p_slice->i_nal_ref_idc == 0 && absFrameNum > 0 ) + absFrameNum--; + + if( absFrameNum > 0 ) + { + int32_t expectedDeltaPerPicOrderCntCycle = 0; + for( int i=0; i<p_sps->i_num_ref_frames_in_pic_order_cnt_cycle; i++ ) + expectedDeltaPerPicOrderCntCycle += p_sps->offset_for_ref_frame[i]; + + unsigned picOrderCntCycleCnt = 0; + unsigned frameNumInPicOrderCntCycle = 0; + if( p_sps->i_num_ref_frames_in_pic_order_cnt_cycle ) + { + picOrderCntCycleCnt = ( absFrameNum - 1 ) / p_sps->i_num_ref_frames_in_pic_order_cnt_cycle; + frameNumInPicOrderCntCycle = ( absFrameNum - 1 ) % p_sps->i_num_ref_frames_in_pic_order_cnt_cycle; + } + + expectedPicOrderCnt = picOrderCntCycleCnt * expectedDeltaPerPicOrderCntCycle; + for( unsigned i=0; i <= frameNumInPicOrderCntCycle; i++ ) + expectedPicOrderCnt = expectedPicOrderCnt + p_sps->offset_for_ref_frame[i]; + } + + if( p_slice->i_nal_ref_idc == 0 ) + expectedPicOrderCnt = expectedPicOrderCnt + p_sps->offset_for_non_ref_pic; + + *p_tFOC = expectedPicOrderCnt + p_slice->i_delta_pic_order_cnt0; + if( !p_slice->i_field_pic_flag ) + *p_bFOC = *p_tFOC + p_sps->offset_for_top_to_bottom_field + p_slice->i_delta_pic_order_cnt1; + else if( p_slice->i_bottom_field_flag ) + *p_bFOC = expectedPicOrderCnt + p_sps->offset_for_top_to_bottom_field + p_slice->i_delta_pic_order_cnt0; + } + else if( p_sps->i_pic_order_cnt_type == 2 ) + { + unsigned tempPicOrderCnt; + + if( p_slice->i_nal_type == H264_NAL_SLICE_IDR ) + tempPicOrderCnt = 0; + else if( p_slice->i_nal_ref_idc == 0 ) + tempPicOrderCnt = 2 * ( frameNumOffset + p_slice->i_frame_num ) - 1; + else + tempPicOrderCnt = 2 * ( frameNumOffset + p_slice->i_frame_num ); + + *p_bFOC = *p_tFOC = tempPicOrderCnt; + } + + p_ctx->prevFrameNum = p_slice->i_frame_num; + if( p_slice->has_mmco5 ) + p_ctx->prevFrameNumOffset = 0; + else + p_ctx->prevFrameNumOffset = frameNumOffset; + } + + /* 8.2.1 (8-1) */ + if( !p_slice->i_field_pic_flag ) /* progressive or contains both fields */ + *p_PictureOrderCount = __MIN( *p_bFOC, *p_tFOC ); + else /* split top or bottom field */ + if ( p_slice->i_bottom_field_flag ) + *p_PictureOrderCount = *p_bFOC; + else + *p_PictureOrderCount = *p_tFOC; +} diff --git a/modules/packetizer/h264_slice.h b/modules/packetizer/h264_slice.h index 0b665b5..1ac399d 100644 --- a/modules/packetizer/h264_slice.h +++ b/modules/packetizer/h264_slice.h @@ -41,6 +41,7 @@ typedef struct int i_delta_pic_order_cnt0; int i_delta_pic_order_cnt1; + bool has_mmco5; } h264_slice_t; static inline void h264_slice_init( h264_slice_t *p_slice ) @@ -58,6 +59,7 @@ static inline void h264_slice_init( h264_slice_t *p_slice ) p_slice->i_delta_pic_order_cnt_bottom = -1; p_slice->i_delta_pic_order_cnt0 = 0; p_slice->i_delta_pic_order_cnt1 = 0; + p_slice->has_mmco5 = false; } bool h264_decode_slice( const uint8_t *p_buffer, size_t i_buffer, @@ -66,4 +68,31 @@ bool h264_decode_slice( const uint8_t *p_buffer, size_t i_buffer, const h264_picture_parameter_set_t ** ), void *, h264_slice_t *p_slice ); +typedef struct +{ + struct + { + int lsb; + int msb; + } prevPicOrderCnt; + unsigned prevFrameNum; + unsigned prevFrameNumOffset; + int prevRefPictureTFOC; + bool prevRefPictureIsBottomField; + bool prevRefPictureHasMMCO5; +} poc_context_t; + +static inline void h264_poc_context_init( poc_context_t *p_ctx ) +{ + p_ctx->prevPicOrderCnt.lsb = 0; + p_ctx->prevPicOrderCnt.msb = 0; + p_ctx->prevFrameNum = 0; + p_ctx->prevFrameNumOffset = 0; + p_ctx->prevRefPictureIsBottomField = false; + p_ctx->prevRefPictureHasMMCO5 = false; +} + +void h264_compute_poc( const h264_sequence_parameter_set_t *p_sps, + const h264_slice_t *p_slice, poc_context_t *p_ctx, + int *p_PictureOrderCount, int *p_tFOC, int *p_bFOC ); #endif _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
