[vlc-devel] [PATCH] Add avparser packetizer for VP9 handling

Rémi Denis-Courmont remi at remlab.net
Thu Feb 26 15:44:23 CET 2015


Le 2015-02-26 17:27, Denis Charmet a écrit :
> From: CHARMET Denis <typx at dinauz.org>
>
> Fix #12944
> ---
>  modules/demux/mkv/matroska_segment_parse.cpp |    1 +
>  modules/packetizer/Makefile.am               |   13 ++
>  modules/packetizer/avparser.c                |  188
> ++++++++++++++++++++++++++
>  3 files changed, 202 insertions(+)
>  create mode 100644 modules/packetizer/avparser.c
>
> diff --git a/modules/demux/mkv/matroska_segment_parse.cpp
> b/modules/demux/mkv/matroska_segment_parse.cpp
> index 7f3bcb2..a3bd5e3 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_fmt->b_packetized = false;

Does the decoder not need to set some need-packetization flag too?

>          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..0e62cb7 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) 
> $(AM_CFLAGS)
> +libpacketizer_avparser_plugin_la_LIBADD = $(AVCODEC_LIBS) $(LIBM)

I'd add AVUTILS even if it is already pulled in implicitly (still).

> +
> +
>  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;
> +}
> +

-- 
Rémi Denis-Courmont



More information about the vlc-devel mailing list