vlc | branch: master | Francois Cartegnie <[email protected]> | 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; _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
