[vlc-commits] packetizer: h264: simplify AVC SPS/PPS setup

Francois Cartegnie git at videolan.org
Sat Dec 12 23:20:16 CET 2015


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Sat Dec 12 20:05:48 2015 +0100| [3a49a650eca4548ed10b14732818444005458d7a] | committer: Francois Cartegnie

packetizer: h264: simplify AVC SPS/PPS setup

Since we have helpers to convert to AnnexB, we just
need to feed the NAL stream to packetizer instead
of parsing, converting and feeding it one by one.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=3a49a650eca4548ed10b14732818444005458d7a
---

 modules/packetizer/h264.c |  128 ++++++++++++++-------------------------------
 1 file changed, 38 insertions(+), 90 deletions(-)

diff --git a/modules/packetizer/h264.c b/modules/packetizer/h264.c
index e0d97c8..c6777e0 100644
--- a/modules/packetizer/h264.c
+++ b/modules/packetizer/h264.c
@@ -104,7 +104,7 @@ struct decoder_sys_t
     int    i_recovery_frames;  /* -1 = no recovery */
 
     /* avcC data */
-    int i_avcC_length_size;
+    uint8_t i_avcC_length_size;
 
     /* Useful values of the Sequence Parameter Set */
     int i_log2_max_frame_num;
@@ -180,10 +180,11 @@ static int Open( vlc_object_t *p_this )
     decoder_sys_t *p_sys;
     int i;
 
+    const bool b_avc = (p_dec->fmt_in.i_original_fourcc == VLC_FOURCC( 'a', 'v', 'c', '1' ));
+
     if( p_dec->fmt_in.i_codec != VLC_CODEC_H264 )
         return VLC_EGENERIC;
-    if( p_dec->fmt_in.i_original_fourcc == VLC_FOURCC( 'a', 'v', 'c', '1') &&
-        p_dec->fmt_in.i_extra < 7 )
+    if( b_avc && p_dec->fmt_in.i_extra < 7 )
         return VLC_EGENERIC;
 
     /* Allocate the memory needed to store the decoder's structure */
@@ -238,101 +239,33 @@ static int Open( vlc_object_t *p_this )
     es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in );
     p_dec->fmt_out.i_codec = VLC_CODEC_H264;
 
-    if( p_dec->fmt_in.i_original_fourcc == VLC_FOURCC( 'a', 'v', 'c', '1' ) )
+    if( b_avc )
     {
         /* This type of stream is produced by mp4 and matroska
          * when we want to store it in another streamformat, you need to convert
          * The fmt_in.p_extra should ALWAYS contain the avcC
          * The fmt_out.p_extra should contain all the SPS and PPS with 4 byte startcodes */
-        uint8_t *p = &((uint8_t*)p_dec->fmt_in.p_extra)[4];
-        int i_sps, i_pps;
-        bool b_dummy;
-        int i;
-
-        /* Parse avcC */
-        p_sys->i_avcC_length_size = 1 + ((*p++)&0x03);
-
-        /* Read SPS */
-        i_sps = (*p++)&0x1f;
-        for( i = 0; i < i_sps; i++ )
+        if( h264_isavcC( p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra ) )
         {
-            uint16_t i_length = GetWBE( p ); p += 2;
-            if( i_length >
-                (uint8_t*)p_dec->fmt_in.p_extra + p_dec->fmt_in.i_extra - p )
-            {
-                return VLC_EGENERIC;
-            }
-            block_t *p_sps = CreateAnnexbNAL( p, i_length );
-            if( !p_sps )
-                return VLC_EGENERIC;
-            ParseNALBlock( p_dec, &b_dummy, p_sps );
-            p += i_length;
-        }
-        /* Read PPS */
-        i_pps = *p++;
-        for( i = 0; i < i_pps; i++ )
-        {
-            uint16_t i_length = GetWBE( p ); p += 2;
-            if( i_length >
-                (uint8_t*)p_dec->fmt_in.p_extra + p_dec->fmt_in.i_extra - p )
-            {
-                return VLC_EGENERIC;
-            }
-            block_t *p_pps = CreateAnnexbNAL( p, i_length );
-            if( !p_pps )
-                return VLC_EGENERIC;
-            ParseNALBlock( p_dec, &b_dummy, p_pps );
-            p += i_length;
-        }
-        msg_Dbg( p_dec, "avcC length size=%d, sps=%d, pps=%d",
-                 p_sys->i_avcC_length_size, i_sps, i_pps );
-
-        if( !p_sys->b_sps || !p_sys->b_pps )
-            return VLC_EGENERIC;
-
-        /* FIXME: FFMPEG isn't happy at all if you leave this */
-        if( p_dec->fmt_out.i_extra > 0 )
             free( p_dec->fmt_out.p_extra );
-        p_dec->fmt_out.i_extra = 0;
-        p_dec->fmt_out.p_extra = NULL;
-
-        /* Set the new extradata */
-        for( i = 0; i < H264_SPS_MAX; i++ )
-        {
-            if( p_sys->pp_sps[i] )
-                p_dec->fmt_out.i_extra += p_sys->pp_sps[i]->i_buffer;
-        }
-        for( i = 0; i < H264_PPS_MAX; i++ )
-        {
-            if( p_sys->pp_pps[i] )
-                p_dec->fmt_out.i_extra += p_sys->pp_pps[i]->i_buffer;
-        }
-        p_dec->fmt_out.p_extra = malloc( p_dec->fmt_out.i_extra );
-        if( p_dec->fmt_out.p_extra )
-        {
-            uint8_t *p_dst = p_dec->fmt_out.p_extra;
-
-            for( i = 0; i < H264_SPS_MAX; i++ )
+            size_t i_size;
+            p_dec->fmt_out.p_extra = h264_avcC_to_AnnexB_NAL( p_dec->fmt_in.p_extra,
+                                                              p_dec->fmt_in.i_extra,
+                                                             &i_size,
+                                                             &p_sys->i_avcC_length_size );
+            p_dec->fmt_out.i_extra = i_size;
+            p_sys->b_header = !!p_dec->fmt_out.i_extra;
+
+            if(!p_dec->fmt_out.p_extra)
             {
-                if( p_sys->pp_sps[i] )
-                {
-                    memcpy( p_dst, p_sys->pp_sps[i]->p_buffer, p_sys->pp_sps[i]->i_buffer );
-                    p_dst += p_sys->pp_sps[i]->i_buffer;
-                }
-            }
-            for( i = 0; i < H264_PPS_MAX; i++ )
-            {
-                if( p_sys->pp_pps[i] )
-                {
-                    memcpy( p_dst, p_sys->pp_pps[i]->p_buffer, p_sys->pp_pps[i]->i_buffer );
-                    p_dst += p_sys->pp_pps[i]->i_buffer;
-                }
+                msg_Err( p_dec, "Invalid AVC extradata");
+                return VLC_EGENERIC;
             }
-            p_sys->b_header = true;
         }
         else
         {
-            p_dec->fmt_out.i_extra = 0;
+            msg_Err( p_dec, "Invalid or missing AVC extradata");
+            return VLC_EGENERIC;
         }
 
         /* Set callback */
@@ -346,11 +279,26 @@ static int Open( vlc_object_t *p_this )
 
         /* Set callback */
         p_dec->pf_packetize = Packetize;
+    }
+
+    /* */
+    if( p_dec->fmt_out.i_extra > 0 )
+    {
+        packetizer_Header( &p_sys->packetizer,
+                           p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra );
+    }
+
+    if( b_avc )
+    {
+        if( !p_sys->b_sps || !p_sys->b_pps )
+        {
+            msg_Err( p_dec, "Invalid or missing SPS %d or PPS %d in AVC extradata",
+                     p_sys->b_sps, p_sys->b_pps );
+            return VLC_EGENERIC;
+        }
 
-        /* */
-        if( p_dec->fmt_in.i_extra > 0 )
-            packetizer_Header( &p_sys->packetizer,
-                               p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra );
+        msg_Dbg( p_dec, "Packetizer fed with AVC, nal length size=%d",
+                         p_sys->i_avcC_length_size );
     }
 
     /* CC are the same for H264/AVC in T35 sections (ETSI TS 101 154)  */



More information about the vlc-commits mailing list