[vlc-devel] [PATCH 1/2] Split SPS/PPS parsing and annex b conversion to a reusable utility function

Martin Storsjö martin at martin.st
Wed Sep 28 17:26:39 CEST 2011


---
The actual functionality shouldn't be broken (since I've tested
it in the omxil module), but please make sure it still builds,
since I don't have a build configuration that uses crystalhd
at the moment.

And AFAIK j-b was the author of this particular function, so I
only kept that author name from the copyright header.

 modules/codec/crystalhd.c |   72 ++++-----------------------------
 modules/codec/h264_nal.h  |   97 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 105 insertions(+), 64 deletions(-)
 create mode 100644 modules/codec/h264_nal.h

diff --git a/modules/codec/crystalhd.c b/modules/codec/crystalhd.c
index ff60509..4fd6d7f 100644
--- a/modules/codec/crystalhd.c
+++ b/modules/codec/crystalhd.c
@@ -37,6 +37,7 @@
 #include <vlc_common.h>
 #include <vlc_plugin.h>
 #include <vlc_codec.h>
+#include "h264_nal.h"
 
 /* Workaround for some versions of libcrystalHD */
 #if !defined(_WIN32) && !defined(__APPLE__)
@@ -95,7 +96,6 @@ vlc_module_end ()
  *****************************************************************************/
 static picture_t *DecodeBlock   ( decoder_t *p_dec, block_t **pp_block );
 // static void crystal_CopyPicture ( picture_t *, BC_DTS_PROC_OUT* );
-static int crystal_insert_sps_pps(decoder_t *, uint8_t *, uint32_t);
 
 /*****************************************************************************
  * decoder_sys_t : CrysalHD decoder structure
@@ -606,9 +606,7 @@ static int crystal_insert_sps_pps( decoder_t *p_dec,
                                    uint32_t i_buf_size)
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
-    int i_profile;
-    uint32_t i_data_size = i_buf_size, i_nal_size;
-    unsigned int i_loop_end;
+    int ret;
 
     p_sys->i_sps_pps_size = 0;
 
@@ -616,68 +614,14 @@ static int crystal_insert_sps_pps( decoder_t *p_dec,
     if( !p_sys->p_sps_pps_buf )
         return VLC_ENOMEM;
 
-    /* */
-    if( i_data_size < 7 )
-    {
-        msg_Err( p_dec, "Input Metadata too small" );
-        goto error;
-    }
-
-    /* Read infos in first 6 bytes */
-    i_profile         = (p_buf[1] << 16) | (p_buf[2] << 8) | p_buf[3];
-    p_sys->i_nal_size = (p_buf[4] & 0x03) + 1;
-    p_buf            += 5;
-    i_data_size      -= 5;
-
-    for ( unsigned int j = 0; j < 2; j++ )
-    {
-        /* First time is SPS, Second is PPS */
-        if( i_data_size < 1 )
-        {
-            msg_Err( p_dec, "PPS too small after processing SPS/PPS %u",
-                    i_data_size );
-            goto error;
-        }
-        i_loop_end = p_buf[0] & (j == 0 ? 0x1f : 0xff);
-        p_buf++; i_data_size--;
-
-        for ( unsigned int i = 0; i < i_loop_end; i++)
-        {
-            if( i_data_size < 2 )
-            {
-                msg_Err( p_dec, "SPS is too small %u", i_data_size );
-                goto error;
-            }
-
-            i_nal_size = (p_buf[0] << 8) | p_buf[1];
-            p_buf += 2;
-            i_data_size -= 2;
-
-            if( i_data_size < i_nal_size )
-            {
-                msg_Err( p_dec, "SPS size does not match NAL specified size %u",
-                        i_data_size );
-                goto error;
-            }
-
-            p_sys->p_sps_pps_buf[p_sys->i_sps_pps_size++] = 0;
-            p_sys->p_sps_pps_buf[p_sys->i_sps_pps_size++] = 0;
-            p_sys->p_sps_pps_buf[p_sys->i_sps_pps_size++] = 0;
-            p_sys->p_sps_pps_buf[p_sys->i_sps_pps_size++] = 1;
+    ret = convert_sps_pps( p_dec, p_buf, i_buf_size, p_sys->p_sps_pps_buf,
+                           p_dec->fmt_in.i_extra * 2, &p_sys->i_sps_pps_size,
+                           &p_sys->i_nal_size );
+    if( !ret )
+        return ret;
 
-            memcpy( p_sys->p_sps_pps_buf + p_sys->i_sps_pps_size, p_buf, i_nal_size );
-            p_sys->i_sps_pps_size += i_nal_size;
-
-            p_buf += i_nal_size;
-            i_data_size -= i_nal_size;
-        }
-    }
-
-    return VLC_SUCCESS;
-
-error:
     free( p_sys->p_sps_pps_buf );
     p_sys->p_sps_pps_buf = NULL;
-    return VLC_ENOMEM;
+    return ret;
 }
 
diff --git a/modules/codec/h264_nal.h b/modules/codec/h264_nal.h
new file mode 100644
index 0000000..70fda1a
--- /dev/null
+++ b/modules/codec/h264_nal.h
@@ -0,0 +1,97 @@
+/*****************************************************************************
+ * Copyright © 2010-2011 VideoLAN
+ *
+ * Authors: Jean-Baptiste Kempf <jb at videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+/* Parse the SPS/PPS Metadata and convert it to annex b format */
+static int convert_sps_pps( decoder_t *p_dec, const uint8_t *p_buf,
+                            uint32_t i_buf_size, uint8_t *p_out_buf,
+                            uint32_t i_out_buf_size, uint32_t *p_sps_pps_size,
+                            int *p_nal_size)
+{
+    int i_profile;
+    uint32_t i_data_size = i_buf_size, i_nal_size, i_sps_pps_size = 0;
+    unsigned int i_loop_end;
+
+    /* */
+    if( i_data_size < 7 )
+    {
+        msg_Err( p_dec, "Input Metadata too small" );
+        return VLC_ENOMEM;
+    }
+
+    /* Read infos in first 6 bytes */
+    i_profile    = (p_buf[1] << 16) | (p_buf[2] << 8) | p_buf[3];
+    *p_nal_size  = (p_buf[4] & 0x03) + 1;
+    p_buf       += 5;
+    i_data_size -= 5;
+
+    for ( unsigned int j = 0; j < 2; j++ )
+    {
+        /* First time is SPS, Second is PPS */
+        if( i_data_size < 1 )
+        {
+            msg_Err( p_dec, "PPS too small after processing SPS/PPS %u",
+                    i_data_size );
+            return VLC_ENOMEM;
+        }
+        i_loop_end = p_buf[0] & (j == 0 ? 0x1f : 0xff);
+        p_buf++; i_data_size--;
+
+        for ( unsigned int i = 0; i < i_loop_end; i++)
+        {
+            if( i_data_size < 2 )
+            {
+                msg_Err( p_dec, "SPS is too small %u", i_data_size );
+                return VLC_ENOMEM;
+            }
+
+            i_nal_size = (p_buf[0] << 8) | p_buf[1];
+            p_buf += 2;
+            i_data_size -= 2;
+
+            if( i_data_size < i_nal_size )
+            {
+                msg_Err( p_dec, "SPS size does not match NAL specified size %u",
+                        i_data_size );
+                return VLC_ENOMEM;
+            }
+            if( i_sps_pps_size + 4 + i_nal_size > i_out_buf_size )
+            {
+                msg_Err( p_dec, "Output SPS/PPS buffer too small" );
+                return VLC_ENOMEM;
+            }
+
+            p_out_buf[i_sps_pps_size++] = 0;
+            p_out_buf[i_sps_pps_size++] = 0;
+            p_out_buf[i_sps_pps_size++] = 0;
+            p_out_buf[i_sps_pps_size++] = 1;
+
+            memcpy( p_out_buf + i_sps_pps_size, p_buf, i_nal_size );
+            i_sps_pps_size += i_nal_size;
+
+            p_buf += i_nal_size;
+            i_data_size -= i_nal_size;
+        }
+    }
+
+    *p_sps_pps_size = i_sps_pps_size;
+
+    return VLC_SUCCESS;
+}
+
-- 
1.7.2.5




More information about the vlc-devel mailing list