Commit 27309e80 authored by Gildas Bazin's avatar Gildas Bazin

* modules/codec/ffmpeg/encoder.c: work around stupid timestamping behaviour in libavcodec.

parent c9833343
...@@ -51,6 +51,8 @@ ...@@ -51,6 +51,8 @@
#define HURRY_UP_GUARD2 (300000) #define HURRY_UP_GUARD2 (300000)
#define HURRY_UP_GUARD3 (100000) #define HURRY_UP_GUARD3 (100000)
#define MAX_FRAME_DELAY (FF_MAX_B_FRAMES + 2)
/***************************************************************************** /*****************************************************************************
* Local prototypes * Local prototypes
*****************************************************************************/ *****************************************************************************/
...@@ -135,6 +137,10 @@ struct encoder_sys_t ...@@ -135,6 +137,10 @@ struct encoder_sys_t
vlc_bool_t b_mpeg4_matrix; vlc_bool_t b_mpeg4_matrix;
vlc_bool_t b_trellis; vlc_bool_t b_trellis;
int i_quality; /* for VBR */ int i_quality; /* for VBR */
/* Used to work around stupid timestamping behaviour in libavcodec */
uint64_t i_framenum;
mtime_t pi_delay_pts[MAX_FRAME_DELAY];
}; };
static const char *ppsz_enc_options[] = { static const char *ppsz_enc_options[] = {
...@@ -202,6 +208,7 @@ int E_(OpenEncoder)( vlc_object_t *p_this ) ...@@ -202,6 +208,7 @@ int E_(OpenEncoder)( vlc_object_t *p_this )
msg_Err( p_enc, "out of memory" ); msg_Err( p_enc, "out of memory" );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
memset( p_sys, 0, sizeof(encoder_sys_t) );
p_enc->p_sys = p_sys; p_enc->p_sys = p_sys;
p_sys->p_codec = p_codec; p_sys->p_codec = p_codec;
...@@ -210,7 +217,6 @@ int E_(OpenEncoder)( vlc_object_t *p_this ) ...@@ -210,7 +217,6 @@ int E_(OpenEncoder)( vlc_object_t *p_this )
p_sys->p_buffer_out = NULL; p_sys->p_buffer_out = NULL;
p_sys->p_buffer = NULL; p_sys->p_buffer = NULL;
p_sys->b_inited = 0;
p_sys->p_context = p_context = avcodec_alloc_context(); p_sys->p_context = p_context = avcodec_alloc_context();
...@@ -333,7 +339,7 @@ int E_(OpenEncoder)( vlc_object_t *p_this ) ...@@ -333,7 +339,7 @@ int E_(OpenEncoder)( vlc_object_t *p_this )
if( p_sys->i_key_int > 0 ) if( p_sys->i_key_int > 0 )
p_context->gop_size = p_sys->i_key_int; p_context->gop_size = p_sys->i_key_int;
p_context->max_b_frames = p_context->max_b_frames =
__MIN( p_sys->i_b_frames, FF_MAX_B_FRAMES ); __MAX( __MIN( p_sys->i_b_frames, FF_MAX_B_FRAMES ), 0 );
p_context->b_frame_strategy = 0; p_context->b_frame_strategy = 0;
#if LIBAVCODEC_BUILD >= 4687 #if LIBAVCODEC_BUILD >= 4687
...@@ -470,12 +476,6 @@ int E_(OpenEncoder)( vlc_object_t *p_this ) ...@@ -470,12 +476,6 @@ int E_(OpenEncoder)( vlc_object_t *p_this )
p_sys->p_buffer = malloc( p_sys->i_frame_size ); p_sys->p_buffer = malloc( p_sys->i_frame_size );
} }
p_sys->i_last_ref_pts = 0;
p_sys->i_buggy_pts_detect = 0;
p_sys->i_samples_delay = 0;
p_sys->i_pts = 0;
p_sys->i_last_pts = 0;
msg_Dbg( p_enc, "found encoder %s", psz_namecodec ); msg_Dbg( p_enc, "found encoder %s", psz_namecodec );
return VLC_SUCCESS; return VLC_SUCCESS;
...@@ -693,6 +693,17 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict ) ...@@ -693,6 +693,17 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict )
frame.quality = p_sys->i_quality; frame.quality = p_sys->i_quality;
/* Ugly work-around for stupid libavcodec behaviour */
#if LIBAVCODEC_BUILD >= 4722
p_sys->i_framenum++;
p_sys->pi_delay_pts[p_sys->i_framenum % MAX_FRAME_DELAY] = frame.pts;
frame.pts = p_sys->i_framenum * AV_TIME_BASE *
p_enc->fmt_in.video.i_frame_rate_base;
frame.pts += p_enc->fmt_in.video.i_frame_rate - 1;
frame.pts /= p_enc->fmt_in.video.i_frame_rate;
#endif
/* End work-around */
i_out = avcodec_encode_video( p_sys->p_context, p_sys->p_buffer_out, i_out = avcodec_encode_video( p_sys->p_context, p_sys->p_buffer_out,
AVCODEC_MAX_VIDEO_FRAME_SIZE, &frame ); AVCODEC_MAX_VIDEO_FRAME_SIZE, &frame );
...@@ -701,21 +712,37 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict ) ...@@ -701,21 +712,37 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict )
block_t *p_block = block_New( p_enc, i_out ); block_t *p_block = block_New( p_enc, i_out );
memcpy( p_block->p_buffer, p_sys->p_buffer_out, i_out ); memcpy( p_block->p_buffer, p_sys->p_buffer_out, i_out );
if( p_sys->p_context->coded_frame->pts != AV_NOPTS_VALUE &&
p_sys->p_context->coded_frame->pts != 0 &&
p_sys->i_buggy_pts_detect != p_sys->p_context->coded_frame->pts )
{
p_sys->i_buggy_pts_detect = p_sys->p_context->coded_frame->pts;
/* FIXME, 3-2 pulldown is not handled correctly */ /* FIXME, 3-2 pulldown is not handled correctly */
p_block->i_length = I64C(1000000) * p_block->i_length = I64C(1000000) *
p_enc->fmt_in.video.i_frame_rate_base / p_enc->fmt_in.video.i_frame_rate_base /
p_enc->fmt_in.video.i_frame_rate; p_enc->fmt_in.video.i_frame_rate;
if( !p_sys->p_context->max_b_frames || !p_sys->p_context->delay )
{
/* No delay -> output pts == input pts */
p_block->i_pts = p_block->i_dts = p_pict->date;
}
else if( p_sys->p_context->coded_frame->pts != AV_NOPTS_VALUE &&
p_sys->p_context->coded_frame->pts != 0 &&
p_sys->i_buggy_pts_detect != p_sys->p_context->coded_frame->pts )
{
p_sys->i_buggy_pts_detect = p_sys->p_context->coded_frame->pts;
p_block->i_pts = p_sys->p_context->coded_frame->pts; p_block->i_pts = p_sys->p_context->coded_frame->pts;
if( !p_sys->p_context->delay || /* Ugly work-around for stupid libavcodec behaviour */
( p_sys->p_context->coded_frame->pict_type != FF_I_TYPE && #if LIBAVCODEC_BUILD >= 4722
p_sys->p_context->coded_frame->pict_type != FF_P_TYPE ) ) {
int64_t i_framenum = p_block->i_pts *
p_enc->fmt_in.video.i_frame_rate /
p_enc->fmt_in.video.i_frame_rate_base / AV_TIME_BASE;
p_block->i_pts = p_sys->pi_delay_pts[i_framenum % MAX_FRAME_DELAY];
}
#endif
/* End work-around */
if( p_sys->p_context->coded_frame->pict_type != FF_I_TYPE &&
p_sys->p_context->coded_frame->pict_type != FF_P_TYPE )
{ {
p_block->i_dts = p_block->i_pts; p_block->i_dts = p_block->i_pts;
} }
...@@ -738,9 +765,6 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict ) ...@@ -738,9 +765,6 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict )
{ {
/* Buggy libavcodec which doesn't update coded_frame->pts /* Buggy libavcodec which doesn't update coded_frame->pts
* correctly */ * correctly */
p_block->i_length = I64C(1000000) *
p_enc->fmt_in.video.i_frame_rate_base /
p_enc->fmt_in.video.i_frame_rate;
p_block->i_dts = p_block->i_pts = p_pict->date; p_block->i_dts = p_block->i_pts = p_pict->date;
} }
......
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