[vlc-devel] [PATCH] Add avparser packetizer for VP9 handling
Denis Charmet
typx at dinauz.org
Thu Feb 26 17:32:29 CET 2015
From: CHARMET Denis <typx at dinauz.org>
Fix #12944
---
modules/codec/avcodec/video.c | 4 +
modules/demux/mkv/matroska_segment_parse.cpp | 1 +
modules/packetizer/Makefile.am | 13 ++
modules/packetizer/avparser.c | 188 ++++++++++++++++++++++++++
4 files changed, 206 insertions(+)
create mode 100644 modules/packetizer/avparser.c
diff --git a/modules/codec/avcodec/video.c b/modules/codec/avcodec/video.c
index 5ba6e2e..381fe62 100644
--- a/modules/codec/avcodec/video.c
+++ b/modules/codec/avcodec/video.c
@@ -454,6 +454,10 @@ int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context,
}
p_dec->pf_decode_video = DecodeVideo;
+
+ if ( p_dec->fmt_in.i_codec == VLC_CODEC_VP9 )
+ p_dec->b_need_packetized = true;
+
return VLC_SUCCESS;
}
diff --git a/modules/demux/mkv/matroska_segment_parse.cpp b/modules/demux/mkv/matroska_segment_parse.cpp
index 7f3bcb2..ff47a2b5 100644
--- a/modules/demux/mkv/matroska_segment_parse.cpp
+++ b/modules/demux/mkv/matroska_segment_parse.cpp
@@ -1370,6 +1370,7 @@ int32_t matroska_segment_c::TrackInit( mkv_track_t * p_tk )
else if( !strncmp( p_tk->psz_codec, "V_VP9", 5 ) )
{
p_tk->fmt.i_codec = VLC_CODEC_VP9;
+ p_tk->fmt.b_packetized = false;
fill_extra_data( p_tk, 0 );
}
else if( !strncmp( p_tk->psz_codec, "V_MPEG4", 7 ) )
diff --git a/modules/packetizer/Makefile.am b/modules/packetizer/Makefile.am
index ff28b08..ce71ce2 100644
--- a/modules/packetizer/Makefile.am
+++ b/modules/packetizer/Makefile.am
@@ -13,6 +13,14 @@ libpacketizer_dirac_plugin_la_SOURCES = packetizer/dirac.c
libpacketizer_flac_plugin_la_SOURCES = packetizer/flac.c
libpacketizer_hevc_plugin_la_SOURCES = packetizer/hevc.c
+libpacketizer_avparser_plugin_la_SOURCES = packetizer/avparser.c \
+ codec/avcodec/avcommon.h \
+ codec/avcodec/avcodec.h \
+ codec/avcodec/fourcc.c
+libpacketizer_avparser_plugin_la_CFLAGS = $(AVCODEC_CFLAGS) $(AVUTIL_CFLAGS) $(AM_CFLAGS)
+libpacketizer_avparser_plugin_la_LIBADD = $(AVCODEC_LIBS) $(AVUTIL_LIBS) $(LIBM)
+
+
noinst_HEADERS += packetizer/packetizer_helper.h
packetizer_LTLIBRARIES = \
@@ -29,3 +37,8 @@ packetizer_LTLIBRARIES = \
if ENABLE_SOUT
packetizer_LTLIBRARIES += libpacketizer_copy_plugin.la
endif
+
+if HAVE_AVCODEC
+packetizer_LTLIBRARIES += libpacketizer_avparser_plugin.la
+endif
+
diff --git a/modules/packetizer/avparser.c b/modules/packetizer/avparser.c
new file mode 100644
index 0000000..d172462
--- /dev/null
+++ b/modules/packetizer/avparser.c
@@ -0,0 +1,188 @@
+/*****************************************************************************
+ * avparser.c
+ *****************************************************************************
+ * Copyright (C) 2015 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 "../codec/avcodec/avcodec.h"
+#include "../codec/avcodec/avcommon.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_("avparser packetizer") )
+ set_capability( "packetizer", 1 )
+ set_callbacks( Open, Close )
+vlc_module_end ()
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+struct decoder_sys_t
+{
+ AVCodecParserContext * p_parser_ctx;
+ AVCodecContext * p_codec_ctx;
+ int i_offset;
+};
+
+static block_t * Packetize( decoder_t *, block_t ** );
+
+/*****************************************************************************
+ * Open: probe the packetizer and return score
+ *****************************************************************************
+ * Tries to launch a decoder and return score so that the interface is able
+ * to choose.
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ decoder_t *p_dec = (decoder_t*)p_this;
+ decoder_sys_t *p_sys;
+
+ /* Restrict to VP9 for now */
+ if( p_dec->fmt_in.i_codec != VLC_CODEC_VP9 )
+ return VLC_EGENERIC;
+
+ unsigned i_avcodec_id;
+
+ if( !GetFfmpegCodec( p_dec->fmt_in.i_codec, NULL, &i_avcodec_id, NULL ) )
+ return VLC_EGENERIC;
+
+ /* init avcodec */
+ vlc_init_avcodec(p_this);
+
+ /* It is less likely to have a parser than a codec, start by that */
+ AVCodecParserContext * p_ctx = av_parser_init( i_avcodec_id );
+ if( !p_ctx )
+ return VLC_EGENERIC;
+
+ AVCodec * p_codec = avcodec_find_decoder( i_avcodec_id );
+ if( unlikely( !p_codec ) )
+ {
+ av_parser_close( p_ctx );
+ return VLC_EGENERIC;
+ }
+
+ AVCodecContext * p_codec_ctx = avcodec_alloc_context3( p_codec );
+ if( unlikely( !p_codec_ctx ) )
+ {
+ av_parser_close( p_ctx );
+ return VLC_ENOMEM;
+ }
+
+ p_dec->p_sys = p_sys = malloc( sizeof(*p_sys) );
+
+ if( unlikely( !p_sys ) )
+ {
+ avcodec_free_context( &p_codec_ctx );
+ av_parser_close( p_ctx );
+ return VLC_ENOMEM;
+ }
+ p_dec->pf_packetize = Packetize;
+ p_sys->p_parser_ctx = p_ctx;
+ p_sys->p_codec_ctx = p_codec_ctx;
+ p_sys->i_offset = 0;
+ es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in );
+
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Close:
+ *****************************************************************************/
+static void Close( vlc_object_t *p_this )
+{
+ decoder_t *p_dec = (decoder_t*)p_this;
+ avcodec_free_context( &p_dec->p_sys->p_codec_ctx );
+ av_parser_close( p_dec->p_sys->p_parser_ctx );
+ es_format_Clean( &p_dec->fmt_out );
+ free( p_dec->p_sys );
+}
+
+/*****************************************************************************
+ * Packetize: packetize a frame
+ *****************************************************************************/
+static block_t *Packetize ( decoder_t *p_dec, block_t **pp_block )
+{
+ decoder_sys_t *p_sys = p_dec->p_sys;
+
+ if( pp_block == NULL || *pp_block == NULL )
+ return NULL;
+ if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
+ {
+ block_Release( *pp_block );
+ return NULL;
+ }
+
+ block_t * p_block = *pp_block;
+
+ uint8_t * p_indata = p_block->p_buffer + p_sys->i_offset;
+ int i_inlen = p_block->i_buffer - p_sys->i_offset;
+ uint8_t * p_outdata;
+ int i_outlen;
+
+ if( p_sys->i_offset == i_inlen )
+ goto out;
+
+ p_sys->i_offset += av_parser_parse2( p_sys->p_parser_ctx, p_sys->p_codec_ctx,
+ &p_outdata, &i_outlen, p_indata, i_inlen,
+ p_block->i_pts, p_block->i_dts, -1);
+
+ if( unlikely( i_outlen <= 0 || !p_outdata ) )
+ goto out;
+
+ block_t * p_ret = block_Alloc( i_outlen );
+
+ if( unlikely ( !p_ret ) )
+ goto out;
+
+ memcpy( p_ret->p_buffer, p_outdata, i_outlen );
+ p_ret->i_pts = p_block->i_pts;
+ p_ret->i_dts = p_block->i_dts;
+
+ p_block->i_pts = p_block->i_dts = VLC_TS_INVALID;
+
+ return p_ret;
+
+out:
+ p_sys->i_offset = 0;
+ block_Release( *pp_block );
+ *pp_block == NULL;
+ return NULL;
+}
+
--
1.7.9.5
More information about the vlc-devel
mailing list