Commit 7dce9c04 authored by Francois Cartegnie's avatar Francois Cartegnie

packetizer: hevc: add hvc1 packetization (fix #16061)

parent 0b609071
...@@ -13,7 +13,9 @@ libpacketizer_mlp_plugin_la_SOURCES = packetizer/mlp.c ...@@ -13,7 +13,9 @@ libpacketizer_mlp_plugin_la_SOURCES = packetizer/mlp.c
libpacketizer_dirac_plugin_la_SOURCES = packetizer/dirac.c libpacketizer_dirac_plugin_la_SOURCES = packetizer/dirac.c
libpacketizer_flac_plugin_la_SOURCES = packetizer/flac.c libpacketizer_flac_plugin_la_SOURCES = packetizer/flac.c
libpacketizer_hevc_plugin_la_SOURCES = packetizer/hevc.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 \ libpacketizer_avparser_plugin_la_SOURCES = packetizer/avparser.c \
packetizer/avparser.h \ packetizer/avparser.h \
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <vlc_block_helper.h> #include <vlc_block_helper.h>
#include "packetizer_helper.h" #include "packetizer_helper.h"
#include "hevc_nal.h" #include "hevc_nal.h"
#include "hxxx_common.h"
/***************************************************************************** /*****************************************************************************
* Module descriptor * Module descriptor
...@@ -57,10 +58,12 @@ vlc_module_end () ...@@ -57,10 +58,12 @@ vlc_module_end ()
/**************************************************************************** /****************************************************************************
* Local prototypes * 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 PacketizeFlush( decoder_t * );
static void PacketizeReset(void *p_private, bool b_broken); 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 *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 *); static int PacketizeValidate(void *p_private, block_t *);
struct decoder_sys_t struct decoder_sys_t
...@@ -71,6 +74,7 @@ struct decoder_sys_t ...@@ -71,6 +74,7 @@ struct decoder_sys_t
bool b_vcl; bool b_vcl;
block_t *p_frame; block_t *p_frame;
uint8_t i_nal_length_size;
}; };
static const uint8_t p_hevc_startcode[3] = {0x00, 0x00, 0x01}; 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}; ...@@ -81,11 +85,12 @@ static const uint8_t p_hevc_startcode[3] = {0x00, 0x00, 0x01};
static int Open(vlc_object_t *p_this) static int Open(vlc_object_t *p_this)
{ {
decoder_t *p_dec = (decoder_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) if (p_dec->fmt_in.i_codec != VLC_CODEC_HEVC)
return VLC_EGENERIC; 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) if (!p_dec->p_sys)
return VLC_ENOMEM; return VLC_ENOMEM;
...@@ -97,12 +102,44 @@ static int Open(vlc_object_t *p_this) ...@@ -97,12 +102,44 @@ static int Open(vlc_object_t *p_this)
/* Copy properties */ /* Copy properties */
es_format_Copy(&p_dec->fmt_out, &p_dec->fmt_in); es_format_Copy(&p_dec->fmt_out, &p_dec->fmt_in);
/* Set callback */ /* Set callbacks */
p_dec->pf_packetize = Packetize; 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; p_dec->pf_flush = PacketizeFlush;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
/***************************************************************************** /*****************************************************************************
...@@ -120,7 +157,15 @@ static void Close(vlc_object_t *p_this) ...@@ -120,7 +157,15 @@ static void Close(vlc_object_t *p_this)
/**************************************************************************** /****************************************************************************
* Packetize * 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; decoder_sys_t *p_sys = p_dec->p_sys;
...@@ -149,18 +194,18 @@ static void PacketizeReset(void *p_private, bool b_broken) ...@@ -149,18 +194,18 @@ static void PacketizeReset(void *p_private, bool b_broken)
p_sys->b_vcl = false; 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; decoder_sys_t *p_sys = p_dec->p_sys;
block_t * p_nal = NULL; 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_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 */ /* Get NALU type */
uint32_t forbidden_zero_bit = bs_read1(&bs); 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 ...@@ -188,25 +233,36 @@ static block_t *PacketizeParse(void *p_private, bool *pb_ts_used, block_t *p_blo
p_sys->p_frame = NULL; p_sys->p_frame = NULL;
} }
block_ChainAppend(&p_sys->p_frame, p_block); block_ChainAppend(&p_sys->p_frame, p_frag);
} }
else else
{ {
if (p_sys->b_vcl) if (p_sys->b_vcl)
{ {
p_nal = block_ChainGather(p_sys->p_frame); 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->p_frame = NULL;
p_sys->b_vcl =false; p_sys->b_vcl =false;
} }
else else
p_nal = p_block; p_nal = p_frag;
} }
*pb_ts_used = false; *pb_ts_used = false;
return p_nal; 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 ) static int PacketizeValidate( void *p_private, block_t *p_au )
{ {
VLC_UNUSED(p_private); VLC_UNUSED(p_private);
......
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