[vlc-devel] [PATCH 1/2] Add a trivial hevc packetizer

Denis Charmet typx at dinauz.org
Sun Feb 9 23:01:07 CET 2014


---
 modules/packetizer/Modules.am |   2 +
 modules/packetizer/hevc.c     | 248 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 250 insertions(+)
 create mode 100644 modules/packetizer/hevc.c

diff --git a/modules/packetizer/Modules.am b/modules/packetizer/Modules.am
index 3d4f806..15b1190 100644
--- a/modules/packetizer/Modules.am
+++ b/modules/packetizer/Modules.am
@@ -7,6 +7,7 @@ SOURCES_packetizer_vc1 = vc1.c
 SOURCES_packetizer_mlp = mlp.c
 SOURCES_packetizer_dirac = dirac.c
 SOURCES_packetizer_flac = flac.c
+SOURCES_packetizer_hevc = hevc.c
 
 noinst_HEADERS = packetizer_helper.h
 
@@ -19,6 +20,7 @@ packetizer_LTLIBRARIES += \
 	libpacketizer_mlp_plugin.la \
 	libpacketizer_dirac_plugin.la \
 	libpacketizer_flac_plugin.la \
+	libpacketizer_hevc_plugin.la \
 	$(NULL)
 if ENABLE_SOUT
 packetizer_LTLIBRARIES += libpacketizer_copy_plugin.la
diff --git a/modules/packetizer/hevc.c b/modules/packetizer/hevc.c
new file mode 100644
index 0000000..407cc2f
--- /dev/null
+++ b/modules/packetizer/hevc.c
@@ -0,0 +1,248 @@
+/*****************************************************************************
+ * hevc.c: h.265/hevc video packetizer
+ *****************************************************************************
+ * Copyright (C) 2014 VLC authors and VideoLAN
+ * $Id$
+ *
+ * Authors: Denis Charmet <typx at videolan.org>
+ *
+ * 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.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <assert.h>
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_codec.h>
+#include <vlc_block.h>
+
+#include <vlc_block_helper.h>
+#include <vlc_bits.h>
+#include "packetizer_helper.h"
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+static int  Open (vlc_object_t *);
+static void Close(vlc_object_t *);
+
+vlc_module_begin ()
+    set_category(CAT_SOUT)
+    set_subcategory(SUBCAT_SOUT_PACKETIZER)
+    set_description(N_("H.265/HEVC video packetizer"))
+    set_capability("packetizer", 50)
+    set_callbacks(Open, Close)
+vlc_module_end ()
+
+
+/****************************************************************************
+ * Local prototypes
+ ****************************************************************************/
+
+struct decoder_sys_t
+{
+    /* */
+    packetizer_t packetizer;
+
+    bool     b_vcl;
+    block_t *p_frame;
+
+};
+
+enum nal_unit_type_e
+{
+    TRAIL_N    = 0,
+    TRAIL_R    = 1,
+    TSA_N      = 2,
+    TSA_R      = 3,
+    STSA_N     = 4,
+    STSA_R     = 5,
+    RADL_N     = 6,
+    RADL_R     = 7,
+    RASL_N     = 8,
+    RASL_R     = 9,
+    /* 10 to 15 reserved */
+    /* Key frames */
+    BLA_W_LP   = 16,
+    BLA_W_RADL = 17,
+    BLA_N_LP   = 18,
+    IDR_W_RADL = 19,
+    IDR_N_LP   = 20,
+    CRA        = 21,
+    /* 22 to 31 reserved */
+    /* Non VCL NAL*/
+    VPS        = 32,
+    SPS        = 33,
+    PPS        = 34,
+    AUD        = 35, /* Access unit delimiter */
+    EOS        = 36, /* End of sequence */
+    EOB        = 37, /* End of bitstream */
+    FD         = 38, /* Filler data*/
+    PREF_SEI   = 39, /* Prefix SEI */
+    SUFF_SEI   = 40, /* Suffix SEI */
+    UNKNOWN_NAL
+};
+
+static block_t *Packetize(decoder_t *, block_t **);
+
+static void PacketizeReset(void *p_private, bool b_broken);
+static block_t *PacketizeParse(void *p_private, bool *pb_ts_used, block_t *);
+static int PacketizeValidate(void *p_private, block_t *);
+
+static const uint8_t p_hevc_startcode[3] = {0x00, 0x00, 0x01};
+
+/*****************************************************************************
+ * Open
+ *****************************************************************************/
+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;
+
+    if ((p_dec->p_sys = p_sys = calloc(1, sizeof(decoder_sys_t))) == NULL)
+        return VLC_ENOMEM;
+
+    packetizer_Init(&p_sys->packetizer,
+                    p_hevc_startcode, sizeof(p_hevc_startcode),
+                    NULL, 0, 0,
+                    PacketizeReset, PacketizeParse, PacketizeValidate, p_dec);
+
+    /* Copy properties */
+    es_format_Copy(&p_dec->fmt_out, &p_dec->fmt_in);
+    p_dec->fmt_out.i_codec = p_dec->fmt_in.i_codec;
+
+    /* Set callback */
+    p_dec->pf_packetize = Packetize;
+
+    return VLC_SUCCESS;
+
+}
+
+/*****************************************************************************
+ * Close
+ *****************************************************************************/
+static void Close(vlc_object_t *p_this)
+{
+    decoder_t *p_dec = (decoder_t*)p_this;
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    packetizer_Clean(&p_sys->packetizer);
+
+    free(p_sys);
+}
+
+/****************************************************************************
+ * Packetize
+ ****************************************************************************/
+static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    return packetizer_Packetize(&p_sys->packetizer, pp_block);
+}
+
+/****************************************************************************
+ * Packetizer Helpers
+ ****************************************************************************/
+static void PacketizeReset(void *p_private, bool b_broken)
+{
+    VLC_UNUSED(b_broken);
+
+    decoder_t *p_dec = p_private;
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    block_ChainRelease(p_sys->p_frame);
+
+    p_sys->p_frame = NULL;
+    p_sys->b_vcl = false;
+}
+
+static block_t *PacketizeParse(void *p_private, bool *pb_ts_used, block_t *p_block)
+{
+    decoder_t *p_dec = p_private;
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    block_t * p_nal = NULL;
+    
+    /* Remove trailing 0 bytes */
+    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+3, p_block->i_buffer-3);
+
+    /* Get NALU type */
+    uint32_t forbidden_zero_bit = bs_read1(&bs);
+
+    if (forbidden_zero_bit)
+    {
+        msg_Err(p_dec,"Forbidden zero bit not null, corrupted NAL");
+        p_sys->p_frame = NULL;
+        p_sys->b_vcl = false;
+        return NULL;
+    }
+    uint32_t nalu_type = bs_read(&bs,6);
+    bs_skip(&bs, 9);
+
+    if (nalu_type < VPS)
+    {
+        /* NAL is a VCL NAL */
+        p_sys->b_vcl = true;
+
+        uint32_t first_slice_in_pic = bs_read1(&bs);
+
+        if (first_slice_in_pic && p_sys->p_frame)
+        {
+            p_nal = block_ChainGather(p_sys->p_frame);
+            p_sys->p_frame = NULL;
+        }
+
+        block_ChainAppend(&p_sys->p_frame, p_block);
+    }
+    else
+    {
+        if (p_sys->b_vcl)
+        {
+            p_nal = block_ChainGather(p_sys->p_frame);
+            p_nal->p_next = p_block;
+            p_sys->p_frame = NULL;
+        }
+        else
+            p_nal = p_block;
+
+        p_sys->b_vcl =false;
+
+    }
+
+    *pb_ts_used = 0;
+    return p_nal;
+}
+
+static int PacketizeValidate( void *p_private, block_t *p_au )
+{
+    VLC_UNUSED(p_private);
+    VLC_UNUSED(p_au);
+    return VLC_SUCCESS;
+}
+
+
-- 
1.9.rc1




More information about the vlc-devel mailing list