vlc | branch: master | Francois Cartegnie <[email protected]> | 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); _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
