[vlc-devel] commit: Added support for multiple SPS and/or PPS. (Laurent Aimar )

git version control git at videolan.org
Fri Jul 25 23:32:06 CEST 2008


vlc | branch: master | Laurent Aimar <fenrir at videolan.org> | Fri Jul 25 23:31:11 2008 +0200| [126902d38ee6f661d127c3118d7fa107228315a7]

Added support for multiple SPS and/or PPS.

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

 modules/packetizer/h264.c |  118 ++++++++++++++++++++++++++++++++-------------
 1 files changed, 85 insertions(+), 33 deletions(-)

diff --git a/modules/packetizer/h264.c b/modules/packetizer/h264.c
index 43d3604..abffa1f 100644
--- a/modules/packetizer/h264.c
+++ b/modules/packetizer/h264.c
@@ -93,17 +93,17 @@ struct decoder_sys_t
     size_t  i_offset;
     uint8_t startcode[4];
 
-    bool b_slice;
-    block_t    *p_frame;
+    bool    b_slice;
+    block_t *p_frame;
 
+    bool   b_header;
     bool   b_sps;
     bool   b_pps;
-    bool   b_header;
+    block_t *pp_sps[SPS_MAX];
+    block_t *pp_pps[PPS_MAX];
 
     /* avcC data */
     int i_avcC_length_size;
-    block_t *p_sps;
-    block_t *p_pps;
 
     /* Useful values of the Sequence Parameter Set */
     int i_log2_max_frame_num;
@@ -168,6 +168,7 @@ static int Open( vlc_object_t *p_this )
 {
     decoder_t     *p_dec = (decoder_t*)p_this;
     decoder_sys_t *p_sys;
+    int i;
 
     if( p_dec->fmt_in.i_codec != VLC_FOURCC( 'h', '2', '6', '4') &&
         p_dec->fmt_in.i_codec != VLC_FOURCC( 'H', '2', '6', '4') &&
@@ -194,11 +195,13 @@ static int Open( vlc_object_t *p_this )
     p_sys->bytestream = block_BytestreamInit();
     p_sys->b_slice = false;
     p_sys->p_frame = NULL;
+    p_sys->b_header= false;
     p_sys->b_sps   = false;
     p_sys->b_pps   = false;
-    p_sys->p_sps   = 0;
-    p_sys->p_pps   = 0;
-    p_sys->b_header= false;
+    for( i = 0; i < SPS_MAX; i++ )
+        p_sys->pp_sps[i] = NULL;
+    for( i = 0; i < PPS_MAX; i++ )
+        p_sys->pp_pps[i] = NULL;
 
     p_sys->slice.i_nal_type = -1;
     p_sys->slice.i_nal_ref_idc = -1;
@@ -263,26 +266,53 @@ static int Open( vlc_object_t *p_this )
         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->p_sps || p_sys->p_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 );
+        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 */
-        p_dec->fmt_out.i_extra = p_sys->p_pps->i_buffer + p_sys->p_sps->i_buffer;
+        for( i = 0; i < 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 < 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 )
         {
-            memcpy( (uint8_t*)p_dec->fmt_out.p_extra,
-                    p_sys->p_sps->p_buffer, p_sys->p_sps->i_buffer);
-            memcpy( (uint8_t*)p_dec->fmt_out.p_extra+p_sys->p_sps->i_buffer,
-                    p_sys->p_pps->p_buffer, p_sys->p_pps->i_buffer);
+            uint8_t *p_dst = p_dec->fmt_out.p_extra;
+
+            for( i = 0; i < SPS_MAX; i++ )
+            {
+                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 < 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;
+                }
+            }
             p_sys->b_header = true;
         }
-        else p_dec->fmt_out.i_extra = 0;
+        else
+        {
+            p_dec->fmt_out.i_extra = 0;
+        }
 
         /* Set callback */
         p_dec->pf_packetize = PacketizeAVC1;
@@ -323,10 +353,19 @@ static void Close( vlc_object_t *p_this )
 {
     decoder_t *p_dec = (decoder_t*)p_this;
     decoder_sys_t *p_sys = p_dec->p_sys;
+    int i;
 
     if( p_sys->p_frame ) block_ChainRelease( p_sys->p_frame );
-    if( p_sys->p_sps ) block_Release( p_sys->p_sps );
-    if( p_sys->p_pps ) block_Release( p_sys->p_pps );
+    for( i = 0; i < SPS_MAX; i++ )
+    {
+        if( p_sys->pp_sps[i] )
+            block_Release( p_sys->pp_sps[i] );
+    }
+    for( i = 0; i < PPS_MAX; i++ )
+    {
+        if( p_sys->pp_pps[i] )
+            block_Release( p_sys->pp_pps[i] );
+    }
     block_BytestreamRelease( &p_sys->bytestream );
     free( p_sys );
 }
@@ -651,16 +690,29 @@ static block_t *OutputPicture( decoder_t *p_dec )
     if( !p_sys->b_header && p_sys->slice.i_frame_type != BLOCK_FLAG_TYPE_I)
         return NULL;
 
-    if( p_sys->slice.i_frame_type == BLOCK_FLAG_TYPE_I && p_sys->p_sps && p_sys->p_pps )
+    if( p_sys->slice.i_frame_type == BLOCK_FLAG_TYPE_I && p_sys->b_sps && p_sys->b_pps )
     {
-        block_t *p_sps = block_Duplicate( p_sys->p_sps );
-        block_t *p_pps = block_Duplicate( p_sys->p_pps );
-        p_sps->i_dts = p_sys->p_frame->i_dts;
-        p_sps->i_pts = p_sys->p_frame->i_pts;
-        block_ChainAppend( &p_sps, p_pps );
-        block_ChainAppend( &p_sps, p_sys->p_frame );
-        p_sys->b_header = true;
-        p_pic = block_ChainGather( p_sps );
+        block_t *p_list = NULL;
+        int i;
+
+        for( i = 0; i < SPS_MAX; i++ )
+        {
+            if( p_sys->pp_sps[i] )
+                block_ChainAppend( &p_list, block_Duplicate( p_sys->pp_sps[i] ) );
+        }
+        for( i = 0; i < PPS_MAX; i++ )
+        {
+            if( p_sys->pp_pps[i] )
+                block_ChainAppend( &p_list, block_Duplicate( p_sys->pp_pps[i] ) );
+        }
+        if( p_list )
+        {
+            p_list->i_dts = p_sys->p_frame->i_dts;
+            p_list->i_pts = p_sys->p_frame->i_pts;
+            p_sys->b_header = true;
+        }
+        block_ChainAppend( &p_list, p_sys->p_frame );
+        p_pic = block_ChainGather( p_list );
     }
     else
     {
@@ -815,9 +867,9 @@ static void PutSPS( decoder_t *p_dec, block_t *p_frag )
         msg_Dbg( p_dec, "found NAL_SPS (sps_id=%d)", i_sps_id );
     p_sys->b_sps = true;
 
-    if( p_sys->p_sps )
-        block_Release( p_sys->p_sps );
-    p_sys->p_sps = p_frag;
+    if( p_sys->pp_sps[i_sps_id] )
+        block_Release( p_sys->pp_sps[i_sps_id] );
+    p_sys->pp_sps[i_sps_id] = p_frag;
 }
 
 static void PutPPS( decoder_t *p_dec, block_t *p_frag )
@@ -845,9 +897,9 @@ static void PutPPS( decoder_t *p_dec, block_t *p_frag )
         msg_Dbg( p_dec, "found NAL_PPS (pps_id=%d sps_id=%d)", i_pps_id, i_sps_id );
     p_sys->b_pps = true;
 
-    if( p_sys->p_pps )
-        block_Release( p_sys->p_pps );
-    p_sys->p_pps = p_frag;
+    if( p_sys->pp_pps[i_pps_id] )
+        block_Release( p_sys->pp_pps[i_pps_id] );
+    p_sys->pp_pps[i_pps_id] = p_frag;
 }
 
 static void ParseSlice( decoder_t *p_dec, bool *pb_new_picture, slice_t *p_slice,




More information about the vlc-devel mailing list