[vlc-commits] packetizer: hevc: add hvc1 packetization (fix #16061)
Francois Cartegnie
git at videolan.org
Tue Dec 8 23:10:07 CET 2015
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Tue Dec 8 22:42:01 2015 +0100| [7dce9c048b59af679d97d18802f84c6259a1f70f] | committer: Francois Cartegnie
packetizer: hevc: add hvc1 packetization (fix #16061)
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=7dce9c048b59af679d97d18802f84c6259a1f70f
---
modules/packetizer/Makefile.am | 4 +-
modules/packetizer/hevc.c | 86 +++++++++++++++++++++++++++++++++-------
2 files changed, 74 insertions(+), 16 deletions(-)
diff --git a/modules/packetizer/Makefile.am b/modules/packetizer/Makefile.am
index 21cf9e9..54f875a 100644
--- a/modules/packetizer/Makefile.am
+++ b/modules/packetizer/Makefile.am
@@ -13,7 +13,9 @@ libpacketizer_mlp_plugin_la_SOURCES = packetizer/mlp.c
libpacketizer_dirac_plugin_la_SOURCES = packetizer/dirac.c
libpacketizer_flac_plugin_la_SOURCES = packetizer/flac.c
libpacketizer_hevc_plugin_la_SOURCES = packetizer/hevc.c \
- packetizer/hevc_nal.h packetizer/hxxx_nal.h
+ packetizer/hevc_nal.h packetizer/hevc_nal.c \
+ packetizer/hxxx_nal.h \
+ packetizer/hxxx_common.c packetizer/hxxx_common.h
libpacketizer_avparser_plugin_la_SOURCES = packetizer/avparser.c \
packetizer/avparser.h \
diff --git a/modules/packetizer/hevc.c b/modules/packetizer/hevc.c
index a7079c5..d8d6cbc 100644
--- a/modules/packetizer/hevc.c
+++ b/modules/packetizer/hevc.c
@@ -38,6 +38,7 @@
#include <vlc_block_helper.h>
#include "packetizer_helper.h"
#include "hevc_nal.h"
+#include "hxxx_common.h"
/*****************************************************************************
* Module descriptor
@@ -57,10 +58,12 @@ vlc_module_end ()
/****************************************************************************
* Local prototypes
****************************************************************************/
-static block_t *Packetize(decoder_t *, block_t **);
+static block_t *PacketizeAnnexB(decoder_t *, block_t **);
+static block_t *PacketizeHVC1(decoder_t *, block_t **);
static void PacketizeFlush( decoder_t * );
static void PacketizeReset(void *p_private, bool b_broken);
static block_t *PacketizeParse(void *p_private, bool *pb_ts_used, block_t *);
+static block_t *ParseNALBlock(decoder_t *, bool *pb_ts_used, block_t *);
static int PacketizeValidate(void *p_private, block_t *);
struct decoder_sys_t
@@ -71,6 +74,7 @@ struct decoder_sys_t
bool b_vcl;
block_t *p_frame;
+ uint8_t i_nal_length_size;
};
static const uint8_t p_hevc_startcode[3] = {0x00, 0x00, 0x01};
@@ -81,11 +85,12 @@ static const uint8_t p_hevc_startcode[3] = {0x00, 0x00, 0x01};
static int Open(vlc_object_t *p_this)
{
decoder_t *p_dec = (decoder_t*)p_this;
+ decoder_sys_t *p_sys;
if (p_dec->fmt_in.i_codec != VLC_CODEC_HEVC)
return VLC_EGENERIC;
- p_dec->p_sys = calloc(1, sizeof(decoder_sys_t));
+ p_dec->p_sys = p_sys = calloc(1, sizeof(decoder_sys_t));
if (!p_dec->p_sys)
return VLC_ENOMEM;
@@ -97,12 +102,44 @@ static int Open(vlc_object_t *p_this)
/* Copy properties */
es_format_Copy(&p_dec->fmt_out, &p_dec->fmt_in);
- /* Set callback */
- p_dec->pf_packetize = Packetize;
+ /* Set callbacks */
+ const uint8_t *p_extra = p_dec->fmt_in.p_extra;
+ const size_t i_extra = p_dec->fmt_in.i_extra;
+ /* Check if we have hvcC as extradata */
+ if(hevc_ishvcC(p_extra, i_extra))
+ {
+ p_sys->i_nal_length_size = 1 + (p_extra[21] & 0x03);
+ p_dec->pf_packetize = PacketizeHVC1;
+
+ /* Clear hvcC/HVC1 extra, to be replaced with AnnexB */
+ free(p_dec->fmt_out.p_extra);
+ p_dec->fmt_out.i_extra = 0;
+
+ size_t i_new_extra = i_extra + 40 * (4 - p_sys->i_nal_length_size);
+ uint8_t *p_new_extra = malloc(i_new_extra);
+ if(p_new_extra)
+ {
+ uint32_t i_total = 0;
+ if( hevc_hvcC_to_AnnexB_NAL( p_dec, p_extra, i_extra,
+ p_new_extra, i_new_extra,
+ &i_total, NULL ) == VLC_SUCCESS )
+ {
+ p_dec->fmt_out.p_extra = p_new_extra;
+ p_dec->fmt_out.i_extra = i_total;
+ }
+ else
+ {
+ free(p_new_extra);
+ }
+ }
+ }
+ else
+ {
+ p_dec->pf_packetize = PacketizeAnnexB;
+ }
p_dec->pf_flush = PacketizeFlush;
return VLC_SUCCESS;
-
}
/*****************************************************************************
@@ -120,7 +157,15 @@ static void Close(vlc_object_t *p_this)
/****************************************************************************
* Packetize
****************************************************************************/
-static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
+static block_t *PacketizeHVC1(decoder_t *p_dec, block_t **pp_block)
+{
+ decoder_sys_t *p_sys = p_dec->p_sys;
+
+ return PacketizeXXC1( p_dec, p_sys->i_nal_length_size,
+ pp_block, ParseNALBlock );
+}
+
+static block_t *PacketizeAnnexB(decoder_t *p_dec, block_t **pp_block)
{
decoder_sys_t *p_sys = p_dec->p_sys;
@@ -149,18 +194,18 @@ static void PacketizeReset(void *p_private, bool b_broken)
p_sys->b_vcl = false;
}
-static block_t *PacketizeParse(void *p_private, bool *pb_ts_used, block_t *p_block)
+/*****************************************************************************
+ * ParseNALBlock: parses annexB type NALs
+ * All p_frag blocks are required to start with 0 0 0 1 4-byte startcode
+ *****************************************************************************/
+static block_t *ParseNALBlock(decoder_t *p_dec, bool *pb_ts_used, block_t *p_frag)
{
- decoder_t *p_dec = p_private;
decoder_sys_t *p_sys = p_dec->p_sys;
block_t * p_nal = NULL;
- while (p_block->i_buffer > 5 && p_block->p_buffer[p_block->i_buffer-1] == 0x00 )
- p_block->i_buffer--;
-
bs_t bs;
- bs_init(&bs, p_block->p_buffer+4, p_block->i_buffer-4);
+ bs_init(&bs, p_frag->p_buffer+4, p_frag->i_buffer-4);
/* Get NALU type */
uint32_t forbidden_zero_bit = bs_read1(&bs);
@@ -188,25 +233,36 @@ static block_t *PacketizeParse(void *p_private, bool *pb_ts_used, block_t *p_blo
p_sys->p_frame = NULL;
}
- block_ChainAppend(&p_sys->p_frame, p_block);
+ block_ChainAppend(&p_sys->p_frame, p_frag);
}
else
{
if (p_sys->b_vcl)
{
p_nal = block_ChainGather(p_sys->p_frame);
- p_nal->p_next = p_block;
+ p_nal->p_next = p_frag;
p_sys->p_frame = NULL;
p_sys->b_vcl =false;
}
else
- p_nal = p_block;
+ p_nal = p_frag;
}
*pb_ts_used = false;
return p_nal;
}
+static block_t *PacketizeParse(void *p_private, bool *pb_ts_used, block_t *p_block)
+{
+ decoder_t *p_dec = p_private;
+
+ /* Remove trailing 0 bytes */
+ while (p_block->i_buffer > 5 && p_block->p_buffer[p_block->i_buffer-1] == 0x00 )
+ p_block->i_buffer--;
+
+ return ParseNALBlock( p_dec, pb_ts_used, p_block );
+}
+
static int PacketizeValidate( void *p_private, block_t *p_au )
{
VLC_UNUSED(p_private);
More information about the vlc-commits
mailing list