Commit 17e07afc authored by Denis Charmet's avatar Denis Charmet Committed by Jean-Baptiste Kempf

Add avparser packetizer for VP9 handling

Fix #12944
Signed-off-by: default avatarJean-Baptiste Kempf <jb@videolan.org>
parent e72bccd5
......@@ -262,6 +262,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
......
......@@ -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;
}
......
......@@ -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 ) )
......
......@@ -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
/*****************************************************************************
* avparser.c
*****************************************************************************
* Copyright (C) 2015 VLC authors and VideoLAN
* $Id$
*
* Authors: Denis Charmet <typx@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;
}
......@@ -998,6 +998,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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment