[vlc-commits] Add a trivial hevc packetizer
Denis Charmet
git at videolan.org
Tue Feb 11 22:49:51 CET 2014
vlc | branch: master | Denis Charmet <typx at dinauz.org> | Sun Feb 9 22:57:06 2014 +0100| [b1c0b336315c986c0c33cac3215e8aa2a9cd0fc0] | committer: Denis Charmet
Add a trivial hevc packetizer
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=b1c0b336315c986c0c33cac3215e8aa2a9cd0fc0
---
modules/packetizer/Modules.am | 2 +
modules/packetizer/hevc.c | 240 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 242 insertions(+)
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..58b207b
--- /dev/null
+++ b/modules/packetizer/hevc.c
@@ -0,0 +1,240 @@
+/*****************************************************************************
+ * 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 <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_codec.h>
+#include <vlc_block.h>
+
+#include <vlc_bits.h>
+#include <vlc_block_helper.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_("HEVC/H.265 video packetizer"))
+ set_capability("packetizer", 50)
+ set_callbacks(Open, Close)
+vlc_module_end ()
+
+
+/****************************************************************************
+ * Local prototypes
+ ****************************************************************************/
+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 *);
+
+struct decoder_sys_t
+{
+ /* */
+ packetizer_t packetizer;
+
+ bool b_vcl;
+ block_t *p_frame;
+
+};
+
+/* NAL types from https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-H.265-201304-I!!PDF-E&type=items */
+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 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;
+
+ if (p_dec->fmt_in.i_codec != VLC_CODEC_HEVC)
+ return VLC_EGENERIC;
+
+ p_dec->p_sys = calloc(1, sizeof(decoder_sys_t));
+ if (!p_dec->p_sys)
+ return VLC_ENOMEM;
+
+ packetizer_Init(&p_dec->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);
+
+ /* 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;
+
+ 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;
+ p_sys->b_vcl =false;
+ }
+ else
+ p_nal = p_block;
+ }
+
+ *pb_ts_used = false;
+ return p_nal;
+}
+
+static int PacketizeValidate( void *p_private, block_t *p_au )
+{
+ VLC_UNUSED(p_private);
+ VLC_UNUSED(p_au);
+ return VLC_SUCCESS;
+}
More information about the vlc-commits
mailing list