Commit 273e38d0 authored by François Cartegnie's avatar François Cartegnie 🤞

vlc_bits: rework for custom handler pos/remain accounting

parent 671789ae
...@@ -32,59 +32,140 @@ ...@@ -32,59 +32,140 @@
* This file defines functions, structures for handling streams of bits in vlc * This file defines functions, structures for handling streams of bits in vlc
*/ */
typedef struct bs_s bs_t;
typedef struct
{
/* forward read modifier (p_start, p_end, p_fwpriv, count, pos, remain) */
size_t (*pf_byte_forward)(bs_t *, size_t);
size_t (*pf_byte_pos)(const bs_t *);
size_t (*pf_byte_remain)(const bs_t *);
} bs_byte_callbacks_t;
typedef struct bs_s typedef struct bs_s
{ {
uint8_t *p_start; uint8_t *p_start;
uint8_t *p; uint8_t *p; /* points to currently read/written byte */
uint8_t *p_end; uint8_t *p_end;
ssize_t i_left; /* i_count number of available bits */ uint8_t i_left; /* i_count number of available bits */
bool b_read_only; bool b_read_only;
/* forward read modifier (p_start, p_end, p_fwpriv, count) */ bs_byte_callbacks_t cb;
uint8_t *(*pf_forward)(uint8_t *, uint8_t *, void *, size_t); void *p_priv;
void *p_fwpriv;
} bs_t; } bs_t;
static inline void bs_write_init( bs_t *s, void *p_data, size_t i_data ) static size_t bs_impl_bytes_forward( bs_t *s, size_t i_count )
{
if( s->p == NULL )
{
s->p = s->p_start;
return 1;
}
if( s->p >= s->p_end )
return 0;
if( (size_t) (s->p_end - s->p) < i_count )
i_count = s->p_end - s->p;
s->p += i_count;
return i_count;
}
static size_t bs_impl_bytes_remain( const bs_t *s )
{
if( s->p )
return s->p < s->p_end ? s->p_end - s->p - 1: 0;
else
return s->p_end - s->p_start;
}
static size_t bs_impl_bytes_pos( const bs_t *s )
{
if( s->p )
return s->p < s->p_end ? s->p - s->p_start + 1 : s->p - s->p_start;
else
return 0;
}
static inline void bs_init_custom( bs_t *s, const void *p_data, size_t i_data,
const bs_byte_callbacks_t *cb, void *priv )
{ {
s->p_start = (uint8_t *)p_data; s->p_start = (uint8_t *)p_data;
s->p = s->p_start; s->p = NULL;
s->p_end = s->p_start + i_data; s->p_end = s->p_start + i_data;
s->i_left = 8; s->i_left = 0;
s->b_read_only = false; s->b_read_only = true;
s->p_fwpriv = NULL; s->p_priv = priv;
s->pf_forward = NULL; s->cb = *cb;
} }
static inline void bs_init( bs_t *s, const void *p_data, size_t i_data ) static inline void bs_init( bs_t *s, const void *p_data, size_t i_data )
{ {
bs_write_init( s, (void*) p_data, i_data ); bs_byte_callbacks_t cb = {
s->b_read_only = true; bs_impl_bytes_forward,
bs_impl_bytes_pos,
bs_impl_bytes_remain,
};
bs_init_custom( s, p_data, i_data, &cb, NULL );
} }
static inline int bs_pos( const bs_t *s ) static inline void bs_write_init( bs_t *s, void *p_data, size_t i_data )
{ {
return( 8 * ( s->p - s->p_start ) + 8 - s->i_left ); bs_init( s, (const void *) p_data, i_data );
s->b_read_only = false;
} }
static inline int bs_remain( const bs_t *s ) static inline int bs_refill( bs_t *s )
{ {
if( s->p >= s->p_end ) if( s->i_left == 0 )
return 0; {
else if( s->cb.pf_byte_forward( s, 1 ) != 1 )
return( 8 * ( s->p_end - s->p ) - 8 + s->i_left ); return -1;
if( s->p < s->p_end )
s->i_left = 8;
}
return s->i_left > 0 ? 0 : 1;
}
static inline bool bs_eof( bs_t *s )
{
return bs_refill( s ) != 0;
} }
static inline int bs_eof( const bs_t *s ) static inline size_t bs_pos( const bs_t *s )
{ {
return( s->p >= s->p_end ? 1: 0 ); return 8 * s->cb.pf_byte_pos( s ) - s->i_left;
} }
#define bs_forward( s, i ) \ static inline size_t bs_remain( const bs_t *s )
s->p = s->pf_forward ? s->pf_forward( s->p, s->p_end, s->p_fwpriv, i ) : s->p + i {
return 8 * s->cb.pf_byte_remain( s ) + s->i_left;
}
static inline uint32_t bs_read( bs_t *s, int i_count ) static inline void bs_skip( bs_t *s, size_t i_count )
{
if( i_count == 0 )
return;
if( bs_refill( s ) )
return;
if( i_count > s->i_left )
{
i_count -= s->i_left;
s->i_left = 0;
if( i_count / 8 )
s->cb.pf_byte_forward( s, i_count / 8 );
i_count = i_count % 8;
if( i_count > 0 && !bs_refill( s ) )
s->i_left = 8 - i_count;
}
else s->i_left -= i_count;
}
static inline uint32_t bs_read( bs_t *s, uint8_t i_count )
{ {
static const uint32_t i_mask[33] = static const uint32_t i_mask[33] =
{ 0x00, { 0x00,
...@@ -96,7 +177,7 @@ static inline uint32_t bs_read( bs_t *s, int i_count ) ...@@ -96,7 +177,7 @@ static inline uint32_t bs_read( bs_t *s, int i_count )
0x1fffff, 0x3fffff, 0x7fffff, 0xffffff, 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff,
0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff, 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff,
0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff}; 0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff};
int i_shr, i_drop = 0; uint8_t i_shr, i_drop = 0;
uint32_t i_result = 0; uint32_t i_result = 0;
if( i_count > 32 ) if( i_count > 32 )
...@@ -107,87 +188,53 @@ static inline uint32_t bs_read( bs_t *s, int i_count ) ...@@ -107,87 +188,53 @@ static inline uint32_t bs_read( bs_t *s, int i_count )
while( i_count > 0 ) while( i_count > 0 )
{ {
if( s->p >= s->p_end ) if( bs_refill( s ) )
{
break; break;
}
if( ( i_shr = s->i_left - i_count ) >= 0 ) if( s->i_left > i_count )
{ {
i_shr = s->i_left - i_count;
/* more in the buffer than requested */ /* more in the buffer than requested */
i_result |= ( *s->p >> i_shr )&i_mask[i_count]; i_result |= ( *s->p >> i_shr )&i_mask[i_count];
s->i_left -= i_count; s->i_left -= i_count;
if( s->i_left == 0 )
{
bs_forward( s, 1 );
s->i_left = 8;
}
break; break;
} }
else else
{ {
i_shr = i_count - s->i_left;
/* less in the buffer than requested */ /* less in the buffer than requested */
if( -i_shr == 32 ) if( i_shr >= 32 )
i_result = 0; i_result = 0;
else else
i_result |= (*s->p&i_mask[s->i_left]) << -i_shr; i_result |= (*s->p&i_mask[s->i_left]) << i_shr;
i_count -= s->i_left; i_count -= s->i_left;
bs_forward( s, 1); s->i_left = 0;
s->i_left = 8;
} }
} }
if( i_drop ) if( i_drop )
bs_forward( s, i_drop ); bs_skip( s, i_drop );
return( i_result ); return( i_result );
} }
static inline uint32_t bs_read1( bs_t *s ) static inline uint32_t bs_read1( bs_t *s )
{ {
if( s->p < s->p_end ) if( bs_refill( s ) )
{ return 0;
unsigned int i_result; s->i_left--;
return ( *s->p >> s->i_left )&0x01;
s->i_left--;
i_result = ( *s->p >> s->i_left )&0x01;
if( s->i_left == 0 )
{
bs_forward( s, 1 );
s->i_left = 8;
}
return i_result;
}
return 0;
}
static inline void bs_skip( bs_t *s, ssize_t i_count )
{
s->i_left -= i_count;
if( s->i_left <= 0 )
{
const size_t i_bytes = 1 + s->i_left / -8;
bs_forward( s, i_bytes );
if( i_bytes * 8 < i_bytes /* ofw */ )
s->i_left = i_bytes;
else
s->i_left += 8 * i_bytes;
}
} }
static inline void bs_write( bs_t *s, int i_count, uint32_t i_bits ) static inline void bs_write( bs_t *s, uint8_t i_count, uint32_t i_bits )
{ {
if( s->b_read_only ) if( s->b_read_only )
return; return;
while( i_count > 0 ) while( i_count > 0 )
{ {
if( s->p >= s->p_end ) if( bs_refill( s ) )
{
break; break;
}
i_count--; i_count--;
...@@ -200,11 +247,6 @@ static inline void bs_write( bs_t *s, int i_count, uint32_t i_bits ) ...@@ -200,11 +247,6 @@ static inline void bs_write( bs_t *s, int i_count, uint32_t i_bits )
*s->p &= ~( 1 << ( s->i_left - 1 ) ); *s->p &= ~( 1 << ( s->i_left - 1 ) );
} }
s->i_left--; s->i_left--;
if( s->i_left == 0 )
{
bs_forward( s, 1 );
s->i_left = 8;
}
} }
} }
...@@ -215,28 +257,18 @@ static inline bool bs_aligned( bs_t *s ) ...@@ -215,28 +257,18 @@ static inline bool bs_aligned( bs_t *s )
static inline void bs_align( bs_t *s ) static inline void bs_align( bs_t *s )
{ {
if( s->i_left != 8 ) if( s->i_left % 8 )
{ s->i_left = 0;
s->i_left = 8;
s->p++;
}
} }
static inline void bs_align_0( bs_t *s ) static inline void bs_write_align( bs_t *s, uint8_t v )
{ {
if( s->i_left != 8 ) if( !s->b_read_only && (s->i_left % 8) )
{ bs_write( s, s->i_left, v ? 0xFF : 0 );
bs_write( s, s->i_left, 0 );
}
} }
static inline void bs_align_1( bs_t *s ) #define bs_align_0( s ) bs_write_align( s, 0 )
{ #define bs_align_1( s ) bs_write_align( s, 1 )
while( !s->b_read_only && s->i_left != 8 )
{
bs_write( s, 1, 1 );
}
}
/* Read unsigned Exp-Golomb code */ /* Read unsigned Exp-Golomb code */
static inline uint_fast32_t bs_read_ue( bs_t * bs ) static inline uint_fast32_t bs_read_ue( bs_t * bs )
......
...@@ -14,8 +14,10 @@ libpacketizer_h264_plugin_la_SOURCES = \ ...@@ -14,8 +14,10 @@ libpacketizer_h264_plugin_la_SOURCES = \
packetizer/h264.c packetizer/hxxx_nal.h \ packetizer/h264.c packetizer/hxxx_nal.h \
packetizer/hxxx_sei.c packetizer/hxxx_sei.h \ packetizer/hxxx_sei.c packetizer/hxxx_sei.h \
packetizer/hxxx_common.c packetizer/hxxx_common.h \ packetizer/hxxx_common.c packetizer/hxxx_common.h \
packetizer/hxxx_ep3b.h \
packetizer/iso_color_tables.h packetizer/iso_color_tables.h
libpacketizer_vc1_plugin_la_SOURCES = packetizer/vc1.c \ libpacketizer_vc1_plugin_la_SOURCES = packetizer/vc1.c \
packetizer/hxxx_ep3b.h \
packetizer/hxxx_nal.h packetizer/hxxx_nal.h
libpacketizer_mlp_plugin_la_SOURCES = packetizer/mlp.c libpacketizer_mlp_plugin_la_SOURCES = packetizer/mlp.c
libpacketizer_flac_plugin_la_SOURCES = packetizer/flac.c \ libpacketizer_flac_plugin_la_SOURCES = packetizer/flac.c \
...@@ -25,6 +27,7 @@ libpacketizer_hevc_plugin_la_SOURCES = packetizer/hevc.c \ ...@@ -25,6 +27,7 @@ libpacketizer_hevc_plugin_la_SOURCES = packetizer/hevc.c \
packetizer/hxxx_sei.c packetizer/hxxx_sei.h \ packetizer/hxxx_sei.c packetizer/hxxx_sei.h \
packetizer/hxxx_nal.h \ packetizer/hxxx_nal.h \
packetizer/hxxx_common.c packetizer/hxxx_common.h \ packetizer/hxxx_common.c packetizer/hxxx_common.h \
packetizer/hxxx_ep3b.h \
packetizer/iso_color_tables.h packetizer/iso_color_tables.h
libpacketizer_a52_plugin_la_SOURCES = packetizer/a52.c packetizer/a52.h libpacketizer_a52_plugin_la_SOURCES = packetizer/a52.c packetizer/a52.h
libpacketizer_dts_plugin_la_SOURCES = packetizer/dts.c \ libpacketizer_dts_plugin_la_SOURCES = packetizer/dts.c \
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "h264_nal.h" #include "h264_nal.h"
#include "hxxx_nal.h" #include "hxxx_nal.h"
#include "hxxx_ep3b.h"
#include "iso_color_tables.h" #include "iso_color_tables.h"
#include <vlc_bits.h> #include <vlc_bits.h>
...@@ -615,14 +616,13 @@ static bool h264_parse_picture_parameter_set_rbsp( bs_t *p_bs, ...@@ -615,14 +616,13 @@ static bool h264_parse_picture_parameter_set_rbsp( bs_t *p_bs,
if(likely(p_h264type)) \ if(likely(p_h264type)) \
{ \ { \
bs_t bs; \ bs_t bs; \
bs_init( &bs, p_buf, i_buf ); \ struct hxxx_bsfw_ep3b_ctx_s bsctx; \
unsigned i_bitflow = 0; \
if( b_escaped ) \ if( b_escaped ) \
{ \ { \
bs.p_fwpriv = &i_bitflow; \ hxxx_bsfw_ep3b_ctx_init( &bsctx ); \
bs.pf_forward = hxxx_bsfw_ep3b_to_rbsp; /* Does the emulated 3bytes conversion to rbsp */ \ bs_init_custom( &bs, p_buf, i_buf, &hxxx_bsfw_ep3b_callbacks, &bsctx );\
} \ } \
else (void) i_bitflow;\ else bs_init( &bs, p_buf, i_buf ); \
bs_skip( &bs, 8 ); /* Skip nal_unit_header */ \ bs_skip( &bs, 8 ); /* Skip nal_unit_header */ \
if( !decode( &bs, p_h264type ) ) \ if( !decode( &bs, p_h264type ) ) \
{ \ { \
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "h264_nal.h" #include "h264_nal.h"
#include "h264_slice.h" #include "h264_slice.h"
#include "hxxx_nal.h" #include "hxxx_nal.h"
#include "hxxx_ep3b.h"
bool h264_decode_slice( const uint8_t *p_buffer, size_t i_buffer, bool h264_decode_slice( const uint8_t *p_buffer, size_t i_buffer,
void (* get_sps_pps)(uint8_t, void *, void (* get_sps_pps)(uint8_t, void *,
...@@ -37,10 +38,9 @@ bool h264_decode_slice( const uint8_t *p_buffer, size_t i_buffer, ...@@ -37,10 +38,9 @@ bool h264_decode_slice( const uint8_t *p_buffer, size_t i_buffer,
int i_slice_type; int i_slice_type;
h264_slice_init( p_slice ); h264_slice_init( p_slice );
bs_t s; bs_t s;
unsigned i_bitflow = 0; struct hxxx_bsfw_ep3b_ctx_s bsctx;
bs_init( &s, p_buffer, i_buffer ); hxxx_bsfw_ep3b_ctx_init( &bsctx );
s.p_fwpriv = &i_bitflow; bs_init_custom( &s, p_buffer, i_buffer, &hxxx_bsfw_ep3b_callbacks, &bsctx );
s.pf_forward = hxxx_bsfw_ep3b_to_rbsp; /* Does the emulated 3bytes conversion to rbsp */
/* nal unit header */ /* nal unit header */
bs_skip( &s, 1 ); bs_skip( &s, 1 );
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "hevc_nal.h" #include "hevc_nal.h"
#include "hxxx_nal.h" #include "hxxx_nal.h"
#include "hxxx_ep3b.h"
#include "iso_color_tables.h" #include "iso_color_tables.h"
#include <vlc_common.h> #include <vlc_common.h>
...@@ -700,14 +701,13 @@ void hevc_rbsp_release_vps( hevc_video_parameter_set_t *p_vps ) ...@@ -700,14 +701,13 @@ void hevc_rbsp_release_vps( hevc_video_parameter_set_t *p_vps )
if(likely(p_hevctype)) \ if(likely(p_hevctype)) \
{ \ { \
bs_t bs; \ bs_t bs; \
bs_init( &bs, p_buf, i_buf ); \ struct hxxx_bsfw_ep3b_ctx_s bsctx; \
unsigned i_bitflow = 0; \
if( b_escaped ) \ if( b_escaped ) \
{ \ { \
bs.p_fwpriv = &i_bitflow; \ hxxx_bsfw_ep3b_ctx_init( &bsctx ); \
bs.pf_forward = hxxx_bsfw_ep3b_to_rbsp; /* Does the emulated 3bytes conversion to rbsp */ \ bs_init_custom( &bs, p_buf, i_buf, &hxxx_bsfw_ep3b_callbacks, &bsctx );\
} \ } \
else (void) i_bitflow;\ else bs_init( &bs, p_buf, i_buf ); \
bs_skip( &bs, 7 ); /* nal_unit_header */ \ bs_skip( &bs, 7 ); /* nal_unit_header */ \
uint8_t i_nuh_layer_id = bs_read( &bs, 6 ); \ uint8_t i_nuh_layer_id = bs_read( &bs, 6 ); \
bs_skip( &bs, 3 ); /* !nal_unit_header */ \ bs_skip( &bs, 3 ); /* !nal_unit_header */ \
...@@ -762,7 +762,7 @@ static bool hevc_parse_st_ref_pic_set( bs_t *p_bs, unsigned stRpsIdx, ...@@ -762,7 +762,7 @@ static bool hevc_parse_st_ref_pic_set( bs_t *p_bs, unsigned stRpsIdx,
{ {
nal_ue_t num_negative_pics = bs_read_ue( p_bs ); nal_ue_t num_negative_pics = bs_read_ue( p_bs );
nal_ue_t num_positive_pics = bs_read_ue( p_bs ); nal_ue_t num_positive_pics = bs_read_ue( p_bs );
if( bs_remain( p_bs ) < ((int64_t)num_negative_pics + num_positive_pics) * 2 ) if( bs_remain( p_bs ) < (num_negative_pics + num_positive_pics) * 2 )
return false; return false;
for(unsigned int i=0; i<num_negative_pics; i++) for(unsigned int i=0; i<num_negative_pics; i++)
{ {
...@@ -977,8 +977,8 @@ static bool hevc_parse_pic_parameter_set_rbsp( bs_t *p_bs, ...@@ -977,8 +977,8 @@ static bool hevc_parse_pic_parameter_set_rbsp( bs_t *p_bs,
p_pps->uniform_spacing_flag = bs_read1( p_bs ); p_pps->uniform_spacing_flag = bs_read1( p_bs );
if( !p_pps->uniform_spacing_flag ) if( !p_pps->uniform_spacing_flag )
{ {
if( bs_remain( p_bs ) < (int64_t) p_pps->num_tile_columns_minus1 + if( bs_remain( p_bs ) < p_pps->num_tile_columns_minus1 +
p_pps->num_tile_rows_minus1 + 1 ) p_pps->num_tile_rows_minus1 + 1 )
return false; return false;
for( unsigned i=0; i< p_pps->num_tile_columns_minus1; i++ ) for( unsigned i=0; i< p_pps->num_tile_columns_minus1; i++ )
(void) bs_read_ue( p_bs ); (void) bs_read_ue( p_bs );
...@@ -1296,14 +1296,13 @@ hevc_slice_segment_header_t * hevc_decode_slice_header( const uint8_t *p_buf, si ...@@ -1296,14 +1296,13 @@ hevc_slice_segment_header_t * hevc_decode_slice_header( const uint8_t *p_buf, si
if(likely(p_sh)) if(likely(p_sh))
{ {
bs_t bs; bs_t bs;
bs_init( &bs, p_buf, i_buf ); struct hxxx_bsfw_ep3b_ctx_s bsctx;
unsigned i_bitflow = 0;
if( b_escaped ) if( b_escaped )
{ {
bs.p_fwpriv = &i_bitflow; hxxx_bsfw_ep3b_ctx_init( &bsctx );
bs.pf_forward = hxxx_bsfw_ep3b_to_rbsp; /* Does the emulated 3bytes conversion to rbsp */ bs_init_custom( &bs, p_buf, i_buf, &hxxx_bsfw_ep3b_callbacks, &bsctx );
} }
else (void) i_bitflow; else bs_init( &bs, p_buf, i_buf );
bs_skip( &bs, 1 ); bs_skip( &bs, 1 );
p_sh->nal_type = bs_read( &bs, 6 ); p_sh->nal_type = bs_read( &bs, 6 );
p_sh->nuh_layer_id = bs_read( &bs, 6 ); p_sh->nuh_layer_id = bs_read( &bs, 6 );
...@@ -1359,10 +1358,9 @@ static void hevc_dcr_params_from_vps( const uint8_t * p_buffer, size_t i_buffer, ...@@ -1359,10 +1358,9 @@ static void hevc_dcr_params_from_vps( const uint8_t * p_buffer, size_t i_buffer,
return; return;
bs_t bs; bs_t bs;
bs_init( &bs, p_buffer, i_buffer ); struct hxxx_bsfw_ep3b_ctx_s bsctx;
unsigned i_bitflow = 0; hxxx_bsfw_ep3b_ctx_init( &bsctx );
bs.p_fwpriv = &i_bitflow; bs_init_custom( &bs, p_buffer, i_buffer, &hxxx_bsfw_ep3b_callbacks, &bsctx );
bs.pf_forward = hxxx_bsfw_ep3b_to_rbsp; /* Does the emulated 3bytes conversion to rbsp */
/* first two bytes are the NAL header, 3rd and 4th are: /* first two bytes are the NAL header, 3rd and 4th are:
vps_video_parameter_set_id(4) vps_video_parameter_set_id(4)
......
/*****************************************************************************
* hxxx_ep3b.h
*****************************************************************************
* Copyright (C) 2014-2015 VLC authors and VideoLAN
* 2018 VideoLabs
*
* 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 Lesser General Public License for more details.
*