Commit 4d2737fc authored by Jean-Paul Saman's avatar Jean-Paul Saman

davinci: refactor and force I frames every --sout-davinci-keyint

Forcing the encoder to output an key frame at every --sout-davinci-keyint setting improves the generated stream random access feature. A client picks up the stream every keyint frames now. While previous it didn't.
parent a4556602
......@@ -63,6 +63,7 @@ struct encoder_sys_t
/* video */
VIDENC_Handle c;
VIDENC_DynamicParams dparams;
/* audio */
AUDENC_Handle a;
......@@ -70,10 +71,12 @@ struct encoder_sys_t
XDM_BufDesc in;
XDM_BufDesc out;
#ifdef FPS_DEBUG
/* stats */
mtime_t i_pts_start;
mtime_t i_pts_end;
int i_fps;
#endif
int i_pics;
};
......@@ -201,7 +204,10 @@ static int GetVideoEncoderSettings( encoder_t *p_enc, const char *psz_codec )
p_enc->i_iframes = var_CreateGetInteger( p_enc, ENC_CFG_PREFIX "keyint" );
p_enc->i_tolerance = var_CreateGetInteger( p_enc, ENC_CFG_PREFIX "tolerance" );
p_enc->i_tolerance *= 1024; /* bits per second */
p_sys->i_fps = 25;
#ifdef FPS_DEBUG
p_sys->i_fps = p_enc->i_iframes;
#endif
p_sys->dparams.size = sizeof( p_sys->dparams );
/* Configure encoder */
params.size = sizeof( params );
......@@ -267,6 +273,7 @@ static int GetVideoEncoderSettings( encoder_t *p_enc, const char *psz_codec )
return VLC_SUCCESS;
}
#ifdef FPS_DEBUG
static inline void calculate_fps( encoder_t *p_enc )
{
encoder_sys_t *p_sys = p_enc->p_sys;
......@@ -294,6 +301,7 @@ static inline void calculate_fps( encoder_t *p_enc )
p_sys->i_pts_start = p_sys->i_pts_end = (mtime_t)0;
}
}
#endif
static inline void davinci_CopyPictureToXDM( encoder_t *p_enc, XDM_BufDesc *p_buf, picture_t *p_pic )
{
......@@ -310,61 +318,59 @@ static inline void davinci_CopyPictureToXDM( encoder_t *p_enc, XDM_BufDesc *p_bu
}
}
static int davinci_InitVideoBuffers( encoder_t *p_enc )
static void davinci_InitDynamicParams( encoder_t *p_enc )
{
encoder_sys_t *p_sys = p_enc->p_sys;
int i_ret = VLC_SUCCESS;
VIDENC_DynamicParams dparams;
VIDENC_Status status;
dparams.size = sizeof( dparams );
memset( &status, 0, sizeof( status ) );
status.size = sizeof( status );
/* Configue the encoder */
dparams.inputHeight = p_enc->fmt_in.video.i_height;
dparams.inputWidth = p_enc->fmt_in.video.i_width;
dparams.refFrameRate = (p_enc->fmt_out.video.i_frame_rate_base != 0) ?
p_sys->dparams.inputHeight = p_enc->fmt_in.video.i_height;
p_sys->dparams.inputWidth = p_enc->fmt_in.video.i_width;
p_sys->dparams.refFrameRate = (p_enc->fmt_out.video.i_frame_rate_base != 0) ?
(p_enc->fmt_out.video.i_frame_rate * 1000) /
p_enc->fmt_out.video.i_frame_rate_base :
p_enc->i_iframes * 1000; /* Frames per 1000 seconds */
dparams.targetFrameRate = dparams.refFrameRate; /* input fps = output fps */
dparams.targetBitRate = p_enc->fmt_out.i_bitrate;
dparams.intraFrameInterval = p_enc->i_iframes;
dparams.generateHeader = XDM_ENCODE_AU; /* don't encode only the header */
dparams.captureWidth = 0;
dparams.forceIFrame = 0;
if( VIDENC_control( p_sys->c, XDM_SETPARAMS, &dparams, &status )
p_sys->dparams.targetFrameRate = p_sys->dparams.refFrameRate; /* input fps = output fps */
p_sys->dparams.targetBitRate = p_enc->fmt_out.i_bitrate;
p_sys->dparams.intraFrameInterval = p_enc->i_iframes;
p_sys->dparams.generateHeader = XDM_ENCODE_AU; /* don't encode only the header */
p_sys->dparams.captureWidth = 0;
p_sys->dparams.forceIFrame = 1;
}
static int davinci_SetDynamicParams( encoder_t *p_enc, VIDENC_Status *status )
{
encoder_sys_t *p_sys = p_enc->p_sys;
VIDENC_DynamicParams *dparams = &p_sys->dparams;
/* Configue the encoder */
if( VIDENC_control( p_sys->c, XDM_SETPARAMS, dparams, status )
!= VIDENC_EOK )
{
msg_Err( p_enc, "Failed to set encoder parameters: %dx%d @%d fps, "
"%d kBps, I-frame interval %d",
(int)dparams.inputWidth, (int)dparams.inputHeight,
(int)dparams.refFrameRate / 1000,
(int)dparams.targetBitRate >> 13 /* / (1024 * 8) */,
(int)dparams.intraFrameInterval );
(int)dparams->inputWidth, (int)dparams->inputHeight,
(int)dparams->refFrameRate / 1000,
(int)dparams->targetBitRate >> 13 /* / (1024 * 8) */,
(int)dparams->intraFrameInterval );
return VLC_EGENERIC;
}
msg_Info( p_enc, "using %dx%d at %.3f fps (bitrate %d kBps, I-Frame interval %d)\n",
(int)dparams.inputWidth, (int)dparams.inputHeight,
((float)dparams.targetFrameRate)/1000.,
((int)dparams.targetBitRate) >> 13 /* / (8*1024)*/,
(int)dparams.intraFrameInterval );
(int)dparams->inputWidth, (int)dparams->inputHeight,
((float)dparams->targetFrameRate)/1000.,
((int)dparams->targetBitRate) >> 13 /* / (8*1024)*/,
(int)dparams->intraFrameInterval );
/* Configure buffers */
if( VIDENC_control( p_sys->c, XDM_GETBUFINFO, &dparams, &status )
!= VIDENC_EOK )
{
msg_Err( p_enc, "Failed to get buffer info" );
return VLC_EGENERIC;
}
return VLC_SUCCESS;
}
static int davinci_InitVideoBuffers( encoder_t *p_enc, VIDENC_Status *status )
{
encoder_sys_t *p_sys = p_enc->p_sys;
int i_ret = VLC_SUCCESS;
/* Allocate input buffer(s) */
if( (i_ret = davinci_AllocateBuffer( status.bufInfo.minNumInBufs,
status.bufInfo.minInBufSize, &p_sys->in ))
if( (i_ret = davinci_AllocateBuffer( status->bufInfo.minNumInBufs,
status->bufInfo.minInBufSize, &p_sys->in ) )
!= VLC_SUCCESS )
{
msg_Err( p_enc, "Failed to allocate input buffers" );
......@@ -372,8 +378,8 @@ static int davinci_InitVideoBuffers( encoder_t *p_enc )
}
/* Allocate output buffer */
if( (i_ret = davinci_AllocateBuffer( status.bufInfo.minNumOutBufs,
status.bufInfo.minOutBufSize, &p_sys->out ))
if( (i_ret = davinci_AllocateBuffer( status->bufInfo.minNumOutBufs,
status->bufInfo.minOutBufSize, &p_sys->out ) )
!= VLC_SUCCESS )
{
msg_Err( p_enc, "Failed to allocate input buffers" );
......@@ -393,9 +399,27 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pic )
if( p_sys->in.numBufs == 0 || p_sys->out.numBufs == 0 )
{
if( davinci_InitVideoBuffers( p_enc ) != VLC_SUCCESS )
VIDENC_Status status;
memset( &status, 0, sizeof( status ) );
status.size = sizeof( status );
davinci_InitDynamicParams( p_enc );
if( davinci_SetDynamicParams( p_enc, &status ) != VLC_SUCCESS )
return NULL;
if( davinci_InitVideoBuffers( p_enc, &status ) != VLC_SUCCESS )
return NULL;
}
else if( p_sys->i_pics >= p_enc->i_iframes )
{
VIDENC_Status status;
memset( &status, 0, sizeof( status ) );
status.size = sizeof( status );
if( davinci_SetDynamicParams( p_enc, &status ) != VLC_SUCCESS )
msg_Err( p_enc, "Encoding continues with previous settings" );
p_sys->i_pics = 0;
}
p_sys->i_pics++;
davinci_CopyPictureToXDM( p_enc, &p_sys->in, p_pic );
......@@ -418,7 +442,9 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pic )
/* Print some info */
//msg_Dbg( p_enc, "Bytes generated: %d", (int)out_args.bytesGenerated );
#ifdef FPS_DEBUG
calculate_fps( p_enc );
#endif
/* Put everything in the block */
if( out_args.bytesGenerated <= 0 )
......
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