[vlc-commits] packetizer: hxxx: add NAL iterators

Francois Cartegnie git at videolan.org
Wed Oct 5 14:19:48 CEST 2016


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Tue Oct  4 23:22:09 2016 +0200| [c5ce96099428cdfed37365038f815f9abbb0b458] | committer: Francois Cartegnie

packetizer: hxxx: add NAL iterators

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

 modules/packetizer/hxxx_nal.h  | 65 ++++++++++++++++++++++++++++++
 test/modules/packetizer/hxxx.c | 90 ++++++++++++++++++++++++++++++++++++------
 2 files changed, 144 insertions(+), 11 deletions(-)

diff --git a/modules/packetizer/hxxx_nal.h b/modules/packetizer/hxxx_nal.h
index b8a6610..3da8cad 100644
--- a/modules/packetizer/hxxx_nal.h
+++ b/modules/packetizer/hxxx_nal.h
@@ -22,6 +22,7 @@
 
 #include <vlc_common.h>
 #include <vlc_es.h>
+#include "startcode_helper.h"
 
 static const uint8_t  annexb_startcode4[] = { 0x00, 0x00, 0x00, 0x01 };
 #define annexb_startcode3 (&annexb_startcode4[1])
@@ -247,6 +248,70 @@ static inline uint8_t * hxxx_ep3b_to_rbsp(const uint8_t *p_src, size_t i_src, si
 
 /* Declarations */
 
+typedef struct
+{
+    const uint8_t *p_head;
+    const uint8_t *p_tail;
+    uint8_t i_nal_length_size;
+} hxxx_iterator_ctx_t;
+
+static inline void hxxx_iterator_init( hxxx_iterator_ctx_t *p_ctx, const uint8_t *p_data, size_t i_data,
+                                       uint8_t i_nal_length_size )
+{
+    p_ctx->p_head = p_data;
+    p_ctx->p_tail = p_data + i_data;
+    if( popcount(i_nal_length_size) == 1 && i_nal_length_size <= 4 )
+        p_ctx->i_nal_length_size = i_nal_length_size;
+    else
+        p_ctx->i_nal_length_size = 0;
+}
+
+static inline bool hxxx_iterate_next( hxxx_iterator_ctx_t *p_ctx, const uint8_t **pp_start, size_t *pi_size )
+{
+    if( p_ctx->i_nal_length_size == 0 )
+        return false;
+
+    if( p_ctx->p_tail - p_ctx->p_head < p_ctx->i_nal_length_size )
+        return false;
+
+    size_t i_nal_size = 0;
+    for( uint8_t i=0; i < p_ctx->i_nal_length_size ; i++ )
+        i_nal_size = (i_nal_size << 8) | *p_ctx->p_head++;
+
+    if( (ptrdiff_t) i_nal_size > p_ctx->p_tail - p_ctx->p_head )
+        return false;
+
+    *pp_start = p_ctx->p_head;
+    *pi_size = i_nal_size;
+    p_ctx->p_head += i_nal_size;
+
+    return true;
+}
+
+static inline bool hxxx_annexb_iterate_next( hxxx_iterator_ctx_t *p_ctx, const uint8_t **pp_start, size_t *pi_size )
+{
+    if( !p_ctx->p_head )
+        return false;
+
+    p_ctx->p_head = startcode_FindAnyAnnexB( p_ctx->p_head, p_ctx->p_tail );
+    if( !p_ctx->p_head )
+        return false;
+
+    const uint8_t *p_end = startcode_FindAnyAnnexB( p_ctx->p_head + 3, p_ctx->p_tail );
+    if( !p_end )
+        p_end = p_ctx->p_tail;
+
+    /* fix 3 to 4 startcode offset and strip any trailing zeros */
+    while( p_end > p_ctx->p_head && p_end[-1] == 0 )
+        p_end--;
+
+    *pp_start = p_ctx->p_head;
+    *pi_size = p_end - p_ctx->p_head;
+    p_ctx->p_head = p_end;
+
+    return hxxx_strip_AnnexB_startcode( pp_start, pi_size );
+}
+
 /* Takes any AnnexB NAL buffer and converts it to prefixed size (AVC/HEVC) */
 block_t *hxxx_AnnexB_to_xVC( block_t *p_block, uint8_t i_nal_length_size );
 
diff --git a/test/modules/packetizer/hxxx.c b/test/modules/packetizer/hxxx.c
index a0ea85a..93362a1 100644
--- a/test/modules/packetizer/hxxx.c
+++ b/test/modules/packetizer/hxxx.c
@@ -18,7 +18,6 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
-#include "../../libvlc/test.h"
 #ifdef NDEBUG
  #undef NDEBUG
 #endif
@@ -28,6 +27,56 @@
 #include "../modules/packetizer/hxxx_nal.h"
 #include "../modules/packetizer/hxxx_nal.c"
 
+static void test_iterators( const uint8_t *p_ab, size_t i_ab, /* AnnexB */
+                            const uint8_t **pp_prefix, size_t *pi_prefix /* Prefixed */ )
+{
+    printf("INPUT SET    : ");
+    for(size_t j=0; j<i_ab; j++)
+        printf("0x%.2x, ", p_ab[j] );
+    printf("\n");
+
+    for( unsigned int i=0; i<3; i++)
+    {
+        const uint8_t *p_prefix = pp_prefix[i];
+        size_t i_prefix = pi_prefix[i];
+
+        printf("Test with prefix len %d:\n", 1 << i);
+
+        hxxx_iterator_ctx_t it_ab;
+        hxxx_iterator_init( &it_ab, p_ab, i_ab, 0 );
+
+        hxxx_iterator_ctx_t it_prefix;
+        hxxx_iterator_init( &it_prefix, p_prefix, i_prefix, 1 << i );
+
+        const uint8_t *p_start_ab; size_t i_size_ab;
+        const uint8_t *p_start_prefix; size_t i_size_prefix;
+
+        bool b1 = true;
+        bool b2 = true;
+
+        int i_nal = 0;
+        while(b1 && b2)
+        {
+            b1 = hxxx_annexb_iterate_next( &it_ab, &p_start_ab, &i_size_ab );
+            b2 = hxxx_iterate_next( &it_prefix, &p_start_prefix, &i_size_prefix );
+            printf("NAL %d ", i_nal++);
+            if( b1 != b2 )
+                printf(", returns %d != %d\n", b1, b2);
+            assert(b1 == b2);
+            if( b1 && b2 )
+            {
+                assert(i_size_ab == i_size_prefix);
+                assert(memcmp(p_start_ab, p_start_prefix, i_size_ab) == 0);
+                for(size_t j=0; j<i_size_ab; j++)
+                    printf("0x%.2x, ", p_start_ab[j] );
+                printf("\n");
+            }
+        }
+        printf("\n");
+
+    }
+}
+
 static void testannexbin( const uint8_t *p_data, size_t i_data,
                           const uint8_t **pp_res, size_t *pi_res )
 {
@@ -65,12 +114,12 @@ static void testannexbin( const uint8_t *p_data, size_t i_data,
         }
     }
 }
-#define runtest(number, name) \
+#define runtest(number, name, testfunction) \
     printf("\nTEST %d %s\n", number, name);\
     p_res[0] = test##number##_avcdata1;  rgi_res[0] = sizeof(test##number##_avcdata1);\
     p_res[1] = test##number##_avcdata2;  rgi_res[1] = sizeof(test##number##_avcdata2);\
     p_res[2] = test##number##_avcdata4;  rgi_res[2] = sizeof(test##number##_avcdata4);\
-    testannexbin( test##number##_annexbdata, sizeof(test##number##_annexbdata), \
+    testfunction( test##number##_annexbdata, sizeof(test##number##_annexbdata), \
                   p_res, rgi_res )
 
 static void test_annexb()
@@ -130,18 +179,37 @@ static void test_annexb()
     const uint8_t test6_avcdata2[] =   { 0, 1, 0x11, 0, 0, 0, 0 };
     const uint8_t test6_avcdata4[] =   { 0, 0, 0, 1, 0x11, 0, 0, 0, 0, 0, 0, 0, 0 };
 
-    runtest(4, "empty nal test");
-    runtest(2, "single nal test");
-    runtest(3, "single nal test, startcode 3");
-    runtest(5, "4 bytes prefixed nal only (4 prefix optz)");
-    runtest(1, "mixed nal set");
-    runtest(6, "startcode repeat / empty nal");
+    /* empty nal variation test */
+    const uint8_t test7_annexbdata[] = { 0, 0, 0, 1 };
+    const uint8_t test7_avcdata1[]   = { 0 };
+    const uint8_t test7_avcdata2[]   = { 0, 0 };
+    const uint8_t test7_avcdata4[]   = { 0, 0, 0, 0 };
+
+    runtest(4, "empty nal test", testannexbin);
+    runtest(2, "single nal test", testannexbin);
+    runtest(3, "single nal test, startcode 3", testannexbin);
+    runtest(5, "4 bytes prefixed nal only (4 prefix optz)", testannexbin);
+    runtest(1, "mixed nal set", testannexbin);
+    runtest(6, "startcode repeat / empty nal", testannexbin);
+
+    runtest(1, "IT mixed nal set", test_iterators);
+    runtest(2, "IT single nal test", test_iterators);
+    runtest(3, "IT single nal test, startcode 3", test_iterators);
+    runtest(4, "IT empty nal test", test_iterators);
+    runtest(5, "IT 4 bytes prefixed nal only (4 prefix optz)", test_iterators);
+    runtest(6, "startcode repeat / empty nal", test_iterators);
+    runtest(7, "IT empty nal", test_iterators);
+
+    printf("\nTEST 8 borkage test\n");\
+    rgi_res[0] = 0;
+    rgi_res[1] = rgi_res[2] = 1;
+    p_res[0] = NULL;
+    p_res[1] = p_res[2] = test7_avcdata1;
+    test_iterators( NULL, 0, p_res, rgi_res );
 }
 
 int main( void )
 {
-    test_init();
-
     test_annexb();
 
     return 0;



More information about the vlc-commits mailing list