i_thread_count = __MIN( i_thread_count, 16 );
msg_Dbg( p_dec, "allowing %d thread(s) for decoding", i_thread_count );
p_sys->p_context->thread_count = i_thread_count;
+
+ if( i_codec_id == AV_CODEC_ID_MPEG4 )
+ p_sys->p_context->thread_count = 1;
+
#endif
char *hw = var_CreateGetString( p_dec, "avcodec-hw" ); /* FIXME */
i_codec_id == AV_CODEC_ID_H264 ||
i_codec_id == AV_CODEC_ID_VC1 || i_codec_id == AV_CODEC_ID_WMV3) )
{
-#if defined(HAVE_AVCODEC_MT) && LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 1, 0)
+#if defined(HAVE_AVCODEC_MT) //&& LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 1, 0)
if( p_sys->p_context->thread_type & FF_THREAD_FRAME )
{
- msg_Warn( p_dec, "threaded frame decoding is not compatible with libavcodec-hw, disabled" );
+ msg_Warn( p_dec, "threaded frame decoding is not compatible with avcodec-hw, disabled" );
p_sys->p_context->thread_type &= ~FF_THREAD_FRAME;
}
if( ( p_sys->p_context->thread_type & FF_THREAD_SLICE ) &&
( i_codec_id == AV_CODEC_ID_MPEG1VIDEO || i_codec_id == AV_CODEC_ID_MPEG2VIDEO ) )
{
- msg_Warn( p_dec, "threaded slice decoding is not compatible with libavcodec-hw, disabled" );
+ msg_Warn( p_dec, "threaded slice decoding is not compatible with avcodec-hw, disabled" );
p_sys->p_context->thread_type &= ~FF_THREAD_SLICE;
}
#endif
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 )
- {
vlc_va_Delete( p_sys->p_va );
- p_sys->p_va = NULL;
- }
+
vlc_sem_destroy( &p_sys->sem_mt );
}
}
}
-/*****************************************************************************
- * ffmpeg_GetFrameBuf: callback used by ffmpeg to get a frame buffer.
- *****************************************************************************
- * It is used for direct rendering as well as to get the right PTS for each
- * decoded picture (even in indirect rendering mode).
- *****************************************************************************/
-static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context,
- AVFrame *p_ff_pic )
+static int ffmpeg_va_GetFrameBuf( struct AVCodecContext *p_context, AVFrame *p_ff_pic )
{
decoder_t *p_dec = (decoder_t *)p_context->opaque;
decoder_sys_t *p_sys = p_dec->p_sys;
- picture_t *p_pic;
-
- /* */
- p_ff_pic->opaque = NULL;
+ vlc_va_t *p_va = p_sys->p_va;
- if( p_sys->p_va )
+ /* hwaccel_context is not present in old ffmpeg version */
+ if( vlc_va_Setup( p_va,
+ &p_context->hwaccel_context, &p_dec->fmt_out.video.i_chroma,
+ p_context->width, p_context->height ) )
{
- /* hwaccel_context is not present in old ffmpeg version */
- if( vlc_va_Setup( p_sys->p_va,
- &p_context->hwaccel_context, &p_dec->fmt_out.video.i_chroma,
- p_context->width, p_context->height ) )
- {
- msg_Err( p_dec, "vlc_va_Setup failed" );
- return -1;
- }
-
- /* */
- p_ff_pic->type = FF_BUFFER_TYPE_USER;
-
-#if LIBAVCODEC_VERSION_MAJOR < 54
- p_ff_pic->age = 256*256*256*64;
-#endif
-
- if( vlc_va_Get( p_sys->p_va, p_ff_pic ) )
- {
- msg_Err( p_dec, "VaGrabSurface failed" );
- return -1;
- }
- return 0;
+ msg_Err( p_dec, "vlc_va_Setup failed" );
+ return -1;
}
- else if( !p_sys->b_direct_rendering )
+
+ if( vlc_va_Get( p_va, p_ff_pic ) )
{
- /* Not much to do in indirect rendering mode. */
- return avcodec_default_get_buffer( p_context, p_ff_pic );
+ msg_Err( p_dec, "vlc_va_Get failed" );
+ return -1;
}
- wait_mt( p_sys );
- /* Some codecs set pix_fmt only after the 1st frame has been decoded,
- * so we need to check for direct rendering again. */
+ p_ff_pic->type = FF_BUFFER_TYPE_USER;
+ return 0;
+}
+
+static picture_t *ffmpeg_dr_GetFrameBuf(struct AVCodecContext *p_context)
+{
+ decoder_t *p_dec = (decoder_t *)p_context->opaque;
+ decoder_sys_t *p_sys = p_dec->p_sys;
int i_width = p_context->width;
int i_height = p_context->height;
avcodec_align_dimensions( p_context, &i_width, &i_height );
- if( GetVlcChroma( &p_dec->fmt_out.video, p_context->pix_fmt ) != VLC_SUCCESS ||
- p_context->pix_fmt == PIX_FMT_PAL8 )
+ picture_t *p_pic = NULL;
+ if (GetVlcChroma(&p_dec->fmt_out.video, p_context->pix_fmt) != VLC_SUCCESS)
+ goto no_dr;
+
+ if (p_context->pix_fmt == PIX_FMT_PAL8)
goto no_dr;
p_dec->fmt_out.i_codec = p_dec->fmt_out.video.i_chroma;
- /* Get a new picture */
p_pic = ffmpeg_NewPictBuf( p_dec, p_context );
if( !p_pic )
goto no_dr;
- bool b_compatible = true;
+
if( p_pic->p[0].i_pitch / p_pic->p[0].i_pixel_pitch < i_width ||
p_pic->p[0].i_lines < i_height )
- b_compatible = false;
- for( int i = 0; i < p_pic->i_planes && b_compatible; i++ )
+ goto no_dr;
+
+ for( int i = 0; i < p_pic->i_planes; i++ )
{
unsigned i_align;
switch( p_sys->i_codec_id )
break;
}
if( p_pic->p[i].i_pitch % i_align )
- b_compatible = false;
+ goto no_dr;
if( (intptr_t)p_pic->p[i].p_pixels % i_align )
- b_compatible = false;
+ goto no_dr;
}
- if( p_context->pix_fmt == PIX_FMT_YUV422P && b_compatible )
+
+ if( p_context->pix_fmt == PIX_FMT_YUV422P )
{
if( 2 * p_pic->p[1].i_pitch != p_pic->p[0].i_pitch ||
2 * p_pic->p[2].i_pitch != p_pic->p[0].i_pitch )
- b_compatible = false;
+ goto no_dr;
}
- if( !b_compatible )
- {
+
+ return p_pic;
+
+no_dr:
+ if (p_pic)
decoder_DeletePicture( p_dec, p_pic );
- goto no_dr;
+
+ return NULL;
+}
+
+/*****************************************************************************
+ * ffmpeg_GetFrameBuf: callback used by ffmpeg to get a frame buffer.
+ *****************************************************************************
+ * It is used for direct rendering as well as to get the right PTS for each
+ * decoded picture (even in indirect rendering mode).
+ *****************************************************************************/
+static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context,
+ AVFrame *p_ff_pic )
+{
+ decoder_t *p_dec = (decoder_t *)p_context->opaque;
+ decoder_sys_t *p_sys = p_dec->p_sys;
+
+ /* */
+ p_ff_pic->opaque = NULL;
+#if ! LIBAVCODEC_VERSION_CHECK(54, 34, 0, 79, 101)
+ p_ff_pic->pkt_pts = p_context->pkt ? p_context->pkt->pts : AV_NOPTS_VALUE;
+#endif
+#if LIBAVCODEC_VERSION_MAJOR < 54
+ p_ff_pic->age = 256*256*256*64;
+#endif
+
+ if( p_sys->p_va )
+ return ffmpeg_va_GetFrameBuf(p_context, p_ff_pic);
+
+ if( !p_sys->b_direct_rendering )
+ 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,
+ * so we need to check for direct rendering again. */
+
+ picture_t *p_pic = ffmpeg_dr_GetFrameBuf(p_context);
+ if (!p_pic) {
+ if( p_sys->i_direct_rendering_used != 0 )
+ {
+ msg_Warn( p_dec, "disabling direct rendering" );
+ p_sys->i_direct_rendering_used = 0;
+ }
+
+ post_mt( p_sys );
+ return avcodec_default_get_buffer( p_context, p_ff_pic );
}
- if( p_sys->i_direct_rendering_used != 1 )
- {
+ if( p_sys->i_direct_rendering_used != 1 ) {
msg_Dbg( p_dec, "using direct rendering" );
p_sys->i_direct_rendering_used = 1;
}
p_context->draw_horiz_band = NULL;
+ post_mt( p_sys );
p_ff_pic->opaque = (void*)p_pic;
p_ff_pic->type = FF_BUFFER_TYPE_USER;
p_ff_pic->linesize[2] = p_pic->p[2].i_pitch;
p_ff_pic->linesize[3] = 0;
-#if LIBAVCODEC_VERSION_MAJOR < 54
- p_ff_pic->age = 256*256*256*64;
-#endif
-
- post_mt( p_sys );
return 0;
-
-no_dr:
- if( p_sys->i_direct_rendering_used != 0 )
- {
- msg_Warn( p_dec, "disabling direct rendering" );
- p_sys->i_direct_rendering_used = 0;
- }
- post_mt( p_sys );
- return avcodec_default_get_buffer( p_context, p_ff_pic );
}
static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *p_context,
decoder_sys_t *p_sys = p_dec->p_sys;
if( p_sys->p_va )
- {
vlc_va_Release( p_sys->p_va, p_ff_pic );
- }
- else if( !p_ff_pic->opaque )
- {
+ else if( p_ff_pic->opaque )
+ decoder_UnlinkPicture( p_dec, (picture_t*)p_ff_pic->opaque);
+ else if( p_ff_pic->type == FF_BUFFER_TYPE_INTERNAL )
/* We can end up here without the AVFrame being allocated by
* avcodec_default_get_buffer() if VA is used and the frame is
* released when the decoder is closed
*/
- if( p_ff_pic->type == FF_BUFFER_TYPE_INTERNAL )
- avcodec_default_release_buffer( p_context, p_ff_pic );
- }
- else
- {
- picture_t *p_pic = (picture_t*)p_ff_pic->opaque;
+ avcodec_default_release_buffer( p_context, p_ff_pic );
- decoder_UnlinkPicture( p_dec, p_pic );
- }
for( int i = 0; i < 4; i++ )
p_ff_pic->data[i] = NULL;
}