[vlc-devel] [RFC PATCH 3/7] h264_nal: add h264_get_spspps

Thomas Guillem thomas at gllm.fr
Thu Apr 23 19:30:51 CEST 2015


It fetches the sps and pps pointers from an AnnexB buffer.
---
 modules/packetizer/h264_nal.c | 74 +++++++++++++++++++++++++++++++++++++++++++
 modules/packetizer/h264_nal.h |  6 ++++
 2 files changed, 80 insertions(+)

diff --git a/modules/packetizer/h264_nal.c b/modules/packetizer/h264_nal.c
index 2a375c2..de3ce6f 100644
--- a/modules/packetizer/h264_nal.c
+++ b/modules/packetizer/h264_nal.c
@@ -22,6 +22,8 @@
 
 #include <limits.h>
 
+static const uint8_t annexb_startcode[] = { 0x00, 0x00, 0x00, 0x01 };
+
 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,
@@ -138,6 +140,78 @@ void convert_h264_to_annexb( uint8_t *p_buf, uint32_t i_len,
     }
 }
 
+/* Nal unit order: all units are optional but in that order (cf. 7.4.1.2.3) */
+static int get_nal_order( int i_nal_type )
+{
+    static const int nal_orders[] = {
+        NAL_UNKNOWN, NAL_AU_DELIMITER, NAL_SPS, NAL_PPS
+    };
+
+    for( int i = 0; i < 4; ++i )
+        if( i_nal_type == nal_orders[i] )
+            return i;
+    return -1;
+}
+
+int h264_get_spspps( uint8_t *p_buf, size_t i_buf,
+                     uint8_t **pp_sps, size_t *p_sps_size,
+                     uint8_t **pp_pps, size_t *p_pps_size )
+{
+    int i_last_nal_order = 0;
+    uint8_t *p_sps = NULL, *p_pps = NULL;
+    bool b_is_annexb = false;
+
+    while( i_buf > 5 )
+    {
+        if( memcmp( p_buf, annexb_startcode, 4 ) == 0 )
+        {
+            int i_nal_type = p_buf[4] & 0x1F;
+
+            b_is_annexb = true;
+
+            if( i_nal_type == NAL_AU_DELIMITER ||
+                i_nal_type == NAL_SPS ||
+                i_nal_type == NAL_PPS )
+            {
+                int i_nal_order = get_nal_order( i_nal_type );
+
+                /* nal must be in order */
+                if( i_nal_order < i_last_nal_order )
+                    break;
+                /* pointer to the beginning of the sps/pps  */
+                if( i_nal_type == NAL_SPS && !p_sps )
+                    p_sps = p_buf;
+                if( i_nal_type == NAL_PPS && !p_pps )
+                    p_pps = p_buf;
+                i_last_nal_order = i_nal_order;
+            }
+            else
+            {
+                /* A non AU, SPS, PPS nal unit: stop parsing the annexB.
+                 * Return the pointer to the sps/pps if we found some */
+                if( !p_sps && !p_pps )
+                    break;
+                if( p_sps )
+                    *p_sps_size = (p_pps ? p_pps : p_buf) - p_sps;
+                if( p_pps )
+                    *p_pps_size = p_buf - p_pps;
+                *pp_sps = p_sps;
+                *pp_pps = p_pps;
+                return 0;
+            }
+            /* size of startcode + nal_type */
+            i_buf -= 5;
+            p_buf += 5;
+        } else {
+            i_buf--;
+            p_buf++;
+            if( !b_is_annexb )
+                break;
+        }
+    }
+    return -1;
+}
+
 bool h264_get_profile_level(const es_format_t *p_fmt, size_t *p_profile,
                             size_t *p_level, size_t *p_nal_size)
 {
diff --git a/modules/packetizer/h264_nal.h b/modules/packetizer/h264_nal.h
index 6358fe6..c991ddc 100644
--- a/modules/packetizer/h264_nal.h
+++ b/modules/packetizer/h264_nal.h
@@ -82,6 +82,12 @@ void convert_h264_to_annexb( uint8_t *p_buf, uint32_t i_len,
                              size_t i_nal_size,
                              struct H264ConvertState *state );
 
+/* Get the sps/pps pointers from an AnnexB buffer
+ * Returns 0 if a sps and/or a pps is found */
+int h264_get_spspps( uint8_t *p_buf, size_t i_buf,
+                     uint8_t **pp_sps, size_t *p_sps_size,
+                     uint8_t **pp_pps, size_t *p_pps_size );
+
 /* Get level and Profile */
 bool h264_get_profile_level(const es_format_t *p_fmt, size_t *p_profile,
                             size_t *p_level, size_t *p_nal_size);
-- 
2.1.3




More information about the vlc-devel mailing list