[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