[vlc-devel] [PATCH] x264: write first SEI NAL into first picture

Rafaël Carré rafael.carre at gmail.com
Sun Nov 7 18:55:58 CET 2010


It contains the x264 version info and options used for encoding
If we let it in extradata it will not be present in the final file

libavcodec does that already, and this makes it easier to compare x264
options used by VLC and FFmpeg.

Comparing FFmpeg and VLC with the exact same set of options might help
finding why mpeg (at least mpeg2/mpeg4/flv) encoding is 5 times slower
with vlc than with ffmpeg, supposedly for the same set of options.

---
2nd version of this patch fixes a double free
3rd version of this patch includes:
    - changes for better clarity
    - assert() that x264 headers contain at most 1 SEI nal
    - insert the SEI just before the first SLICE nal
---
 modules/codec/x264.c |   54 +++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 47 insertions(+), 7 deletions(-)

diff --git a/modules/codec/x264.c b/modules/codec/x264.c
index c34b593..673422d 100644
--- a/modules/codec/x264.c
+++ b/modules/codec/x264.c
@@ -42,6 +42,8 @@
 #endif
 #include <x264.h>
 
+#include <assert.h>
+
 #define SOUT_CFG_PREFIX "sout-x264-"
 
 /*****************************************************************************
@@ -712,6 +714,8 @@ struct encoder_sys_t
     mtime_t         i_initial_delay;
 
     char            *psz_stat_name;
+    int             i_sei_size;
+    uint8_t         *p_sei;
 };
 
 #ifdef PTW32_STATIC_LIB
@@ -753,6 +757,8 @@ static int  Open ( vlc_object_t *p_this )
         return VLC_ENOMEM;
     p_sys->i_initial_delay = 0;
     p_sys->psz_stat_name = NULL;
+    p_sys->i_sei_size = 0;
+    p_sys->p_sei = NULL;
 
     x264_param_default( &p_sys->param );
     char *psz_preset = var_GetString( p_enc, SOUT_CFG_PREFIX  "preset" );
@@ -1260,20 +1266,43 @@ static int  Open ( vlc_object_t *p_this )
     }
 
     /* get the globals headers */
-    p_enc->fmt_out.i_extra = x264_encoder_headers( p_sys->h, &nal, &i_nal );
-    p_enc->fmt_out.p_extra = malloc( p_enc->fmt_out.i_extra );
-    if( !p_enc->fmt_out.p_extra )
+    size_t i_extra = x264_encoder_headers( p_sys->h, &nal, &i_nal );
+    uint8_t *p_extra = p_enc->fmt_out.p_extra = malloc( i_extra );
+    if( !p_extra )
     {
         Close( VLC_OBJECT(p_enc) );
         return VLC_ENOMEM;
     }
-    uint8_t *p_tmp = p_enc->fmt_out.p_extra;
+
     for( i = 0; i < i_nal; i++ )
     {
-        memcpy( p_tmp, nal[i].p_payload, nal[i].i_payload );
-        p_tmp += nal[i].i_payload;
+        if( nal[i].i_type != NAL_SEI )
+        {
+            memcpy( p_extra, nal[i].p_payload, nal[i].i_payload );
+            p_extra += nal[i].i_payload;
+            continue; /* next NAL */
+        }
+
+        /* we won't store this NAL in p_extra */
+        assert( i_extra >= (size_t)nal[i].i_payload );
+        i_extra -= nal[i].i_payload;
+
+        /* Make sure we only have one SEI NAL in the headers */
+        assert(p_sys->i_sei_size == 0);
+        p_sys->i_sei_size = nal[i].i_payload;
+
+        p_sys->p_sei = malloc( p_sys->i_sei_size );
+        if( !p_sys->p_sei )
+        {
+            free( p_extra );
+            Close( VLC_OBJECT(p_enc) );
+            return VLC_ENOMEM;
+        }
+        memcpy( p_sys->p_sei, nal[i].p_payload, nal[i].i_payload );
     }
 
+    p_enc->fmt_out.i_extra = i_extra;
+
     return VLC_SUCCESS;
 }
 
@@ -1321,7 +1350,8 @@ static block_t *Encode( encoder_t *p_enc, picture_t *p_pict )
 
 
     /* Get size of block we need */
-    for( i = 0, i_out = 0; i < i_nal; i++ )
+    i_out = p_sys->i_sei_size;
+    for( i = 0; i < i_nal; i++ )
         i_out += nal[i].i_payload;
 
     p_block = block_New( p_enc, i_out );
@@ -1330,6 +1360,15 @@ static block_t *Encode( encoder_t *p_enc, picture_t *p_pict )
     /* copy encoded data directly to block */
     for( i = 0, i_out = 0; i < i_nal; i++ )
     {
+        if( p_sys->i_sei_size && nal[i].i_type == NAL_SLICE )
+        {
+            /* insert x264 headers SEI nal before first SLICE nal */
+            memcpy( p_block->p_buffer, p_sys->p_sei, p_sys->i_sei_size );
+            i_out += p_sys->i_sei_size;
+            p_sys->i_sei_size = 0;
+            free( p_sys->p_sei );
+            p_sys->p_sei = NULL;
+        }
         memcpy( p_block->p_buffer + i_out, nal[i].p_payload, nal[i].i_payload );
         i_out += nal[i].i_payload;
     }
@@ -1364,6 +1403,7 @@ static void Close( vlc_object_t *p_this )
     encoder_sys_t *p_sys = p_enc->p_sys;
 
     free( p_sys->psz_stat_name );
+    free( p_sys->p_sei );
 
     msg_Dbg( p_enc, "framecount still in libx264 buffer: %d", x264_encoder_delayed_frames( p_sys->h ) );
 
-- 
1.7.3.2





More information about the vlc-devel mailing list