Commit c5ce9609 authored by François Cartegnie's avatar François Cartegnie 🤞

packetizer: hxxx: add NAL iterators

parent 5170e637
......@@ -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 );
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment