[vlc-commits] packetizer: h264: decode and compute POC
Francois Cartegnie
git at videolan.org
Fri Mar 17 19:46:35 CET 2017
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | 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
More information about the vlc-commits
mailing list