[vlc-commits] [Git][videolan/vlc][3.0.x] 5 commits: packetizer: h264: write avcC with HIGH extended info

Jean-Baptiste Kempf (@jbk) gitlab at videolan.org
Sat Jul 3 08:19:50 UTC 2021



Jean-Baptiste Kempf pushed to branch 3.0.x at VideoLAN / VLC


Commits:
ff632589 by Francois Cartegnie at 2021-07-03T07:50:52+00:00
packetizer: h264: write avcC with HIGH extended info

(cherry picked from commit 8d5dd5ead3340db5591ef09b703432723aaa1886)

- - - - -
7f85a5ad by Francois Cartegnie at 2021-07-03T07:50:52+00:00
packetizer: h264: add basic decoding for sequence set extension

(cherry picked from commit a9d002e84b49fe395f5564f0fcee57a1f7f25229)

- - - - -
8530682d by Francois Cartegnie at 2021-07-03T07:50:52+00:00
hxxx_helper: process SPS_EXT

(cherry picked from commit 33a34ae731ce03aa4910c680cae1eb6bfd3a56f3)

- - - - -
a3df90aa by Francois Cartegnie at 2021-07-03T07:50:52+00:00
packetizer: h264: remove scan lookup

(cherry picked from commit 8404b8c6b79d4e94ed9f1170b089620614cb7a7f)

- - - - -
cd18bd16 by Francois Cartegnie at 2021-07-03T07:50:52+00:00
packetizer: h264: gather and store SPSEXT

(cherry picked from commit 35251232e281be37ecb994ae8714c32dc2e40c30)

- - - - -


5 changed files:

- modules/codec/hxxx_helper.c
- modules/codec/hxxx_helper.h
- modules/packetizer/h264.c
- modules/packetizer/h264_nal.c
- modules/packetizer/h264_nal.h


Changes:

=====================================
modules/codec/hxxx_helper.c
=====================================
@@ -88,6 +88,8 @@ hxxx_helper_clean(struct hxxx_helper *hh)
                          h264_release_sps(hnal->h264_sps));
             RELEASE_NALS(hh->h264.pps_list, H264_PPS_ID_MAX,
                          h264_release_pps(hnal->h264_pps));
+            RELEASE_NALS(hh->h264.spsext_list, H264_SPSEXT_ID_MAX,
+                         h264_release_sps_extension(hnal->h264_spsext));
             memset(&hh->h264, 0, sizeof(hh->h264));
             break;
         case VLC_CODEC_HEVC:
@@ -229,6 +231,15 @@ h264_helper_parse_nal(struct hxxx_helper *hh, const uint8_t *p_buf, size_t i_buf
                      h264_release_pps);
             msg_Dbg(hh->p_obj, "new PPS parsed: %u", ((h264_picture_parameter_set_t*)p_xps)->i_id);
         }
+        else if(i_nal_type == H264_NAL_SPS_EXT)
+        {
+            LOAD_xPS(hh->h264.spsext_list, hh->h264.i_spsext_count,
+                     p_xps->i_sps_id, H264_SPSEXT_ID_MAX,
+                     h264_sequence_parameter_set_extension_t,
+                     h264_decode_sps_extension,
+                     h264_release_sps_extension);
+            msg_Dbg(hh->p_obj, "new SPSEXT parsed: %u", ((h264_sequence_parameter_set_extension_t*)p_xps)->i_sps_id);
+        }
         else if (i_nal_type <= H264_NAL_SLICE_IDR
               && i_nal_type != H264_NAL_UNKNOWN)
         {
@@ -738,11 +749,11 @@ h264_helper_get_annexb_config(const struct hxxx_helper *hh)
         return NULL;
 
     const struct hxxx_helper_nal *pp_nal_lists[] = {
-        hh->h264.sps_list, hh->h264.pps_list };
-    const size_t p_nal_counts[] = { hh->h264.i_sps_count, hh->h264.i_pps_count };
-    const size_t p_nal_maxs[] = { H264_SPS_ID_MAX+1, H264_PPS_ID_MAX+1 };
+        hh->h264.sps_list, hh->h264.pps_list, hh->h264.spsext_list };
+    const size_t p_nal_counts[] = { hh->h264.i_sps_count, hh->h264.i_pps_count, hh->h264.i_spsext_count };
+    const size_t p_nal_maxs[] = { H264_SPS_ID_MAX+1, H264_PPS_ID_MAX+1, H264_SPSEXT_ID_MAX+1 };
 
-    return hxxx_helper_get_annexb_config( pp_nal_lists, p_nal_counts, p_nal_maxs, 2 );
+    return hxxx_helper_get_annexb_config( pp_nal_lists, p_nal_counts, p_nal_maxs, 3 );
 }
 
 block_t *
@@ -782,8 +793,19 @@ h264_helper_get_avcc_config(const struct hxxx_helper *hh)
         pp_pps_bufs[i_nal_found - 1] = p_nal->b->p_buffer;
         p_pps_sizes[i_nal_found - 1] = p_nal->b->i_buffer;
     }
+
+    const uint8_t *pp_spsext_bufs[hh->h264.i_spsext_count];
+    size_t p_spsext_sizes[hh->h264.i_spsext_count];
+    HELPER_FOREACH_NAL(p_nal, hh->h264.spsext_list, hh->h264.i_spsext_count,
+                       H264_SPSEXT_ID_MAX+1)
+    {
+        pp_spsext_bufs[i_nal_found - 1] = p_nal->b->p_buffer;
+        p_spsext_sizes[i_nal_found - 1] = p_nal->b->i_buffer;
+    }
+
     return h264_NAL_to_avcC(4, pp_sps_bufs, p_sps_sizes, hh->h264.i_sps_count,
-                            pp_pps_bufs, p_pps_sizes, hh->h264.i_pps_count);
+                            pp_pps_bufs, p_pps_sizes, hh->h264.i_pps_count,
+                            pp_spsext_bufs, p_spsext_sizes, hh->h264.i_spsext_count);
 }
 
 block_t *


=====================================
modules/codec/hxxx_helper.h
=====================================
@@ -35,6 +35,7 @@ struct hxxx_helper_nal
         void                            *xps;
         h264_sequence_parameter_set_t   *h264_sps;
         h264_picture_parameter_set_t    *h264_pps;
+        h264_sequence_parameter_set_extension_t *h264_spsext;
         hevc_sequence_parameter_set_t   *hevc_sps;
         hevc_picture_parameter_set_t    *hevc_pps;
         hevc_video_parameter_set_t      *hevc_vps;
@@ -55,9 +56,11 @@ struct hxxx_helper
         struct {
             struct hxxx_helper_nal sps_list[H264_SPS_ID_MAX + 1];
             struct hxxx_helper_nal pps_list[H264_PPS_ID_MAX + 1];
+            struct hxxx_helper_nal spsext_list[H264_SPS_ID_MAX + 1];
             uint8_t i_current_sps;
             uint8_t i_sps_count;
             uint8_t i_pps_count;
+            uint8_t i_spsext_count;
         } h264;
         struct {
             struct hxxx_helper_nal sps_list[HEVC_SPS_ID_MAX + 1];


=====================================
modules/packetizer/h264.c
=====================================
@@ -96,6 +96,10 @@ struct decoder_sys_t
         block_t *p_block;
         h264_picture_parameter_set_t *p_pps;
     } pps[H264_PPS_ID_MAX + 1];
+    struct
+    {
+        block_t *p_block;
+    } spsext[H264_SPSEXT_ID_MAX + 1];
     const h264_sequence_parameter_set_t *p_active_sps;
     const h264_picture_parameter_set_t *p_active_pps;
 
@@ -152,6 +156,7 @@ static block_t *ParseNALBlock( decoder_t *, bool *pb_ts_used, block_t * );
 static block_t *OutputPicture( decoder_t *p_dec );
 static void PutSPS( decoder_t *p_dec, block_t *p_frag );
 static void PutPPS( decoder_t *p_dec, block_t *p_frag );
+static void PutSPSEXT( decoder_t *p_dec, block_t *p_frag );
 static bool ParseSliceHeader( decoder_t *p_dec, const block_t *p_frag, h264_slice_t *p_slice );
 static bool ParseSeiCallback( const hxxx_sei_data_t *, void * );
 
@@ -188,6 +193,13 @@ static void StorePPS( decoder_sys_t *p_sys, uint8_t i_id,
     p_sys->pps[i_id].p_pps = p_pps;
 }
 
+static void StoreSPSEXT( decoder_sys_t *p_sys, uint8_t i_id, block_t *p_block )
+{
+    if( p_sys->spsext[i_id].p_block )
+        block_Release( p_sys->spsext[i_id].p_block );
+    p_sys->spsext[i_id].p_block = p_block;
+}
+
 static void ActivateSets( decoder_t *p_dec, const h264_sequence_parameter_set_t *p_sps,
                                             const h264_picture_parameter_set_t *p_pps )
 {
@@ -237,27 +249,28 @@ static void ActivateSets( decoder_t *p_dec, const h264_sequence_parameter_set_t
 
         if( p_dec->fmt_out.i_extra == 0 && p_pps )
         {
-            const block_t *p_spsblock = NULL;
-            const block_t *p_ppsblock = NULL;
-            for( size_t i=0; i<=H264_SPS_ID_MAX && !p_spsblock; i++ )
-                if( p_sps == p_sys->sps[i].p_sps )
-                    p_spsblock = p_sys->sps[i].p_block;
-
-            for( size_t i=0; i<=H264_PPS_ID_MAX && !p_ppsblock; i++ )
-                if( p_pps == p_sys->pps[i].p_pps )
-                    p_ppsblock = p_sys->pps[i].p_block;
+            const block_t *p_spsblock = p_sys->sps[p_sps->i_id].p_block;
+            const block_t *p_ppsblock = p_sys->pps[p_pps->i_id].p_block;
+            const block_t *p_spsextblock = p_sys->spsext[p_sps->i_id].p_block;
 
             if( p_spsblock && p_ppsblock )
             {
                 size_t i_alloc = p_ppsblock->i_buffer + p_spsblock->i_buffer;
+                if( p_spsextblock )
+                    i_alloc += p_spsextblock->i_buffer;
                 p_dec->fmt_out.p_extra = malloc( i_alloc );
                 if( p_dec->fmt_out.p_extra )
                 {
                     uint8_t*p_buf = p_dec->fmt_out.p_extra;
                     p_dec->fmt_out.i_extra = i_alloc;
-                    memcpy( &p_buf[0], p_spsblock->p_buffer, p_spsblock->i_buffer );
-                    memcpy( &p_buf[p_spsblock->i_buffer], p_ppsblock->p_buffer,
-                            p_ppsblock->i_buffer );
+                    memcpy( p_buf, p_spsblock->p_buffer, p_spsblock->i_buffer );
+                    p_buf += p_spsblock->i_buffer;
+                    if( p_spsextblock )
+                    {
+                        memcpy( p_buf, p_spsextblock->p_buffer, p_spsextblock->i_buffer );
+                        p_buf += p_spsextblock->i_buffer;
+                    }
+                    memcpy( p_buf, p_ppsblock->p_buffer, p_ppsblock->i_buffer );
                 }
             }
         }
@@ -359,6 +372,8 @@ static int Open( vlc_object_t *p_this )
         p_sys->pps[i].p_block = NULL;
     }
     p_sys->p_active_pps = NULL;
+    for( i = 0; i <= H264_SPSEXT_ID_MAX; i++ )
+        p_sys->spsext[i].p_block = NULL;
     p_sys->i_recovery_frame_cnt = UINT_MAX;
 
     h264_slice_init( &p_sys->slice );
@@ -477,6 +492,8 @@ static void Close( vlc_object_t *p_this )
         StoreSPS( p_sys, i, NULL, NULL );
     for( i = 0; i <= H264_PPS_ID_MAX; i++ )
         StorePPS( p_sys, i, NULL, NULL );
+    for( i = 0; i <= H264_SPSEXT_ID_MAX; i++ )
+        StoreSPSEXT( p_sys, i, NULL );
 
     packetizer_Clean( &p_sys->packetizer );
 
@@ -714,6 +731,11 @@ static block_t *ParseNALBlock( decoder_t *p_dec, bool *pb_ts_used, block_t *p_fr
         break;
 
         case H264_NAL_SPS_EXT:
+            PutSPSEXT( p_dec, p_frag );
+            if( p_sys->b_slice )
+                p_pic = OutputPicture( p_dec );
+            break;
+
         case H264_NAL_PREFIX: /* first slice/VCL associated data */
         case H264_NAL_SUBSET_SPS:
         case H264_NAL_DEPTH_PS:
@@ -853,6 +875,10 @@ static block_t *OutputPicture( decoder_t *p_dec )
         {
             if( p_sys->sps[i].p_block )
                 block_ChainLastAppend( &pp_xpsnal_tail, block_Duplicate( p_sys->sps[i].p_block ) );
+            /* 7.4.1.2.3,  shall be the next NAL unit after a sequence parameter set NAL unit
+             * having the same value of seq_parameter_set_id */
+            if( p_sys->spsext[i].p_block )
+                block_ChainLastAppend( &pp_xpsnal_tail, block_Duplicate( p_sys->spsext[i].p_block ) );
         }
         for( int i = 0; i < H264_PPS_ID_MAX && (b_need_sps_pps || p_sys->b_new_pps); i++ )
         {
@@ -1110,6 +1136,37 @@ static void PutPPS( decoder_t *p_dec, block_t *p_frag )
     StorePPS( p_sys, p_pps->i_id, p_frag, p_pps );
 }
 
+static void PutSPSEXT( decoder_t *p_dec, block_t *p_frag )
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    const uint8_t *p_buffer = p_frag->p_buffer;
+    size_t i_buffer = p_frag->i_buffer;
+
+    if( !hxxx_strip_AnnexB_startcode( &p_buffer, &i_buffer ) )
+    {
+        block_Release( p_frag );
+        return;
+    }
+
+    h264_sequence_parameter_set_extension_t *p_spsext =
+            h264_decode_sps_extension( p_buffer, i_buffer, true );
+    if( !p_spsext )
+    {
+        msg_Warn( p_dec, "invalid SPSEXT" );
+        block_Release( p_frag );
+        return;
+    }
+
+    /* We have a new SPSEXT */
+    if( !p_sys->spsext[p_spsext->i_sps_id].p_block )
+        msg_Dbg( p_dec, "found NAL_SPSEXT (sps_id=%d)", p_spsext->i_sps_id );
+
+    StoreSPSEXT( p_sys, p_spsext->i_sps_id, p_frag );
+
+    /* we don't need a decoded one */
+    h264_release_sps_extension( p_spsext );
+}
+
 static void GetSPSPPS( uint8_t i_pps_id, void *priv,
                        const h264_sequence_parameter_set_t **pp_sps,
                        const h264_picture_parameter_set_t **pp_pps )


=====================================
modules/packetizer/h264_nal.c
=====================================
@@ -607,6 +607,20 @@ static bool h264_parse_picture_parameter_set_rbsp( bs_t *p_bs,
     return true;
 }
 
+static bool h264_parse_sequence_parameter_set_extension_rbsp( bs_t *p_bs,
+                                 h264_sequence_parameter_set_extension_t *p_sps_ext )
+{
+    p_sps_ext->i_sps_id = bs_read_ue( p_bs );
+    if( p_sps_ext->i_sps_id > H264_SPSEXT_ID_MAX )
+        return false;
+    return true;
+}
+
+void h264_release_sps_extension( h264_sequence_parameter_set_extension_t *p_sps_ext )
+{
+    free( p_sps_ext );
+}
+
 #define IMPL_h264_generic_decode( name, h264type, decode, release ) \
     h264type * name( const uint8_t *p_buf, size_t i_buf, bool b_escaped ) \
     { \
@@ -638,11 +652,16 @@ IMPL_h264_generic_decode( h264_decode_sps, h264_sequence_parameter_set_t,
 IMPL_h264_generic_decode( h264_decode_pps, h264_picture_parameter_set_t,
                           h264_parse_picture_parameter_set_rbsp, h264_release_pps )
 
+IMPL_h264_generic_decode( h264_decode_sps_extension, h264_sequence_parameter_set_extension_t,
+                          h264_parse_sequence_parameter_set_extension_rbsp, h264_release_sps_extension )
+
 block_t *h264_NAL_to_avcC( uint8_t i_nal_length_size,
                            const uint8_t **pp_sps_buf,
                            const size_t *p_sps_size, uint8_t i_sps_count,
                            const uint8_t **pp_pps_buf,
-                           const size_t *p_pps_size, uint8_t i_pps_count )
+                           const size_t *p_pps_size, uint8_t i_pps_count,
+                           const uint8_t **pp_sps_ext_buf,
+                           const size_t *p_sps_ext_size, uint8_t i_sps_ext_count )
 {
     /* The length of the NAL size is encoded using 1, 2 or 4 bytes */
     if( i_nal_length_size != 1 && i_nal_length_size != 2
@@ -691,6 +710,26 @@ block_t *h264_NAL_to_avcC( uint8_t i_nal_length_size,
         bo_add_mem( &bo, p_pps_size[i], pp_pps_buf[i] );
     }
 
+    const uint8_t i_profile = pp_sps_buf[0][1];
+    if( i_profile == PROFILE_H264_HIGH ||
+        i_profile == PROFILE_H264_HIGH_10 ||
+        i_profile == PROFILE_H264_HIGH_422 ||
+        i_profile == PROFILE_H264_HIGH_444 )
+    {
+        h264_sequence_parameter_set_t *p_sps = h264_decode_sps( pp_sps_buf[0], p_sps_size[0], true );
+        bo_add_8( &bo, 0xfc | (p_sps ? p_sps->i_chroma_idc : 0) );
+        bo_add_8( &bo, 0xf8 | (p_sps ? (p_sps->i_bit_depth_luma - 8) : 0) );
+        bo_add_8( &bo, 0xf8 | (p_sps ? (p_sps->i_bit_depth_chroma - 8) : 0) );
+        if( p_sps )
+            h264_release_sps( p_sps );
+        bo_add_8( &bo, i_sps_ext_count );
+        for( size_t i = 0; i < i_sps_ext_count; ++i )
+        {
+            bo_add_16be( &bo, p_sps_ext_size[i] );
+            bo_add_mem( &bo, p_sps_ext_size[i], pp_sps_ext_buf[i] );
+        }
+    }
+
     return bo.b;
 }
 


=====================================
modules/packetizer/h264_nal.h
=====================================
@@ -44,6 +44,7 @@
 
 #define H264_SPS_ID_MAX (31)
 #define H264_PPS_ID_MAX (255)
+#define H264_SPSEXT_ID_MAX H264_SPS_ID_MAX
 
 enum h264_nal_unit_type_e
 {
@@ -76,12 +77,15 @@ enum h264_nal_unit_type_e
 
 typedef struct h264_sequence_parameter_set_t h264_sequence_parameter_set_t;
 typedef struct h264_picture_parameter_set_t h264_picture_parameter_set_t;
+typedef struct h264_sequence_parameter_set_extension_t h264_sequence_parameter_set_extension_t;
 
 h264_sequence_parameter_set_t * h264_decode_sps( const uint8_t *, size_t, bool );
 h264_picture_parameter_set_t *  h264_decode_pps( const uint8_t *, size_t, bool );
+h264_sequence_parameter_set_extension_t * h264_decode_sps_extension( const uint8_t *, size_t, bool );
 
 void h264_release_sps( h264_sequence_parameter_set_t * );
 void h264_release_pps( h264_picture_parameter_set_t * );
+void h264_release_sps_extension( h264_sequence_parameter_set_extension_t * );
 
 struct h264_sequence_parameter_set_t
 {
@@ -148,6 +152,11 @@ struct h264_picture_parameter_set_t
     uint8_t weighted_bipred_idc;
 };
 
+struct h264_sequence_parameter_set_extension_t
+{
+    uint8_t i_sps_id;
+};
+
 /*
     AnnexB : [\x00] \x00 \x00 \x01 Prefixed NAL
     AVC Sample format : NalLengthSize encoded size prefixed NAL
@@ -175,7 +184,9 @@ block_t *h264_NAL_to_avcC( uint8_t i_nal_length_size,
                            const uint8_t **pp_sps_buf,
                            const size_t *p_sps_size, uint8_t i_sps_count,
                            const uint8_t **pp_pps_buf,
-                           const size_t *p_pps_size, uint8_t i_pps_count );
+                           const size_t *p_pps_size, uint8_t i_pps_count,
+                           const uint8_t **pp_sps_ext_buf,
+                           const size_t *p_sps_ext_size, uint8_t i_sps_ext_count);
 
 /* Convert AVCDecoderConfigurationRecord SPS/PPS to Annex B format */
 uint8_t * h264_avcC_to_AnnexB_NAL( const uint8_t *p_buf, size_t i_buf,



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/4c537f29b0ca27377badf7b7ed77bc4b0b4a9f32...cd18bd167d221412576d974673cd3f0718a80b36

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/4c537f29b0ca27377badf7b7ed77bc4b0b4a9f32...cd18bd167d221412576d974673cd3f0718a80b36
You're receiving this email because of your account on code.videolan.org.




More information about the vlc-commits mailing list