[vlc-commits] vlc_bits: rework for custom handler pos/remain accounting
Francois Cartegnie
git at videolan.org
Mon Aug 20 16:53:22 CEST 2018
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Fri Aug 10 14:51:33 2018 +0200| [273e38d0c35a65f11cdc524ce4e664b60fc0d982] | committer: Francois Cartegnie
vlc_bits: rework for custom handler pos/remain accounting
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=273e38d0c35a65f11cdc524ce4e664b60fc0d982
---
include/vlc_bits.h | 224 +++++++++++++++++++++++-----------------
modules/packetizer/Makefile.am | 3 +
modules/packetizer/h264_nal.c | 10 +-
modules/packetizer/h264_slice.c | 8 +-
modules/packetizer/hevc_nal.c | 32 +++---
modules/packetizer/hxxx_ep3b.h | 137 ++++++++++++++++++++++++
modules/packetizer/hxxx_nal.h | 48 ---------
modules/packetizer/hxxx_sei.c | 24 ++---
modules/packetizer/vc1.c | 25 ++---
test/src/misc/bits.c | 24 +++--
10 files changed, 327 insertions(+), 208 deletions(-)
diff --git a/include/vlc_bits.h b/include/vlc_bits.h
index 1e3d845b3a..7a941933fc 100644
--- a/include/vlc_bits.h
+++ b/include/vlc_bits.h
@@ -32,59 +32,140 @@
* 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
{
uint8_t *p_start;
- uint8_t *p;
+ uint8_t *p; /* points to currently read/written byte */
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;
- /* forward read modifier (p_start, p_end, p_fwpriv, count) */
- uint8_t *(*pf_forward)(uint8_t *, uint8_t *, void *, size_t);
- void *p_fwpriv;
+ bs_byte_callbacks_t cb;
+ void *p_priv;
} 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 = s->p_start;
+ s->p = NULL;
s->p_end = s->p_start + i_data;
- s->i_left = 8;
- s->b_read_only = false;
- s->p_fwpriv = NULL;
- s->pf_forward = NULL;
+ s->i_left = 0;
+ s->b_read_only = true;
+ s->p_priv = priv;
+ s->cb = *cb;
}
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 );
- s->b_read_only = true;
+ bs_byte_callbacks_t cb = {
+ 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 )
- return 0;
- else
- return( 8 * ( s->p_end - s->p ) - 8 + s->i_left );
+ if( s->i_left == 0 )
+ {
+ if( s->cb.pf_byte_forward( s, 1 ) != 1 )
+ 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 ) \
- s->p = s->pf_forward ? s->pf_forward( s->p, s->p_end, s->p_fwpriv, i ) : s->p + i
+static inline size_t bs_remain( const bs_t *s )
+{
+ 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] =
{ 0x00,
@@ -96,7 +177,7 @@ static inline uint32_t bs_read( bs_t *s, int i_count )
0x1fffff, 0x3fffff, 0x7fffff, 0xffffff,
0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff,
0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff};
- int i_shr, i_drop = 0;
+ uint8_t i_shr, i_drop = 0;
uint32_t i_result = 0;
if( i_count > 32 )
@@ -107,87 +188,53 @@ static inline uint32_t bs_read( bs_t *s, int i_count )
while( i_count > 0 )
{
- if( s->p >= s->p_end )
- {
+ if( bs_refill( s ) )
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 */
i_result |= ( *s->p >> i_shr )&i_mask[i_count];
s->i_left -= i_count;
- if( s->i_left == 0 )
- {
- bs_forward( s, 1 );
- s->i_left = 8;
- }
break;
}
else
{
+ i_shr = i_count - s->i_left;
/* less in the buffer than requested */
- if( -i_shr == 32 )
+ if( i_shr >= 32 )
i_result = 0;
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;
- bs_forward( s, 1);
- s->i_left = 8;
+ s->i_left = 0;
}
}
if( i_drop )
- bs_forward( s, i_drop );
+ bs_skip( s, i_drop );
return( i_result );
}
static inline uint32_t bs_read1( bs_t *s )
{
- if( s->p < s->p_end )
- {
- unsigned int i_result;
-
- 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;
- }
+ if( bs_refill( s ) )
+ return 0;
+ s->i_left--;
+ return ( *s->p >> s->i_left )&0x01;
}
-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 )
return;
while( i_count > 0 )
{
- if( s->p >= s->p_end )
- {
+ if( bs_refill( s ) )
break;
- }
i_count--;
@@ -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->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 )
static inline void bs_align( bs_t *s )
{
- if( s->i_left != 8 )
- {
- s->i_left = 8;
- s->p++;
- }
+ if( s->i_left % 8 )
+ s->i_left = 0;
}
-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 )
- {
- bs_write( s, s->i_left, 0 );
- }
+ if( !s->b_read_only && (s->i_left % 8) )
+ bs_write( s, s->i_left, v ? 0xFF : 0 );
}
-static inline void bs_align_1( bs_t *s )
-{
- while( !s->b_read_only && s->i_left != 8 )
- {
- bs_write( s, 1, 1 );
- }
-}
+#define bs_align_0( s ) bs_write_align( s, 0 )
+#define bs_align_1( s ) bs_write_align( s, 1 )
/* Read unsigned Exp-Golomb code */
static inline uint_fast32_t bs_read_ue( bs_t * bs )
diff --git a/modules/packetizer/Makefile.am b/modules/packetizer/Makefile.am
index 4945ed7aca..0551c4d0a7 100644
--- a/modules/packetizer/Makefile.am
+++ b/modules/packetizer/Makefile.am
@@ -14,8 +14,10 @@ libpacketizer_h264_plugin_la_SOURCES = \
packetizer/h264.c packetizer/hxxx_nal.h \
packetizer/hxxx_sei.c packetizer/hxxx_sei.h \
packetizer/hxxx_common.c packetizer/hxxx_common.h \
+ packetizer/hxxx_ep3b.h \
packetizer/iso_color_tables.h
libpacketizer_vc1_plugin_la_SOURCES = packetizer/vc1.c \
+ packetizer/hxxx_ep3b.h \
packetizer/hxxx_nal.h
libpacketizer_mlp_plugin_la_SOURCES = packetizer/mlp.c
libpacketizer_flac_plugin_la_SOURCES = packetizer/flac.c \
@@ -25,6 +27,7 @@ libpacketizer_hevc_plugin_la_SOURCES = packetizer/hevc.c \
packetizer/hxxx_sei.c packetizer/hxxx_sei.h \
packetizer/hxxx_nal.h \
packetizer/hxxx_common.c packetizer/hxxx_common.h \
+ packetizer/hxxx_ep3b.h \
packetizer/iso_color_tables.h
libpacketizer_a52_plugin_la_SOURCES = packetizer/a52.c packetizer/a52.h
libpacketizer_dts_plugin_la_SOURCES = packetizer/dts.c \
diff --git a/modules/packetizer/h264_nal.c b/modules/packetizer/h264_nal.c
index d5144c69d8..74d4ba6b85 100644
--- a/modules/packetizer/h264_nal.c
+++ b/modules/packetizer/h264_nal.c
@@ -25,6 +25,7 @@
#include "h264_nal.h"
#include "hxxx_nal.h"
+#include "hxxx_ep3b.h"
#include "iso_color_tables.h"
#include <vlc_bits.h>
@@ -615,14 +616,13 @@ static bool h264_parse_picture_parameter_set_rbsp( bs_t *p_bs,
if(likely(p_h264type)) \
{ \
bs_t bs; \
- bs_init( &bs, p_buf, i_buf ); \
- unsigned i_bitflow = 0; \
+ struct hxxx_bsfw_ep3b_ctx_s bsctx; \
if( b_escaped ) \
{ \
- bs.p_fwpriv = &i_bitflow; \
- bs.pf_forward = hxxx_bsfw_ep3b_to_rbsp; /* Does the emulated 3bytes conversion to rbsp */ \
+ hxxx_bsfw_ep3b_ctx_init( &bsctx ); \
+ 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 */ \
if( !decode( &bs, p_h264type ) ) \
{ \
diff --git a/modules/packetizer/h264_slice.c b/modules/packetizer/h264_slice.c
index d05256e93e..91b43a3a7e 100644
--- a/modules/packetizer/h264_slice.c
+++ b/modules/packetizer/h264_slice.c
@@ -27,6 +27,7 @@
#include "h264_nal.h"
#include "h264_slice.h"
#include "hxxx_nal.h"
+#include "hxxx_ep3b.h"
bool h264_decode_slice( const uint8_t *p_buffer, size_t i_buffer,
void (* get_sps_pps)(uint8_t, void *,
@@ -37,10 +38,9 @@ bool h264_decode_slice( const uint8_t *p_buffer, size_t i_buffer,
int i_slice_type;
h264_slice_init( p_slice );
bs_t s;
- unsigned i_bitflow = 0;
- bs_init( &s, p_buffer, i_buffer );
- s.p_fwpriv = &i_bitflow;
- s.pf_forward = hxxx_bsfw_ep3b_to_rbsp; /* Does the emulated 3bytes conversion to rbsp */
+ struct hxxx_bsfw_ep3b_ctx_s bsctx;
+ hxxx_bsfw_ep3b_ctx_init( &bsctx );
+ bs_init_custom( &s, p_buffer, i_buffer, &hxxx_bsfw_ep3b_callbacks, &bsctx );
/* nal unit header */
bs_skip( &s, 1 );
diff --git a/modules/packetizer/hevc_nal.c b/modules/packetizer/hevc_nal.c
index bc47f79e55..1a281b74ec 100644
--- a/modules/packetizer/hevc_nal.c
+++ b/modules/packetizer/hevc_nal.c
@@ -23,6 +23,7 @@
#include "hevc_nal.h"
#include "hxxx_nal.h"
+#include "hxxx_ep3b.h"
#include "iso_color_tables.h"
#include <vlc_common.h>
@@ -700,14 +701,13 @@ void hevc_rbsp_release_vps( hevc_video_parameter_set_t *p_vps )
if(likely(p_hevctype)) \
{ \
bs_t bs; \
- bs_init( &bs, p_buf, i_buf ); \
- unsigned i_bitflow = 0; \
+ struct hxxx_bsfw_ep3b_ctx_s bsctx; \
if( b_escaped ) \
{ \
- bs.p_fwpriv = &i_bitflow; \
- bs.pf_forward = hxxx_bsfw_ep3b_to_rbsp; /* Does the emulated 3bytes conversion to rbsp */ \
+ hxxx_bsfw_ep3b_ctx_init( &bsctx ); \
+ 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 */ \
uint8_t i_nuh_layer_id = bs_read( &bs, 6 ); \
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,
{
nal_ue_t num_negative_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;
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,
p_pps->uniform_spacing_flag = bs_read1( p_bs );
if( !p_pps->uniform_spacing_flag )
{
- if( bs_remain( p_bs ) < (int64_t) p_pps->num_tile_columns_minus1 +
- p_pps->num_tile_rows_minus1 + 1 )
+ if( bs_remain( p_bs ) < p_pps->num_tile_columns_minus1 +
+ p_pps->num_tile_rows_minus1 + 1 )
return false;
for( unsigned i=0; i< p_pps->num_tile_columns_minus1; i++ )
(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
if(likely(p_sh))
{
bs_t bs;
- bs_init( &bs, p_buf, i_buf );
- unsigned i_bitflow = 0;
+ struct hxxx_bsfw_ep3b_ctx_s bsctx;
if( b_escaped )
{
- bs.p_fwpriv = &i_bitflow;
- bs.pf_forward = hxxx_bsfw_ep3b_to_rbsp; /* Does the emulated 3bytes conversion to rbsp */
+ hxxx_bsfw_ep3b_ctx_init( &bsctx );
+ 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 );
p_sh->nal_type = 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,
return;
bs_t bs;
- bs_init( &bs, p_buffer, i_buffer );
- unsigned i_bitflow = 0;
- bs.p_fwpriv = &i_bitflow;
- bs.pf_forward = hxxx_bsfw_ep3b_to_rbsp; /* Does the emulated 3bytes conversion to rbsp */
+ struct hxxx_bsfw_ep3b_ctx_s bsctx;
+ hxxx_bsfw_ep3b_ctx_init( &bsctx );
+ bs_init_custom( &bs, p_buffer, i_buffer, &hxxx_bsfw_ep3b_callbacks, &bsctx );
/* first two bytes are the NAL header, 3rd and 4th are:
vps_video_parameter_set_id(4)
diff --git a/modules/packetizer/hxxx_ep3b.h b/modules/packetizer/hxxx_ep3b.h
new file mode 100644
index 0000000000..6e134b65a0
--- /dev/null
+++ b/modules/packetizer/hxxx_ep3b.h
@@ -0,0 +1,137 @@
+/*****************************************************************************
+ * 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+#include <vlc_bits.h>
+
+static inline uint8_t *hxxx_ep3b_to_rbsp( uint8_t *p, uint8_t *end, unsigned *pi_prev, size_t i_count )
+{
+ for( size_t i=0; i<i_count; i++ )
+ {
+ if( ++p >= end )
+ return p;
+
+ *pi_prev = (*pi_prev << 1) | (!*p);
+
+ if( *p == 0x03 &&
+ ( p + 1 ) != end ) /* Never escape sequence if no next byte */
+ {
+ if( (*pi_prev & 0x06) == 0x06 )
+ {
+ ++p;
+ *pi_prev = ((*pi_prev >> 1) << 1) | (!*p);
+ }
+ }
+ }
+ return p;
+}
+
+#if 0
+/* Discards emulation prevention three bytes */
+static inline uint8_t * hxxx_ep3b_to_rbsp(const uint8_t *p_src, size_t i_src, size_t *pi_ret)
+{
+ uint8_t *p_dst;
+ if(!p_src || !(p_dst = malloc(i_src)))
+ return NULL;
+
+ size_t j = 0;
+ for (size_t i = 0; i < i_src; i++) {
+ if (i < i_src - 3 &&
+ p_src[i] == 0 && p_src[i+1] == 0 && p_src[i+2] == 3) {
+ p_dst[j++] = 0;
+ p_dst[j++] = 0;
+ i += 2;
+ continue;
+ }
+ p_dst[j++] = p_src[i];
+ }
+ *pi_ret = j;
+ return p_dst;
+}
+#endif
+
+/* vlc_bits's bs_t forward callback for stripping emulation prevention three bytes */
+struct hxxx_bsfw_ep3b_ctx_s
+{
+ unsigned i_prev;
+ size_t i_bytepos;
+ size_t i_bytesize;
+};
+
+static void hxxx_bsfw_ep3b_ctx_init( struct hxxx_bsfw_ep3b_ctx_s *ctx )
+{
+ ctx->i_prev = 0;
+ ctx->i_bytepos = 0;
+ ctx->i_bytesize = 0;
+}
+
+static size_t hxxx_ep3b_total_size( const uint8_t *p, const uint8_t *p_end )
+{
+ /* compute final size */
+ unsigned i_prev = 0;
+ size_t i = 0;
+ while( p < p_end )
+ {
+ uint8_t *n = hxxx_ep3b_to_rbsp( (uint8_t *)p, (uint8_t *)p_end, &i_prev, 1 );
+ if( n > p )
+ ++i;
+ p = n;
+ }
+ return i;
+}
+
+static size_t hxxx_bsfw_byte_forward_ep3b( bs_t *s, size_t i_count )
+{
+ struct hxxx_bsfw_ep3b_ctx_s *ctx = (struct hxxx_bsfw_ep3b_ctx_s *) s->p_priv;
+ if( s->p == NULL )
+ {
+ ctx->i_bytesize = hxxx_ep3b_total_size( s->p_start, s->p_end );
+ s->p = s->p_start;
+ ctx->i_bytepos = 1;
+ return 1;
+ }
+
+ if( s->p >= s->p_end )
+ return 0;
+
+ s->p = hxxx_ep3b_to_rbsp( s->p, s->p_end, &ctx->i_prev, i_count );
+ ctx->i_bytepos += i_count;
+ return i_count;
+}
+
+static size_t hxxx_bsfw_byte_pos_ep3b( const bs_t *s )
+{
+ struct hxxx_bsfw_ep3b_ctx_s *ctx = (struct hxxx_bsfw_ep3b_ctx_s *) s->p_priv;
+ return ctx->i_bytepos;
+}
+
+static size_t hxxx_bsfw_byte_remain_ep3b( const bs_t *s )
+{
+ struct hxxx_bsfw_ep3b_ctx_s *ctx = (struct hxxx_bsfw_ep3b_ctx_s *) s->p_priv;
+ if( ctx->i_bytesize == 0 && s->p_start != s->p_end )
+ ctx->i_bytesize = hxxx_ep3b_total_size( s->p_start, s->p_end );
+ return ctx->i_bytesize - ctx->i_bytepos;
+}
+
+static const bs_byte_callbacks_t hxxx_bsfw_ep3b_callbacks =
+{
+ hxxx_bsfw_byte_forward_ep3b,
+ hxxx_bsfw_byte_pos_ep3b,
+ hxxx_bsfw_byte_remain_ep3b,
+};
diff --git a/modules/packetizer/hxxx_nal.h b/modules/packetizer/hxxx_nal.h
index 4da89a01b7..81ef497f49 100644
--- a/modules/packetizer/hxxx_nal.h
+++ b/modules/packetizer/hxxx_nal.h
@@ -53,54 +53,6 @@ static inline bool hxxx_strip_AnnexB_startcode( const uint8_t **pp_data, size_t
return false;
}
-/* vlc_bits's bs_t forward callback for stripping emulation prevention three bytes */
-static inline uint8_t *hxxx_bsfw_ep3b_to_rbsp( uint8_t *p, uint8_t *end, void *priv, size_t i_count )
-{
- unsigned *pi_prev = (unsigned *) priv;
- for( size_t i=0; i<i_count; i++ )
- {
- if( ++p >= end )
- return p;
-
- *pi_prev = (*pi_prev << 1) | (!*p);
-
- if( *p == 0x03 &&
- ( p + 1 ) != end ) /* Never escape sequence if no next byte */
- {
- if( (*pi_prev & 0x06) == 0x06 )
- {
- ++p;
- *pi_prev = ((*pi_prev >> 1) << 1) | (!*p);
- }
- }
- }
- return p;
-}
-
-#if 0
-/* Discards emulation prevention three bytes */
-static inline uint8_t * hxxx_ep3b_to_rbsp(const uint8_t *p_src, size_t i_src, size_t *pi_ret)
-{
- uint8_t *p_dst;
- if(!p_src || !(p_dst = malloc(i_src)))
- return NULL;
-
- size_t j = 0;
- for (size_t i = 0; i < i_src; i++) {
- if (i < i_src - 3 &&
- p_src[i] == 0 && p_src[i+1] == 0 && p_src[i+2] == 3) {
- p_dst[j++] = 0;
- p_dst[j++] = 0;
- i += 2;
- continue;
- }
- p_dst[j++] = p_src[i];
- }
- *pi_ret = j;
- return p_dst;
-}
-#endif
-
/* Declarations */
typedef struct
diff --git a/modules/packetizer/hxxx_sei.c b/modules/packetizer/hxxx_sei.c
index 18a249cdaa..79cfa91b3d 100644
--- a/modules/packetizer/hxxx_sei.c
+++ b/modules/packetizer/hxxx_sei.c
@@ -22,11 +22,12 @@
#endif
#include <vlc_common.h>
-#include <vlc_bits.h>
#include <vlc_block.h>
+#include <vlc_bits.h>
#include "hxxx_sei.h"
#include "hxxx_nal.h"
+#include "hxxx_ep3b.h"
void HxxxParse_AnnexB_SEI(const uint8_t *p_buf, size_t i_buf,
uint8_t i_header, pf_hxxx_sei_callback cb, void *cbdata)
@@ -38,30 +39,17 @@ void HxxxParse_AnnexB_SEI(const uint8_t *p_buf, size_t i_buf,
void HxxxParseSEI(const uint8_t *p_buf, size_t i_buf,
uint8_t i_header, pf_hxxx_sei_callback pf_callback, void *cbdata)
{
- bs_t s_ep3b;
bs_t s;
- unsigned i_bitflow = 0;
bool b_continue = true;
- char buf[256];
- int i = 0;
if( i_buf <= i_header )
return;
- bs_init( &s_ep3b, &p_buf[i_header], i_buf - i_header ); /* skip nal unit header */
- s_ep3b.p_fwpriv = &i_bitflow;
- s_ep3b.pf_forward = hxxx_bsfw_ep3b_to_rbsp; /* Does the emulated 3bytes conversion to rbsp */
-
- /* While a NAL can technically be up to 65535 bytes, an SEI NAL
- will never be anywhere near that size */
- if (bs_remain(&s_ep3b) / 8 > sizeof(buf))
- return;
-
- while (bs_remain(&s_ep3b) > 0)
- buf[i++] = bs_read(&s_ep3b, 8);
+ struct hxxx_bsfw_ep3b_ctx_s bsctx;
+ hxxx_bsfw_ep3b_ctx_init( &bsctx );
+ bs_init_custom( &s, &p_buf[i_header], i_buf - i_header, /* skip nal unit header */
+ &hxxx_bsfw_ep3b_callbacks, &bsctx );
- /* Parse the resulting RBSP bytes as SEI */
- bs_init( &s, buf, i);
while( bs_remain( &s ) >= 8 && bs_aligned( &s ) && b_continue )
{
diff --git a/modules/packetizer/vc1.c b/modules/packetizer/vc1.c
index 53b5bc1836..6f70214f73 100644
--- a/modules/packetizer/vc1.c
+++ b/modules/packetizer/vc1.c
@@ -40,6 +40,7 @@
#include "../codec/cc.h"
#include "packetizer_helper.h"
#include "hxxx_nal.h"
+#include "hxxx_ep3b.h"
#include "startcode_helper.h"
/*****************************************************************************
@@ -327,6 +328,7 @@ static void BuildExtraData( decoder_t *p_dec )
memcpy( (uint8_t*)p_es->p_extra + p_sys->sh.p_sh->i_buffer,
p_sys->ep.p_ep->p_buffer, p_sys->ep.p_ep->i_buffer );
}
+
/* ParseIDU: parse an Independent Decoding Unit */
static block_t *ParseIDU( decoder_t *p_dec, bool *pb_ts_used, block_t *p_frag )
{
@@ -438,7 +440,6 @@ static block_t *ParseIDU( decoder_t *p_dec, bool *pb_ts_used, block_t *p_frag )
{
es_format_t *p_es = &p_dec->fmt_out;
bs_t s;
- unsigned i_bitflow = 0;
int i_profile;
/* */
@@ -473,9 +474,10 @@ static block_t *ParseIDU( decoder_t *p_dec, bool *pb_ts_used, block_t *p_frag )
}
/* Parse it */
- bs_init( &s, &p_frag->p_buffer[4], p_frag->i_buffer - 4 );
- s.p_fwpriv = &i_bitflow;
- s.pf_forward = hxxx_bsfw_ep3b_to_rbsp; /* Does the emulated 3bytes conversion to rbsp */
+ struct hxxx_bsfw_ep3b_ctx_s bsctx;
+ hxxx_bsfw_ep3b_ctx_init( &bsctx );
+ bs_init_custom( &s, &p_frag->p_buffer[4], p_frag->i_buffer - 4,
+ &hxxx_bsfw_ep3b_callbacks, &bsctx );
i_profile = bs_read( &s, 2 );
if( i_profile == 3 )
@@ -645,12 +647,12 @@ static block_t *ParseIDU( decoder_t *p_dec, bool *pb_ts_used, block_t *p_frag )
else if( idu == IDU_TYPE_FRAME )
{
bs_t s;
- unsigned i_bitflow = 0;
/* Parse it + interpolate pts/dts if possible */
- bs_init( &s, &p_frag->p_buffer[4], p_frag->i_buffer - 4 );
- s.p_fwpriv = &i_bitflow;
- s.pf_forward = hxxx_bsfw_ep3b_to_rbsp; /* Does the emulated 3bytes conversion to rbsp */
+ struct hxxx_bsfw_ep3b_ctx_s bsctx;
+ hxxx_bsfw_ep3b_ctx_init( &bsctx );
+ bs_init_custom( &s, &p_frag->p_buffer[4], p_frag->i_buffer - 4,
+ &hxxx_bsfw_ep3b_callbacks, &bsctx );
if( p_sys->sh.b_advanced_profile )
{
@@ -724,11 +726,10 @@ static block_t *ParseIDU( decoder_t *p_dec, bool *pb_ts_used, block_t *p_frag )
else if( idu == IDU_TYPE_FRAME_USER_DATA )
{
bs_t s;
- unsigned i_bitflow = 0;
const size_t i_size = p_frag->i_buffer - 4;
- bs_init( &s, &p_frag->p_buffer[4], i_size );
- s.p_fwpriv = &i_bitflow;
- s.pf_forward = hxxx_bsfw_ep3b_to_rbsp; /* Does the emulated 3bytes conversion to rbsp */
+ struct hxxx_bsfw_ep3b_ctx_s bsctx;
+ hxxx_bsfw_ep3b_ctx_init( &bsctx );
+ bs_init_custom( &s, &p_frag->p_buffer[4], i_size, &hxxx_bsfw_ep3b_callbacks, &bsctx );
unsigned i_data;
uint8_t *p_data = malloc( i_size );
diff --git a/test/src/misc/bits.c b/test/src/misc/bits.c
index bd64eaefb3..18ff7d6574 100644
--- a/test/src/misc/bits.c
+++ b/test/src/misc/bits.c
@@ -29,16 +29,24 @@
return 1; \
} } while( 0 )
-static uint8_t *skip1( uint8_t *p, uint8_t *end, void *priv, size_t i_count )
+static size_t skip1( bs_t *s, size_t i_count )
{
- (void) priv;
- for( size_t i=0; i<i_count; i++ )
+ if( s->p == NULL )
{
- p += 2;
- if( p >= end )
- return p;
+ s->p = s->p_start;
+ return 1 + skip1( s, i_count - 1 );
+ }
+
+ if( s->p_end - s->p > (ssize_t) i_count * 2 )
+ {
+ s->p += i_count * 2;
+ return i_count;
+ }
+ else
+ {
+ s->p = s->p_end;
+ return 0;
}
- return p;
}
int main( void )
@@ -126,7 +134,7 @@ int main( void )
const uint8_t ok[6] = { 0xAA, 0xCC, 0xEE, /* ovfw fillers */ 0, 0, 0 };
uint8_t work[6] = { 0 };
bs_init( &bs, &abc, 6 );
- bs.pf_forward = skip1;
+ bs.cb.pf_byte_forward = skip1;
for( unsigned i=0; i<6 && !bs_eof( &bs ); i++ )
work[i] = bs_read( &bs, 8 );
test_assert(memcmp( &work, &ok, 6 ), 0);
More information about the vlc-commits
mailing list