[vlc-commits] Add avparser packetizer for VP9 handling

Denis Charmet git at videolan.org
Thu Feb 26 20:43:05 CET 2015


vlc/vlc-2.2 | branch: master | Denis Charmet <typx at dinauz.org> | Thu Feb 26 17:32:29 2015 +0100| [0a1bb10515efaed0cc62dac4b2cf3302f46b1328] | committer: Jean-Baptiste Kempf

Add avparser packetizer for VP9 handling

Fix #12944

Signed-off-by: Jean-Baptiste Kempf <jb at videolan.org>
(cherry picked from commit 17e07afce4d26cfecf6ab5252c738cd8a0e9756a)
Signed-off-by: Jean-Baptiste Kempf <jb at videolan.org>

> http://git.videolan.org/gitweb.cgi/vlc/vlc-2.2.git/?a=commit;h=0a1bb10515efaed0cc62dac4b2cf3302f46b1328
---

 modules/MODULES_LIST                         |    1 +
 modules/codec/avcodec/video.c                |    3 +
 modules/demux/mkv/matroska_segment_parse.cpp |    1 +
 modules/packetizer/Modules.am                |   11 ++
 modules/packetizer/avparser.c                |  188 ++++++++++++++++++++++++++
 po/POTFILES.in                               |    1 +
 6 files changed, 205 insertions(+)

diff --git a/modules/MODULES_LIST b/modules/MODULES_LIST
index db5820e..d43d1f4 100644
--- a/modules/MODULES_LIST
+++ b/modules/MODULES_LIST
@@ -249,6 +249,7 @@ $Id$
  * opus: a opus audio decoder/packetizer/encoder using the libopus library
  * os2drive: service discovery for OS/2 drives
  * oss: audio output module using the OSS /dev/dsp interface
+ * packetizer_avparser: libavcodec packetizer
  * packetizer_copy: Simple copy packetizer
  * packetizer_dirac: Dirac video packetizer
  * packetizer_flac: FLAC audio packetizer
diff --git a/modules/codec/avcodec/video.c b/modules/codec/avcodec/video.c
index ad9be3b..111ba0f 100644
--- a/modules/codec/avcodec/video.c
+++ b/modules/codec/avcodec/video.c
@@ -441,6 +441,9 @@ int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context,
         return VLC_EGENERIC;
     }
 
+    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 7792667..845d387 100644
--- a/modules/demux/mkv/matroska_segment_parse.cpp
+++ b/modules/demux/mkv/matroska_segment_parse.cpp
@@ -1369,6 +1369,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/Modules.am b/modules/packetizer/Modules.am
index 15b1190..e07880b 100644
--- a/modules/packetizer/Modules.am
+++ b/modules/packetizer/Modules.am
@@ -9,6 +9,14 @@ SOURCES_packetizer_dirac = dirac.c
 SOURCES_packetizer_flac = flac.c
 SOURCES_packetizer_hevc = hevc.c
 
+libpacketizer_avparser_plugin_la_SOURCES = 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_helper.h
 
 packetizer_LTLIBRARIES += \
@@ -25,3 +33,6 @@ 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;
+}
+
diff --git a/po/POTFILES.in b/po/POTFILES.in
index f6f7e7e..142f928 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -990,6 +990,7 @@ modules/mux/ogg.c
 modules/mux/wav.c
 modules/notify/growl.m
 modules/notify/notify.c
+modules/packetizer/avparser.c
 modules/packetizer/copy.c
 modules/packetizer/dirac.c
 modules/packetizer/flac.c



More information about the vlc-commits mailing list