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 @@
#define HURRY_UP_GUARD2 (300000)
#define HURRY_UP_GUARD3 (100000)
#define MAX_FRAME_DELAY (FF_MAX_B_FRAMES + 2)
/*****************************************************************************
* Local prototypes
*****************************************************************************/
......@@ -135,6 +137,10 @@ struct encoder_sys_t
vlc_bool_t b_mpeg4_matrix;
vlc_bool_t b_trellis;
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[] = {
......@@ -202,6 +208,7 @@ int E_(OpenEncoder)( vlc_object_t *p_this )
msg_Err( p_enc, "out of memory" );
return VLC_EGENERIC;
}
memset( p_sys, 0, sizeof(encoder_sys_t) );
p_enc->p_sys = p_sys;
p_sys->p_codec = p_codec;
......@@ -210,7 +217,6 @@ int E_(OpenEncoder)( vlc_object_t *p_this )
p_sys->p_buffer_out = NULL;
p_sys->p_buffer = NULL;
p_sys->b_inited = 0;
p_sys->p_context = p_context = avcodec_alloc_context();
......@@ -333,7 +339,7 @@ int E_(OpenEncoder)( vlc_object_t *p_this )
if( p_sys->i_key_int > 0 )
p_context->gop_size = p_sys->i_key_int;
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;
#if LIBAVCODEC_BUILD >= 4687
......@@ -470,12 +476,6 @@ int E_(OpenEncoder)( vlc_object_t *p_this )
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 );
return VLC_SUCCESS;
......@@ -693,6 +693,17 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict )
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,
AVCODEC_MAX_VIDEO_FRAME_SIZE, &frame );
......@@ -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 );
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 */
p_block->i_length = I64C(1000000) *
p_enc->fmt_in.video.i_frame_rate_base /
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;
if( !p_sys->p_context->delay ||
( p_sys->p_context->coded_frame->pict_type != FF_I_TYPE &&
p_sys->p_context->coded_frame->pict_type != FF_P_TYPE ) )
/* Ugly work-around for stupid libavcodec behaviour */
#if LIBAVCODEC_BUILD >= 4722
{
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;
}
......@@ -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
* 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;
}
......
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