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 ...@@ -63,6 +63,7 @@ struct encoder_sys_t
/* video */ /* video */
VIDENC_Handle c; VIDENC_Handle c;
VIDENC_DynamicParams dparams;
/* audio */ /* audio */
AUDENC_Handle a; AUDENC_Handle a;
...@@ -70,10 +71,12 @@ struct encoder_sys_t ...@@ -70,10 +71,12 @@ struct encoder_sys_t
XDM_BufDesc in; XDM_BufDesc in;
XDM_BufDesc out; XDM_BufDesc out;
#ifdef FPS_DEBUG
/* stats */ /* stats */
mtime_t i_pts_start; mtime_t i_pts_start;
mtime_t i_pts_end; mtime_t i_pts_end;
int i_fps; int i_fps;
#endif
int i_pics; int i_pics;
}; };
...@@ -201,7 +204,10 @@ static int GetVideoEncoderSettings( encoder_t *p_enc, const char *psz_codec ) ...@@ -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_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 = var_CreateGetInteger( p_enc, ENC_CFG_PREFIX "tolerance" );
p_enc->i_tolerance *= 1024; /* bits per second */ 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 */ /* Configure encoder */
params.size = sizeof( params ); params.size = sizeof( params );
...@@ -267,6 +273,7 @@ static int GetVideoEncoderSettings( encoder_t *p_enc, const char *psz_codec ) ...@@ -267,6 +273,7 @@ static int GetVideoEncoderSettings( encoder_t *p_enc, const char *psz_codec )
return VLC_SUCCESS; return VLC_SUCCESS;
} }
#ifdef FPS_DEBUG
static inline void calculate_fps( encoder_t *p_enc ) static inline void calculate_fps( encoder_t *p_enc )
{ {
encoder_sys_t *p_sys = p_enc->p_sys; encoder_sys_t *p_sys = p_enc->p_sys;
...@@ -294,6 +301,7 @@ static inline void calculate_fps( encoder_t *p_enc ) ...@@ -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; 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 ) 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 ...@@ -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; encoder_sys_t *p_sys = p_enc->p_sys;
int i_ret = VLC_SUCCESS;
VIDENC_DynamicParams dparams; p_sys->dparams.inputHeight = p_enc->fmt_in.video.i_height;
VIDENC_Status status; 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) ?
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_enc->fmt_out.video.i_frame_rate * 1000) / (p_enc->fmt_out.video.i_frame_rate * 1000) /
p_enc->fmt_out.video.i_frame_rate_base : p_enc->fmt_out.video.i_frame_rate_base :
p_enc->i_iframes * 1000; /* Frames per 1000 seconds */ p_enc->i_iframes * 1000; /* Frames per 1000 seconds */
dparams.targetFrameRate = dparams.refFrameRate; /* input fps = output fps */ p_sys->dparams.targetFrameRate = p_sys->dparams.refFrameRate; /* input fps = output fps */
dparams.targetBitRate = p_enc->fmt_out.i_bitrate; p_sys->dparams.targetBitRate = p_enc->fmt_out.i_bitrate;
dparams.intraFrameInterval = p_enc->i_iframes; p_sys->dparams.intraFrameInterval = p_enc->i_iframes;
dparams.generateHeader = XDM_ENCODE_AU; /* don't encode only the header */ p_sys->dparams.generateHeader = XDM_ENCODE_AU; /* don't encode only the header */
dparams.captureWidth = 0; p_sys->dparams.captureWidth = 0;
dparams.forceIFrame = 0; p_sys->dparams.forceIFrame = 1;
}
if( VIDENC_control( p_sys->c, XDM_SETPARAMS, &dparams, &status )
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 ) != VIDENC_EOK )
{ {
msg_Err( p_enc, "Failed to set encoder parameters: %dx%d @%d fps, " msg_Err( p_enc, "Failed to set encoder parameters: %dx%d @%d fps, "
"%d kBps, I-frame interval %d", "%d kBps, I-frame interval %d",
(int)dparams.inputWidth, (int)dparams.inputHeight, (int)dparams->inputWidth, (int)dparams->inputHeight,
(int)dparams.refFrameRate / 1000, (int)dparams->refFrameRate / 1000,
(int)dparams.targetBitRate >> 13 /* / (1024 * 8) */, (int)dparams->targetBitRate >> 13 /* / (1024 * 8) */,
(int)dparams.intraFrameInterval ); (int)dparams->intraFrameInterval );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
msg_Info( p_enc, "using %dx%d at %.3f fps (bitrate %d kBps, I-Frame interval %d)\n", msg_Info( p_enc, "using %dx%d at %.3f fps (bitrate %d kBps, I-Frame interval %d)\n",
(int)dparams.inputWidth, (int)dparams.inputHeight, (int)dparams->inputWidth, (int)dparams->inputHeight,
((float)dparams.targetFrameRate)/1000., ((float)dparams->targetFrameRate)/1000.,
((int)dparams.targetBitRate) >> 13 /* / (8*1024)*/, ((int)dparams->targetBitRate) >> 13 /* / (8*1024)*/,
(int)dparams.intraFrameInterval ); (int)dparams->intraFrameInterval );
/* Configure buffers */ return VLC_SUCCESS;
if( VIDENC_control( p_sys->c, XDM_GETBUFINFO, &dparams, &status ) }
!= VIDENC_EOK )
{ static int davinci_InitVideoBuffers( encoder_t *p_enc, VIDENC_Status *status )
msg_Err( p_enc, "Failed to get buffer info" ); {
return VLC_EGENERIC; encoder_sys_t *p_sys = p_enc->p_sys;
} int i_ret = VLC_SUCCESS;
/* Allocate input buffer(s) */ /* Allocate input buffer(s) */
if( (i_ret = davinci_AllocateBuffer( status.bufInfo.minNumInBufs, if( (i_ret = davinci_AllocateBuffer( status->bufInfo.minNumInBufs,
status.bufInfo.minInBufSize, &p_sys->in )) status->bufInfo.minInBufSize, &p_sys->in ) )
!= VLC_SUCCESS ) != VLC_SUCCESS )
{ {
msg_Err( p_enc, "Failed to allocate input buffers" ); msg_Err( p_enc, "Failed to allocate input buffers" );
...@@ -372,8 +378,8 @@ static int davinci_InitVideoBuffers( encoder_t *p_enc ) ...@@ -372,8 +378,8 @@ static int davinci_InitVideoBuffers( encoder_t *p_enc )
} }
/* Allocate output buffer */ /* Allocate output buffer */
if( (i_ret = davinci_AllocateBuffer( status.bufInfo.minNumOutBufs, if( (i_ret = davinci_AllocateBuffer( status->bufInfo.minNumOutBufs,
status.bufInfo.minOutBufSize, &p_sys->out )) status->bufInfo.minOutBufSize, &p_sys->out ) )
!= VLC_SUCCESS ) != VLC_SUCCESS )
{ {
msg_Err( p_enc, "Failed to allocate input buffers" ); 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 ) ...@@ -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( 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; 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 ); 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 ) ...@@ -418,7 +442,9 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pic )
/* Print some info */ /* Print some info */
//msg_Dbg( p_enc, "Bytes generated: %d", (int)out_args.bytesGenerated ); //msg_Dbg( p_enc, "Bytes generated: %d", (int)out_args.bytesGenerated );
#ifdef FPS_DEBUG
calculate_fps( p_enc ); calculate_fps( p_enc );
#endif
/* Put everything in the block */ /* Put everything in the block */
if( out_args.bytesGenerated <= 0 ) 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