[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