Commit dc272d02 authored by Laurent Aimar's avatar Laurent Aimar

Added support for ffmpeg-mt.

It is not well tested yet.
parent 933d6755
...@@ -140,6 +140,10 @@ vlc_module_begin () ...@@ -140,6 +140,10 @@ vlc_module_begin ()
#if defined(HAVE_AVCODEC_VAAPI) || defined(HAVE_AVCODEC_DXVA2) #if defined(HAVE_AVCODEC_VAAPI) || defined(HAVE_AVCODEC_DXVA2)
add_bool( "ffmpeg-hw", false, NULL, HW_TEXT, HW_LONGTEXT, true ) add_bool( "ffmpeg-hw", false, NULL, HW_TEXT, HW_LONGTEXT, true )
#endif #endif
#if defined(FF_THREAD_FRAME)
add_integer( "ffmpeg-threads", 0, NULL, THREADS_TEXT, THREADS_LONGTEXT, true );
#endif
#ifdef ENABLE_SOUT #ifdef ENABLE_SOUT
/* encoder submodule */ /* encoder submodule */
......
...@@ -138,6 +138,9 @@ void EndSubtitleDec( decoder_t *p_dec ); ...@@ -138,6 +138,9 @@ void EndSubtitleDec( decoder_t *p_dec );
#define HW_TEXT N_("Hardware decoding") #define HW_TEXT N_("Hardware decoding")
#define HW_LONGTEXT N_("This allows hardware decoding when available.") #define HW_LONGTEXT N_("This allows hardware decoding when available.")
#define THREADS_TEXT N_( "Threads" )
#define THREADS_LONGTEXT N_( "Number of threads used for decoding, 0 meaning auto" )
/* /*
* Encoder options * Encoder options
*/ */
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <vlc_common.h> #include <vlc_common.h>
#include <vlc_codec.h> #include <vlc_codec.h>
#include <vlc_avcodec.h> #include <vlc_avcodec.h>
#include <vlc_cpu.h>
#include <assert.h> #include <assert.h>
/* ffmpeg header */ /* ffmpeg header */
...@@ -54,6 +55,9 @@ ...@@ -54,6 +55,9 @@
#if defined(HAVE_AVCODEC_VAAPI) || defined(HAVE_AVCODEC_DXVA2) #if defined(HAVE_AVCODEC_VAAPI) || defined(HAVE_AVCODEC_DXVA2)
# define HAVE_AVCODEC_VA # define HAVE_AVCODEC_VA
#endif #endif
#if defined(FF_THREAD_FRAME)
# define HAVE_AVCODEC_MT
#endif
/***************************************************************************** /*****************************************************************************
* decoder_sys_t : decoder descriptor * decoder_sys_t : decoder descriptor
...@@ -93,8 +97,18 @@ struct decoder_sys_t ...@@ -93,8 +97,18 @@ struct decoder_sys_t
/* VA API */ /* VA API */
vlc_va_t *p_va; vlc_va_t *p_va;
vlc_sem_t sem_mt;
}; };
#ifdef HAVE_AVCODEC_MT
# define wait_mt(s) vlc_sem_wait( &s->sem_mt )
# define post_mt(s) vlc_sem_post( &s->sem_mt )
#else
# define wait_mt(s)
# define post_mt(s)
#endif
/* FIXME (dummy palette for now) */ /* FIXME (dummy palette for now) */
static const AVPaletteControl palette_control; static const AVPaletteControl palette_control;
...@@ -207,6 +221,7 @@ int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context, ...@@ -207,6 +221,7 @@ int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context,
p_sys->p_ff_pic = avcodec_alloc_frame(); p_sys->p_ff_pic = avcodec_alloc_frame();
p_sys->b_delayed_open = true; p_sys->b_delayed_open = true;
p_sys->p_va = NULL; p_sys->p_va = NULL;
vlc_sem_init( &p_sys->sem_mt, 0 );
/* ***** Fill p_context with init values ***** */ /* ***** Fill p_context with init values ***** */
p_sys->p_context->codec_tag = ffmpeg_CodecTag( p_dec->fmt_in.i_original_fourcc ?: p_dec->fmt_in.i_codec ); p_sys->p_context->codec_tag = ffmpeg_CodecTag( p_dec->fmt_in.i_original_fourcc ?: p_dec->fmt_in.i_codec );
...@@ -318,10 +333,28 @@ int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context, ...@@ -318,10 +333,28 @@ int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context,
p_sys->p_context->opaque = p_dec; p_sys->p_context->opaque = p_dec;
#ifdef HAVE_AVCODEC_VA #ifdef HAVE_AVCODEC_VA
if( var_CreateGetBool( p_dec, "ffmpeg-hw" ) ) const bool b_use_hw = var_CreateGetBool( p_dec, "ffmpeg-hw" );
if( b_use_hw )
p_sys->p_context->get_format = ffmpeg_GetFormat; p_sys->p_context->get_format = ffmpeg_GetFormat;
#endif #endif
#ifdef HAVE_AVCODEC_MT
int i_thread_count = var_InheritInteger( p_dec, "ffmpeg-threads" );
if( i_thread_count <= 0 )
i_thread_count = vlc_GetCPUCount();
#ifdef HAVE_AVCODEC_VA
if( b_use_hw )
{
if( i_thread_count > 1 )
msg_Err( p_dec, "ffmpeg-hw and ffmpeg-threads options are not compatible" );
i_thread_count = 1;
}
#endif
msg_Dbg( p_dec, "allowing %d thread(s) for decoding", i_thread_count );
p_sys->p_context->thread_count = i_thread_count;
#endif
/* ***** misc init ***** */ /* ***** misc init ***** */
p_sys->i_pts = VLC_TS_INVALID; p_sys->i_pts = VLC_TS_INVALID;
p_sys->b_has_b_frames = false; p_sys->b_has_b_frames = false;
...@@ -376,6 +409,7 @@ int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context, ...@@ -376,6 +409,7 @@ int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context,
{ {
msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec ); msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec );
av_free( p_sys->p_ff_pic ); av_free( p_sys->p_ff_pic );
vlc_sem_destroy( &p_sys->sem_mt );
free( p_sys ); free( p_sys );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
...@@ -533,6 +567,7 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) ...@@ -533,6 +567,7 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
p_block->i_pts = p_block->i_pts =
p_block->i_dts = VLC_TS_INVALID; p_block->i_dts = VLC_TS_INVALID;
post_mt( p_sys );
i_used = avcodec_decode_video( p_context, p_sys->p_ff_pic, i_used = avcodec_decode_video( p_context, p_sys->p_ff_pic,
&b_gotpicture, &b_gotpicture,
...@@ -549,6 +584,7 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) ...@@ -549,6 +584,7 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
&b_gotpicture, p_block->p_buffer, &b_gotpicture, p_block->p_buffer,
p_block->i_buffer ); p_block->i_buffer );
} }
wait_mt( p_sys );
if( p_sys->b_flush ) if( p_sys->b_flush )
p_sys->b_first_frame = true; p_sys->b_first_frame = true;
...@@ -564,7 +600,8 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) ...@@ -564,7 +600,8 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
block_Release( p_block ); block_Release( p_block );
return NULL; return NULL;
} }
else if( i_used > p_block->i_buffer ) else if( i_used > p_block->i_buffer ||
p_context->thread_count > 1 )
{ {
i_used = p_block->i_buffer; i_used = p_block->i_buffer;
} }
...@@ -749,14 +786,19 @@ void EndVideoDec( decoder_t *p_dec ) ...@@ -749,14 +786,19 @@ void EndVideoDec( decoder_t *p_dec )
{ {
decoder_sys_t *p_sys = p_dec->p_sys; decoder_sys_t *p_sys = p_dec->p_sys;
post_mt( p_sys );
/* do not flush buffers if codec hasn't been opened (theora/vorbis/VC1) */ /* do not flush buffers if codec hasn't been opened (theora/vorbis/VC1) */
if( p_sys->p_context->codec ) if( p_sys->p_context->codec )
avcodec_flush_buffers( p_sys->p_context ); avcodec_flush_buffers( p_sys->p_context );
wait_mt( p_sys );
if( p_sys->p_ff_pic ) av_free( p_sys->p_ff_pic ); if( p_sys->p_ff_pic ) av_free( p_sys->p_ff_pic );
if( p_sys->p_va ) if( p_sys->p_va )
vlc_va_Delete( p_sys->p_va ); vlc_va_Delete( p_sys->p_va );
vlc_sem_destroy( &p_sys->sem_mt );
} }
/***************************************************************************** /*****************************************************************************
...@@ -852,6 +894,27 @@ static int ffmpeg_OpenCodec( decoder_t *p_dec ) ...@@ -852,6 +894,27 @@ static int ffmpeg_OpenCodec( decoder_t *p_dec )
if( ret < 0 ) if( ret < 0 )
return VLC_EGENERIC; return VLC_EGENERIC;
msg_Dbg( p_dec, "ffmpeg codec (%s) started", p_sys->psz_namecodec ); msg_Dbg( p_dec, "ffmpeg codec (%s) started", p_sys->psz_namecodec );
#ifdef HAVE_AVCODEC_MT
switch( p_sys->p_context->active_thread_type )
{
case FF_THREAD_FRAME:
msg_Dbg( p_dec, "using frame thread mode with %d threads",
p_sys->p_context->thread_count );
break;
case FF_THREAD_SLICE:
msg_Dbg( p_dec, "using slice thread mode with %d threads",
p_sys->p_context->thread_count );
break;
case 0:
if( p_sys->p_context->thread_count > 1 )
msg_Warn( p_dec, "failed to enable threaded decoding" );
break;
default:
msg_Warn( p_dec, "using unknown thread mode with %d threads",
p_sys->p_context->thread_count );
break;
}
#endif
p_sys->b_delayed_open = false; p_sys->b_delayed_open = false;
...@@ -951,6 +1014,8 @@ static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context, ...@@ -951,6 +1014,8 @@ static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context,
return avcodec_default_get_buffer( p_context, p_ff_pic ); return avcodec_default_get_buffer( p_context, p_ff_pic );
} }
wait_mt( p_sys );
/* Some codecs set pix_fmt only after the 1st frame has been decoded, /* Some codecs set pix_fmt only after the 1st frame has been decoded,
* so we need to check for direct rendering again. */ * so we need to check for direct rendering again. */
...@@ -1028,6 +1093,7 @@ static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context, ...@@ -1028,6 +1093,7 @@ static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context,
/* FIXME what is that, should give good value */ /* FIXME what is that, should give good value */
p_ff_pic->age = 256*256*256*64; // FIXME FIXME from ffmpeg p_ff_pic->age = 256*256*256*64; // FIXME FIXME from ffmpeg
post_mt( p_sys );
return 0; return 0;
no_dr: no_dr:
...@@ -1036,6 +1102,7 @@ no_dr: ...@@ -1036,6 +1102,7 @@ no_dr:
msg_Warn( p_dec, "disabling direct rendering" ); msg_Warn( p_dec, "disabling direct rendering" );
p_sys->i_direct_rendering_used = 0; p_sys->i_direct_rendering_used = 0;
} }
post_mt( p_sys );
return avcodec_default_get_buffer( p_context, p_ff_pic ); return avcodec_default_get_buffer( p_context, p_ff_pic );
} }
static int ffmpeg_ReGetFrameBuf( struct AVCodecContext *p_context, AVFrame *p_ff_pic ) static int ffmpeg_ReGetFrameBuf( struct AVCodecContext *p_context, AVFrame *p_ff_pic )
......
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