Commit 9cd84c84 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

avcodec: use a reference-counted frame

parent ea830431
...@@ -51,6 +51,11 @@ static inline void avcodec_free_context( AVCodecContext **ctx ) ...@@ -51,6 +51,11 @@ static inline void avcodec_free_context( AVCodecContext **ctx )
} }
#endif #endif
#if !LIBAVCODEC_VERSION_CHECK( 55, 28, 1, 45, 101 )
# define av_frame_alloc avcodec_alloc_frame
# define av_frame_free avcodec_free_frame
#endif
#endif /* HAVE_LIBAVCODEC_AVCODEC_H */ #endif /* HAVE_LIBAVCODEC_AVCODEC_H */
#ifdef HAVE_LIBAVUTIL_AVUTIL_H #ifdef HAVE_LIBAVUTIL_AVUTIL_H
......
...@@ -52,8 +52,6 @@ struct decoder_sys_t ...@@ -52,8 +52,6 @@ struct decoder_sys_t
/* Video decoder specific part */ /* Video decoder specific part */
mtime_t i_pts; mtime_t i_pts;
AVFrame *p_ff_pic;
/* for frame skipping algo */ /* for frame skipping algo */
bool b_hurry_up; bool b_hurry_up;
enum AVDiscard i_skip_frame; enum AVDiscard i_skip_frame;
...@@ -321,7 +319,6 @@ int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context, ...@@ -321,7 +319,6 @@ int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context,
p_sys->p_context = p_context; p_sys->p_context = p_context;
p_sys->p_codec = p_codec; p_sys->p_codec = p_codec;
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 ); vlc_sem_init( &p_sys->sem_mt, 0 );
...@@ -402,6 +399,7 @@ int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context, ...@@ -402,6 +399,7 @@ int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context,
/* Always use our get_buffer wrapper so we can calculate the /* Always use our get_buffer wrapper so we can calculate the
* PTS correctly */ * PTS correctly */
p_context->get_buffer2 = lavc_GetFrame; p_context->get_buffer2 = lavc_GetFrame;
p_context->refcounted_frames = true;
p_context->opaque = p_dec; p_context->opaque = p_dec;
#ifdef HAVE_AVCODEC_MT #ifdef HAVE_AVCODEC_MT
...@@ -491,7 +489,6 @@ int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context, ...@@ -491,7 +489,6 @@ int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context,
/* ***** Open the codec ***** */ /* ***** Open the codec ***** */
if( OpenVideoCodec( p_dec ) < 0 ) if( OpenVideoCodec( p_dec ) < 0 )
{ {
avcodec_free_frame( &p_sys->p_ff_pic );
vlc_sem_destroy( &p_sys->sem_mt ); vlc_sem_destroy( &p_sys->sem_mt );
free( p_sys ); free( p_sys );
return VLC_EGENERIC; return VLC_EGENERIC;
...@@ -650,6 +647,13 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) ...@@ -650,6 +647,13 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
int i_used, b_gotpicture; int i_used, b_gotpicture;
AVPacket pkt; AVPacket pkt;
AVFrame *frame = av_frame_alloc();
if (unlikely(frame == NULL))
{
p_dec->b_error = true;
break;
}
post_mt( p_sys ); post_mt( p_sys );
av_init_packet( &pkt ); av_init_packet( &pkt );
...@@ -683,8 +687,8 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) ...@@ -683,8 +687,8 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
p_block->i_dts = VLC_TS_INVALID; p_block->i_dts = VLC_TS_INVALID;
} }
i_used = avcodec_decode_video2( p_context, p_sys->p_ff_pic, i_used = avcodec_decode_video2( p_context, frame, &b_gotpicture,
&b_gotpicture, &pkt ); &pkt );
av_free_packet( &pkt ); av_free_packet( &pkt );
wait_mt( p_sys ); wait_mt( p_sys );
...@@ -699,6 +703,7 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) ...@@ -699,6 +703,7 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
if( i_used < 0 ) if( i_used < 0 )
{ {
av_frame_unref(frame);
if( b_drawpicture ) if( b_drawpicture )
msg_Warn( p_dec, "cannot decode one frame (%zu bytes)", msg_Warn( p_dec, "cannot decode one frame (%zu bytes)",
p_block->i_buffer ); p_block->i_buffer );
...@@ -719,21 +724,21 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) ...@@ -719,21 +724,21 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
/* Nothing to display */ /* Nothing to display */
if( !b_gotpicture ) if( !b_gotpicture )
{ {
av_frame_unref(frame);
if( i_used == 0 ) break; if( i_used == 0 ) break;
continue; continue;
} }
/* Sanity check (seems to be needed for some streams) */ /* Sanity check (seems to be needed for some streams) */
if( p_sys->p_ff_pic->pict_type == AV_PICTURE_TYPE_B) if( frame->pict_type == AV_PICTURE_TYPE_B)
{ {
p_sys->b_has_b_frames = true; p_sys->b_has_b_frames = true;
} }
/* Compute the PTS */ /* Compute the PTS */
mtime_t i_pts = mtime_t i_pts = frame->pkt_pts;
p_sys->p_ff_pic->pkt_pts;
if (i_pts <= VLC_TS_INVALID) if (i_pts <= VLC_TS_INVALID)
i_pts = p_sys->p_ff_pic->pkt_dts; i_pts = frame->pkt_dts;
if( i_pts <= VLC_TS_INVALID ) if( i_pts <= VLC_TS_INVALID )
i_pts = p_sys->i_pts; i_pts = p_sys->i_pts;
...@@ -747,8 +752,7 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) ...@@ -747,8 +752,7 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
if( p_dec->fmt_in.video.i_frame_rate > 0 && if( p_dec->fmt_in.video.i_frame_rate > 0 &&
p_dec->fmt_in.video.i_frame_rate_base > 0 ) p_dec->fmt_in.video.i_frame_rate_base > 0 )
{ {
p_sys->i_pts += CLOCK_FREQ * p_sys->i_pts += CLOCK_FREQ * (2 + frame->repeat_pict) *
(2 + p_sys->p_ff_pic->repeat_pict) *
p_dec->fmt_in.video.i_frame_rate_base / p_dec->fmt_in.video.i_frame_rate_base /
(2 * p_dec->fmt_in.video.i_frame_rate); (2 * p_dec->fmt_in.video.i_frame_rate);
} }
...@@ -758,8 +762,7 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) ...@@ -758,8 +762,7 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
if( i_tick <= 0 ) if( i_tick <= 0 )
i_tick = 1; i_tick = 1;
p_sys->i_pts += CLOCK_FREQ * p_sys->i_pts += CLOCK_FREQ * (2 + frame->repeat_pict) *
(2 + p_sys->p_ff_pic->repeat_pict) *
i_tick * p_context->time_base.num / i_tick * p_context->time_base.num /
(2 * p_context->time_base.den); (2 * p_context->time_base.den);
} }
...@@ -781,10 +784,13 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) ...@@ -781,10 +784,13 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
p_sys->i_late_frames = 0; p_sys->i_late_frames = 0;
} }
if( !b_drawpicture || ( !p_sys->p_va && !p_sys->p_ff_pic->linesize[0] ) ) if( !b_drawpicture || ( !p_sys->p_va && !frame->linesize[0] ) )
{
av_frame_unref(frame);
continue; continue;
}
picture_t *p_pic = p_sys->p_ff_pic->opaque; picture_t *p_pic = frame->opaque;
if( p_pic == NULL ) if( p_pic == NULL )
{ {
/* Get a new picture */ /* Get a new picture */
...@@ -792,18 +798,19 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) ...@@ -792,18 +798,19 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
p_pic = ffmpeg_NewPictBuf( p_dec, p_context ); p_pic = ffmpeg_NewPictBuf( p_dec, p_context );
if( !p_pic ) if( !p_pic )
{ {
av_frame_unref(frame);
if( p_block ) if( p_block )
block_Release( p_block ); block_Release( p_block );
return NULL; return NULL;
} }
/* Fill picture_t from AVFrame */ /* Fill picture_t from AVFrame */
lavc_CopyPicture(p_dec, p_pic, p_sys->p_ff_pic); lavc_CopyPicture(p_dec, p_pic, frame);
} }
else else
{ {
if( p_sys->p_va != NULL ) if( p_sys->p_va != NULL )
vlc_va_Extract( p_sys->p_va, p_pic, p_sys->p_ff_pic->data[3] ); vlc_va_Extract( p_sys->p_va, p_pic, frame->data[3] );
picture_Hold( p_pic ); picture_Hold( p_pic );
} }
...@@ -822,28 +829,23 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block ) ...@@ -822,28 +829,23 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
} }
} }
/* Send decoded frame to vout */ p_pic->date = i_pts;
if( i_pts > VLC_TS_INVALID) /* Hack to force display of still pictures */
{ p_pic->b_force = p_sys->b_first_frame;
p_pic->date = i_pts; p_pic->i_nb_fields = 2 + frame->repeat_pict;
p_pic->b_progressive = !frame->interlaced_frame;
p_pic->b_top_field_first = frame->top_field_first;
if( p_sys->b_first_frame ) av_frame_unref(frame);
{
/* Hack to force display of still pictures */
p_sys->b_first_frame = false;
p_pic->b_force = true;
}
p_pic->i_nb_fields = 2 + p_sys->p_ff_pic->repeat_pict;
p_pic->b_progressive = !p_sys->p_ff_pic->interlaced_frame;
p_pic->b_top_field_first = p_sys->p_ff_pic->top_field_first;
/* Send decoded frame to vout */
if (i_pts > VLC_TS_INVALID)
{
p_sys->b_first_frame = false;
return p_pic; return p_pic;
} }
else else
{
picture_Release( p_pic ); picture_Release( p_pic );
}
} }
if( p_block ) if( p_block )
...@@ -871,9 +873,6 @@ void EndVideoDec( decoder_t *p_dec ) ...@@ -871,9 +873,6 @@ void EndVideoDec( decoder_t *p_dec )
ffmpeg_CloseCodec( p_dec ); ffmpeg_CloseCodec( p_dec );
if( p_sys->p_ff_pic )
avcodec_free_frame( &p_sys->p_ff_pic );
if( p_sys->p_va ) if( p_sys->p_va )
vlc_va_Delete( p_sys->p_va, p_sys->p_context ); vlc_va_Delete( p_sys->p_va, p_sys->p_context );
......
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