Commit 352e95ad authored by Jean-Paul Saman's avatar Jean-Paul Saman

davinci: XDM 1.0 HEAAC DSP encoder

parent a8c5af18
......@@ -39,6 +39,9 @@
/* XDM 1.0 */
#include <ti/sdo/ce/audio1/audenc1.h>
/* AAC LC Encoder */
#include <ti/sdo/ce/audio1/iaacenc.h>
#include <assert.h>
/*****************************************************************************
......@@ -48,7 +51,8 @@
/* XDM 1.0 */
static block_t *EncodeAudio1( encoder_t *, aout_buffer_t * );
static inline IAUDIO_ChannelMode davinci_get_audio_channels( int i_channels );
static void davinci_get_audio_channels( int i_physical_channels, int i_original_channels,
IAUDIO_ChannelMode *channel_mode, IAUDIO_DualMonoMode *dual_mono, XDAS_Int32 *lfe );
/*****************************************************************************
* Encoder
......@@ -62,8 +66,23 @@ struct xdm_sys_t
AUDENC1_Params params;
AUDENC1_DynamicParams dparams;
AUDENC1_InArgs in_args;
XDM1_BufDesc in;
AUDENC1_OutArgs out_args;
XDM1_BufDesc out;
/* misc */
uint32_t i_channels;
uint32_t i_frames; /* number of sample frames needed */
uint32_t i_bytespersample;
/* remainder buffer management */
uint8_t *p_tmp;
size_t i_nb_bytes;
uint32_t i_nb_samples;
mtime_t start_date;
mtime_t end_date;
};
/*****************************************************************************
......@@ -74,39 +93,141 @@ int OpenEncoderAudio1( encoder_t *p_enc )
encoder_sys_t *p_sys = p_enc->p_sys;
xdm_sys_t *xdm;
p_sys->xdm = (xdm_sys_t *) calloc( 1, sizeof( xdm_sys_t ) );
p_sys->xdm = xdm = (xdm_sys_t *) calloc( 1, sizeof( xdm_sys_t ) );
if( !p_sys->xdm )
return VLC_ENOMEM;
xdm = p_sys->xdm;
/* */
xdm->p_tmp = NULL;
xdm->i_channels = aout_FormatNbChannels(&p_enc->fmt_out.audio) ?
aout_FormatNbChannels(&p_enc->fmt_out.audio) :
p_enc->fmt_out.audio.i_channels;
xdm->i_bytespersample = p_enc->fmt_out.audio.i_bitspersample >> 3;
/* */
xdm->params.size = sizeof( xdm->params );
xdm->dparams.size = sizeof( xdm->dparams );
memset( &xdm->in_args, 0, sizeof( xdm->in_args ) );
xdm->in_args.size = sizeof( xdm->in_args );
xdm->in_args.ancData.bufSize = 0L;
xdm->in_args.ancData.buf = (XDAS_Int8 *)NULL;
memset( &xdm->out_args, 0, sizeof( xdm->out_args ) );
xdm->out_args.size = sizeof( xdm->out_args );
/* */
p_enc->i_tolerance = var_CreateGetInteger( p_enc, ENC_CFG_PREFIX "tolerance" );
p_enc->i_tolerance *= 1024; /* bits per second */
xdm->params.encMode = var_CreateGetBool( p_enc, ENC_CFG_PREFIX "cbr" ) ? IAUDIO_CBR : IAUDIO_VBR;
xdm->params.encMode = var_CreateGetBool( p_enc, ENC_CFG_PREFIX "cbr" ) ?
IAUDIO_CBR : IAUDIO_VBR;
xdm->params.bitRate = p_enc->fmt_out.i_bitrate;
if( xdm->params.encMode == IAUDIO_VBR )
xdm->params.maxBitRate = p_enc->fmt_out.i_bitrate + p_enc->i_tolerance;
else
xdm->params.maxBitRate = p_enc->fmt_out.i_bitrate;
xdm->params.sampleRate = p_enc->fmt_out.audio.i_rate;
xdm->params.channelMode = davinci_get_audio_channels( p_enc->fmt_out.audio.i_channels );
if( xdm->params.channelMode == IAUDIO_11_0 )
xdm->params.dualMonoMode = IAUDIO_DUALMONO_LR;
davinci_get_audio_channels( p_enc->fmt_out.audio.i_physical_channels,
p_enc->fmt_out.audio.i_original_channels,
(IAUDIO_ChannelMode*)&xdm->params.channelMode,
(IAUDIO_DualMonoMode*)&xdm->params.dualMonoMode,
&xdm->params.lfeFlag );
xdm->params.dataEndianness = XDM_LE_16;
xdm->params.inputFormat = IAUDIO_INTERLEAVED; // IAUDIO_BLOCK
xdm->params.inputFormat = IAUDIO_INTERLEAVED; /* IAUDIO_BLOCK; */
xdm->params.inputBitsPerSample = p_enc->fmt_out.audio.i_bitspersample;
xdm->params.crcFlag = XDAS_FALSE;
xdm->params.ancFlag = XDAS_FALSE;
xdm->params.lfeFlag = XDAS_FALSE;
msg_Info( p_enc, "audio %d channels, %d Hz (max bitrate %d kBps)\n",
(int)p_enc->fmt_out.audio.i_channels,
msg_Info( p_enc, "DSP algorithm '%s', audio %d channels, samplerate %d Hz (max bitrate %d kbps)\n",
p_sys->psz_codec, xdm->i_channels,
(int)xdm->params.sampleRate,
((int)xdm->params.maxBitRate) >> 13 /* / (8*1024)*/);
((int)xdm->params.maxBitRate/1000) );
/* Set codec specific parameters */
if( VLC_FOURCC('m','p','4','a') == p_enc->fmt_out.i_codec ||
VLC_FOURCC('a','a','c',' ') == p_enc->fmt_out.i_codec )
{
IAACENC_Params aacParams;
char *psz_aac_profile = var_CreateGetString( p_enc, ENC_CFG_PREFIX "aac-profile" );
xdm->params.size = sizeof( aacParams );
memcpy( &aacParams.audenc_params, &(xdm->params), sizeof( xdm->params ) );
xdm->i_frames = 2048; /* HE AAC frame size */
if( !strncmp(psz_aac_profile, "sbr", 3) )
aacParams.outObjectType = AACENC_OBJ_TYP_HEAAC; /* HE-AAC with SBR */
else if( !strncmp(psz_aac_profile, "ps", 2) )
aacParams.outObjectType = AACENC_OBJ_TYP_PS; /* HE-AAC with SBR and PS */
else if( !strncmp(psz_aac_profile, "low", 3) )
{
aacParams.outObjectType = AACENC_OBJ_TYP_LC; /* Low Complexity AAC */
xdm->i_frames = 1024; /* LC AAC frame size */
}
else
{
msg_Err( p_enc, "AAC encoder does not support this profile: '%s'",
psz_aac_profile );
free( psz_aac_profile );
goto error;
}
free( psz_aac_profile );
msg_Dbg( p_enc, "using aac-profile '%s'",
aacParams.outObjectType == AACENC_OBJ_TYP_HEAAC ? "sbr" :
aacParams.outObjectType == AACENC_OBJ_TYP_PS ? "ps" : "low" );
/* boundary checks */
switch( aacParams.outObjectType )
{
default:
case AACENC_OBJ_TYP_LC:
if( xdm->params.maxBitRate > (192*1024) ||
xdm->params.sampleRate > 96000 ||
xdm->params.sampleRate < 8000 )
{
msg_Err( p_enc, "samplerate between range 8000 and 96000 Hz and "
"bitrate smaller then 192 kbit/s expected" );
goto error;
}
if( xdm->params.channelMode != IAUDIO_2_0 )
{
msg_Err( p_enc,
"AAC LC encoder only supports 2 channels %d requested",
xdm->i_channels );
goto error;
}
break;
case AACENC_OBJ_TYP_HEAAC:
case AACENC_OBJ_TYP_PS:
if( xdm->params.maxBitRate > (64*1024) ||
xdm->params.sampleRate > 48000 ||
xdm->params.sampleRate < 16000 )
{
msg_Err( p_enc, "samplerate between range 16000 and 48000 Hz and "
"bitrate smaller then 64 kbit/s expected" );
goto error;
}
break;
}
aacParams.outFileFormat = AACENC_TT_ADTS; /* ADTS formatted */
aacParams.useTns = AACENC_TRUE;
aacParams.usePns = AACENC_TRUE;
aacParams.downMixFlag = AACENC_FALSE;
aacParams.bitRateMode = AACENC_BR_MODE_VBR_5;
aacParams.ancRate = 0; /* default -1 */
xdm->handle = AUDENC1_create( p_sys->engine, (String)p_sys->psz_codec,
(AUDENC1_Params *)&aacParams );
}
else
{
xdm->handle = AUDENC1_create( p_sys->engine, (String)p_sys->psz_codec,
&xdm->params );
}
/* Create encoder handle */
xdm->handle = AUDENC1_create( p_sys->engine, (String)p_sys->psz_codec, &xdm->params );
if( !xdm->handle )
{
goto error;
......@@ -126,6 +247,8 @@ void CloseEncoderAudio1( encoder_t *p_enc )
encoder_sys_t *p_sys = p_enc->p_sys;
xdm_sys_t *xdm = p_sys->xdm;
if( !xdm ) return;
/* Delete audio encoder */
if( p_enc->fmt_out.i_cat == AUDIO_ES )
AUDENC1_delete( xdm->handle );
......@@ -134,6 +257,7 @@ void CloseEncoderAudio1( encoder_t *p_enc )
davinci_FreeBuffer1( &xdm->in );
davinci_FreeBuffer1( &xdm->out );
free( xdm->p_tmp );
free( xdm );
xdm = NULL;
}
......@@ -141,60 +265,180 @@ void CloseEncoderAudio1( encoder_t *p_enc )
/*****************************************************************************
* Audio Encoder: XDM 1.0 API
*****************************************************************************/
static inline IAUDIO_ChannelMode davinci_get_audio_channels( int i_channels )
static void davinci_get_audio_channels( int i_physical_channels, int i_original_channels,
IAUDIO_ChannelMode *channel_mode, IAUDIO_DualMonoMode *dual_mono, XDAS_Int32 *lfe )
{
IAUDIO_ChannelMode i_mode = IAUDIO_2_0;
switch( i_channels )
/* default setting */
*channel_mode = IAUDIO_2_0;
*dual_mono = IAUDIO_DUALMONO_LR;
*lfe = XDAS_FALSE;
switch ( i_physical_channels & AOUT_CHAN_PHYSMASK )
{
case 1: i_mode = IAUDIO_1_0; /* Single channel. */
break;
case 2: i_mode = IAUDIO_2_0; /* Two channel. */
break;
case 3: i_mode = IAUDIO_3_0; /* Three channel. */
break;
case 4: i_mode = IAUDIO_3_1; /* Four channel. */
break;
case 5: i_mode = IAUDIO_3_2; /* Five channel. */
break;
case 6: i_mode = IAUDIO_2_3; /* 5.1 channel. */
break;
case 7: i_mode = IAUDIO_3_4; /* 7.1 channel. */
break;
default: i_mode = IAUDIO_2_0; /**< Two channel. */
break;
case AOUT_CHAN_LEFT:
case AOUT_CHAN_RIGHT:
case AOUT_CHAN_CENTER:
if ( (i_original_channels & AOUT_CHAN_CENTER)
|| (i_original_channels
& (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT)) )
*channel_mode = IAUDIO_1_0;
else if ( i_original_channels & AOUT_CHAN_LEFT )
*channel_mode = IAUDIO_1_0;
else
*channel_mode = IAUDIO_1_0;
break;
case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT:
if ( i_original_channels & AOUT_CHAN_REVERSESTEREO )
{
if ( i_original_channels & AOUT_CHAN_DOLBYSTEREO )
*channel_mode = IAUDIO_2_0;
else
*channel_mode = IAUDIO_2_0;
}
else
{
if ( i_original_channels & AOUT_CHAN_DUALMONO )
{
*channel_mode = IAUDIO_11_0;
*dual_mono = IAUDIO_DUALMONO_LR;
}
else if ( i_original_channels == AOUT_CHAN_CENTER )
*channel_mode = IAUDIO_2_0;
else if ( !(i_original_channels & AOUT_CHAN_RIGHT) )
*channel_mode = IAUDIO_2_0;
else if ( !(i_original_channels & AOUT_CHAN_LEFT) )
*channel_mode = IAUDIO_2_0;
else
*channel_mode = IAUDIO_2_0;
}
break;
case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER:
*channel_mode = IAUDIO_3_0;
break;
case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARCENTER:
*channel_mode = IAUDIO_2_1;
break;
case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
| AOUT_CHAN_REARCENTER:
*channel_mode = IAUDIO_3_1;
break;
case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
| AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT:
*channel_mode = IAUDIO_2_2;
break;
case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
| AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT:
*channel_mode = IAUDIO_2_2;
break;
case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
| AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT:
*channel_mode = IAUDIO_3_2;
break;
case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
| AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT:
*channel_mode = IAUDIO_3_3;
break;
/* LFE */
case AOUT_CHAN_CENTER | AOUT_CHAN_LFE:
*lfe = XDAS_TRUE;
if ( (i_original_channels & AOUT_CHAN_CENTER)
|| (i_original_channels
& (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT)) )
*channel_mode = IAUDIO_1_0;
else if ( i_original_channels & AOUT_CHAN_LEFT )
*channel_mode = IAUDIO_1_0;
else
*channel_mode = IAUDIO_1_0;
break;
case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_LFE:
*lfe = XDAS_TRUE;
if ( i_original_channels & AOUT_CHAN_DOLBYSTEREO )
*channel_mode = IAUDIO_2_0;
else if ( i_original_channels & AOUT_CHAN_DUALMONO )
{
*channel_mode = IAUDIO_11_0;
*dual_mono = IAUDIO_DUALMONO_LR;
}
else if ( i_original_channels == AOUT_CHAN_CENTER )
*channel_mode = IAUDIO_1_0;
else if ( !(i_original_channels & AOUT_CHAN_RIGHT) )
*channel_mode = IAUDIO_2_0;
else if ( !(i_original_channels & AOUT_CHAN_LEFT) )
*channel_mode = IAUDIO_2_0;
else
*channel_mode = IAUDIO_2_0;
break;
case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_LFE:
*lfe = XDAS_TRUE;
*channel_mode = IAUDIO_3_0;
break;
case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARCENTER
| AOUT_CHAN_LFE:
*lfe = XDAS_TRUE;
*channel_mode = IAUDIO_2_1;
break;
case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
| AOUT_CHAN_REARCENTER | AOUT_CHAN_LFE:
*lfe = XDAS_TRUE;
*channel_mode = IAUDIO_3_1;
break;
case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
| AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE:
*lfe = XDAS_TRUE;
*channel_mode = IAUDIO_2_2;
break;
case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
| AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE:
*lfe = XDAS_TRUE;
*channel_mode = IAUDIO_2_3;
break;
case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
| AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE:
*lfe = XDAS_TRUE;
*channel_mode = IAUDIO_3_2;
break;
case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
| AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE:
*lfe = XDAS_TRUE;
*channel_mode = IAUDIO_3_3;
break;
case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
| AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT
| AOUT_CHAN_MIDDLERIGHT:
*channel_mode = IAUDIO_3_4;
break;
case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
| AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT
| AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE:
*lfe = XDAS_TRUE;
*channel_mode = IAUDIO_3_4;
break;
}
return i_mode;
}
static inline int davinci_InitAudio1Buffers( encoder_t *p_enc )
/* NOTE: The DSP TI audio codecs generate a output packet with header and
* 0 as data on a parameters change. Thus only change parameters when it is
* needed with davinci_SetDynamicParams.
*/
static inline int davinci_SetDynamicParams( encoder_t *p_enc )
{
encoder_sys_t *p_sys = p_enc->p_sys;
xdm_sys_t *xdm = p_sys->xdm;
int i_ret = VLC_SUCCESS;
AUDENC1_Status status;
xdm->dparams.size = sizeof( xdm->dparams );
memset( &status, 0, sizeof( status ) );
status.size = sizeof( status );
/* Configue the encoder */
xdm->dparams.bitRate = p_enc->fmt_out.i_bitrate;
xdm->dparams.sampleRate = p_enc->fmt_out.audio.i_rate;
xdm->dparams.channelMode = davinci_get_audio_channels( p_enc->fmt_out.audio.i_channels );
if( xdm->dparams.channelMode == IAUDIO_11_0 )
xdm->dparams.dualMonoMode = IAUDIO_DUALMONO_LR;
xdm->dparams.lfeFlag = XDAS_FALSE; /* FIXME: What to fill in here?
* Number of LFE (Low Frequency Effects) channels in the stream. */
xdm->dparams.inputBitsPerSample = p_enc->fmt_out.audio.i_bitspersample;
//(p_enc->fmt_in.i_codec == AOUT_FMT_S16_NE) ? 16: 32;
davinci_get_audio_channels( p_enc->fmt_out.audio.i_physical_channels,
p_enc->fmt_out.audio.i_original_channels,
(IAUDIO_ChannelMode*)&xdm->dparams.channelMode,
(IAUDIO_DualMonoMode*)&xdm->dparams.dualMonoMode,
&xdm->dparams.lfeFlag );
assert( xdm->dparams.channelMode == xdm->params.channelMode );
msg_Info( p_enc, "using %d channels at %d Hz samplerate (bitrate %d kBps, "
"%d bits per sample)\n",
p_enc->fmt_out.audio.i_channels,
(int)xdm->dparams.sampleRate,
((int)xdm->dparams.bitRate) >> 13 /* / (8*1024)*/,
(int)xdm->dparams.inputBitsPerSample );
xdm->dparams.inputBitsPerSample = p_enc->fmt_out.audio.i_bitspersample;
if( AUDENC1_control( xdm->handle, XDM_SETPARAMS, &xdm->dparams, &status )
!= AUDENC1_EOK )
......@@ -203,6 +447,20 @@ static inline int davinci_InitAudio1Buffers( encoder_t *p_enc )
return VLC_EGENERIC;
}
return VLC_SUCCESS;
}
static inline int davinci_InitAudio1Buffers( encoder_t *p_enc )
{
encoder_sys_t *p_sys = p_enc->p_sys;
xdm_sys_t *xdm = p_sys->xdm;
int i_ret = VLC_SUCCESS;
AUDENC1_Status status;
memset( &status, 0, sizeof( status ) );
status.size = sizeof( status );
/* Configure buffers */
if( AUDENC1_control( xdm->handle, XDM_GETBUFINFO, &xdm->dparams, &status )
!= AUDENC1_EOK )
......@@ -231,62 +489,190 @@ static inline int davinci_InitAudio1Buffers( encoder_t *p_enc )
return i_ret;
}
#if 0
static void DumpBuffers( const uint8_t *src, const uint32_t size )
{
int n = 0;
printf("\n");
for( uint32_t i = 0; i < size; i++, n++ )
{
if ((n % 20) == 0)
printf( "\n %.4d: ", n );
printf( "0x%.2x ", src[i] );
}
printf("\n");
}
#endif
static block_t *EncodeAudio1( encoder_t *p_enc, aout_buffer_t *p_buffer )
{
encoder_sys_t *p_sys = p_enc->p_sys;
xdm_sys_t *xdm = p_sys->xdm;
AUDENC1_InArgs in_args;
AUDENC1_OutArgs out_args;
block_t *p_block;
int i_ret;
uint32_t i_nb_samples = 0;
mtime_t i_pts = (mtime_t)0;
mtime_t i_pts_end = (mtime_t)0;
if( xdm->in.numBufs == 0 || xdm->out.numBufs == 0 )
{
if( davinci_InitAudio1Buffers( p_enc ) != VLC_SUCCESS )
return NULL;
if( xdm->p_tmp == NULL )
{
xdm->p_tmp = (int8_t *) malloc( (uint32_t)xdm->in.descs[0].bufSize * sizeof(int8_t) );
if( xdm->p_tmp == NULL )
return NULL;
}
if( davinci_SetDynamicParams( p_enc ) != VLC_SUCCESS )
{
msg_Warn( p_enc, "Failed setting dynamic params" );
}
msg_Info( p_enc, "using %d channels at %d Hz samplerate (bitrate %d kbp/s, "
"%d bits per sample)\n",
xdm->i_channels,
(int)xdm->dparams.sampleRate,
(int)xdm->dparams.bitRate/1000,
(int)xdm->dparams.inputBitsPerSample );
}
/* Configure input */
memset( &in_args, 0, sizeof( in_args ) );
in_args.size = sizeof( in_args );
/* buffer management */
if( (p_buffer->i_nb_bytes == (size_t)xdm->in.descs[0].bufSize) &&
(xdm->i_nb_bytes == 0) )
{
/* buffer fits in encoder buffer entirely */
memcpy( (uint8_t*)xdm->in.descs[0].buf, p_buffer->p_buffer, p_buffer->i_nb_bytes );
/* NOTE: assume interleaved channels */
memcpy( xdm->in.descs[0].buf, p_buffer->p_buffer, p_buffer->i_nb_bytes );
/* samples in DSP buffer */
i_nb_samples = p_buffer->i_nb_samples;
/* Configure output */
memset( &out_args, 0, sizeof( out_args ) );
out_args.size = sizeof( out_args );
i_pts = p_buffer->start_date;
i_pts_end = p_buffer->end_date;
xdm->start_date = 0;
xdm->end_date = 0;
}
else
{
// FIXME: optimize by using xdm->in.descs[0].buf for filling and xdm->p_tmp as overflow
// This will save several memcpy's
uint32_t i_nb_delayed_samples = 0;
size_t i_size = 0;
/* delayed pts */
if( xdm->start_date == 0 )
xdm->start_date = p_buffer->start_date;
if( xdm->i_nb_bytes + p_buffer->i_nb_bytes <= (size_t)xdm->in.descs[0].bufSize )
{
memcpy( xdm->p_tmp + xdm->i_nb_bytes, p_buffer->p_buffer, p_buffer->i_nb_bytes );
xdm->i_nb_bytes += p_buffer->i_nb_bytes;
xdm->i_nb_samples += p_buffer->i_nb_samples;
xdm->end_date = p_buffer->end_date;
if( xdm->i_nb_bytes < (size_t)xdm->in.descs[0].bufSize )
{
/* wait for more samples to arrive */
return NULL;
}
}
else // if( xdm->i_nb_bytes + p_buffer->i_nb_bytes > (size_t)xdm->in.descs[0].bufSize )
{
i_size = xdm->in.descs[0].bufSize - xdm->i_nb_bytes;
i_size = __MIN(i_size, p_buffer->i_nb_bytes);
memcpy( xdm->p_tmp + xdm->i_nb_bytes, p_buffer->p_buffer, i_size );
i_nb_delayed_samples = p_buffer->i_nb_samples - (xdm->i_frames - xdm->i_nb_samples);
xdm->i_nb_samples += (p_buffer->i_nb_samples - i_nb_delayed_samples);
xdm->i_nb_bytes += i_size;
/* compensate for incomplete buffer copy */
xdm->end_date = p_buffer->start_date +
((p_buffer->end_date - p_buffer->start_date) /
p_buffer->i_nb_samples) *
(p_buffer->i_nb_samples - i_nb_delayed_samples);
}
/* always fill entire encoder bufer */
assert( (uint32_t)xdm->in.descs[0].bufSize == xdm->i_nb_bytes );
memcpy( (uint8_t*)xdm->in.descs[0].buf, xdm->p_tmp, xdm->i_nb_bytes );
/* samples in DSP buffer */
i_nb_samples = xdm->i_nb_samples;
i_pts = xdm->start_date;
i_pts_end = xdm->end_date;
/* keep remainder */
if( i_nb_delayed_samples > 0 )
{
memset( xdm->p_tmp, 0, (uint32_t)xdm->in.descs[0].bufSize );
memcpy( xdm->p_tmp, p_buffer->p_buffer + i_size, p_buffer->i_nb_bytes - i_size );
xdm->i_nb_bytes = p_buffer->i_nb_bytes - i_size;
xdm->i_nb_samples = i_nb_delayed_samples;
xdm->start_date = i_pts_end;
xdm->end_date = p_buffer->end_date;
}
else
{
xdm->start_date = xdm->end_date = (mtime_t) 0;
xdm->i_nb_bytes = xdm->i_nb_samples = 0;
}
}
/* test: for max samples */
assert( i_nb_samples == xdm->i_frames );
/* nr. of input samples */
xdm->in_args.numInSamples = i_nb_samples;
/* Encode the audio */
if( (i_ret = AUDENC1_process( xdm->handle, &xdm->in, &xdm->out,
&in_args, &out_args )) != AUDENC1_EOK )
i_ret = AUDENC1_process( xdm->handle, (XDM1_BufDesc *)&xdm->in,
(XDM1_BufDesc *)&xdm->out,
&xdm->in_args, &xdm->out_args );
if( i_ret != AUDENC1_EOK )
{
msg_Err( p_enc, "Audio encoding failed (%d): %s", i_ret,
davinci_GetExtendedError( out_args.extendedError ) );
davinci_GetExtendedError( xdm->out_args.extendedError ) );
return NULL;
}
assert( xdm->out_args.extendedError == 0 ); // assumption - test code
#if 0
/* Print some info */
//msg_Dbg( p_enc, "Bytes generated: %d", (int)out_args.bytesGenerated );
msg_Info( p_enc, "Bytes generated: %d, buffer: %d/%d, samples: %d/%d, zeroed: %d",
(int)xdm->out_args.bytesGenerated,
(int)xdm->in.descs[0].bufSize, (int)xdm->out.descs[0].bufSize,
(int)xdm->in_args.numInSamples, (int)xdm->out_args.numInSamples,
(int)xdm->out_args.numZeroesPadded );
#endif
/* Put everything in the block */
if( out_args.bytesGenerated <= 0 )
if( xdm->out_args.bytesGenerated <= 0 )
return NULL;
p_block = block_New( p_enc, out_args.bytesGenerated );
/* process samples */
p_block = block_New( p_enc, xdm->out_args.bytesGenerated );
if( !p_block )
return NULL;
memcpy( p_block->p_buffer, xdm->out.descs[0].buf, out_args.bytesGenerated );
memcpy( p_block->p_buffer, (uint8_t *)(xdm->out.descs[0].buf), p_block->i_buffer );
/* NOTE: assumption */
p_block->i_dts = p_block->i_pts = p_buffer->start_date;
#if 0 /* output buffer */
DumpBuffers( p_block->p_buffer, (uint32_t) xdm->out_args.bytesGenerated );
#endif
/* Shamelessly copied from ffmpeg/encoder.c */
p_block->i_length = (mtime_t)1000000 *
(mtime_t)p_enc->fmt_out.audio.i_frame_length /
(mtime_t)p_enc->fmt_out.audio.i_rate;
p_block->i_length = i_pts_end - i_pts;
p_block->i_dts = p_block->i_pts = i_pts;
return p_block;
}
......
......@@ -63,6 +63,11 @@ struct xdm_sys_t
XDM_BufDesc in;
XDM_BufDesc out;
/* remainder buffer management */
uint8_t p_buffer[4096]; /* FIXME: assume buffer is 4096 */
mtime_t i_pts;
size_t i_size;
};
/*****************************************************************************
......@@ -80,6 +85,8 @@ int OpenEncoderAudio( encoder_t *p_enc )
xdm = p_sys->xdm;
xdm->params.size = sizeof( xdm->params );
xdm->dparams.size = sizeof( xdm->dparams );
switch( var_CreateGetInteger( p_enc, ENC_CFG_PREFIX "quality" ) )
{
case 1: xdm->params.encodingPreset = XDM_HIGH_QUALITY; break;
......@@ -118,6 +125,8 @@ void CloseEncoderAudio( encoder_t *p_enc )
encoder_sys_t *p_sys = p_enc->p_sys;
xdm_sys_t *xdm = p_sys->xdm;
if( !xdm ) return;
/* Delete audio encoder */
if( p_enc->fmt_out.i_cat == AUDIO_ES )
AUDENC_delete( xdm->handle );
......@@ -133,15 +142,12 @@ void CloseEncoderAudio( encoder_t *p_enc )
/*****************************************************************************
* Audio Encoder: XDM 0.9
*****************************************************************************/
static inline int davinci_InitAudioBuffers( encoder_t *p_enc )
static inline int davinci_SetDynamicParams( encoder_t *p_enc )
{
encoder_sys_t *p_sys = p_enc->p_sys;
xdm_sys_t *xdm = p_sys->xdm;
int i_ret = VLC_SUCCESS;
AUDENC_Status status;
xdm->dparams.size = sizeof( xdm->dparams );
memset( &status, 0, sizeof( status ) );
status.size = sizeof( status );
......@@ -172,14 +178,6 @@ static inline int davinci_InitAudioBuffers( encoder_t *p_enc )
xdm->dparams.numLFEChannels = 0; /* FIXME: What to fill in here?
* Number of LFE (Low Frequency Effects) channels in the stream. */
xdm->dparams.inputBitsPerSample = p_enc->fmt_out.audio.i_bitspersample;
//p_enc->fmt_in.i_codec == AOUT_FMT_S16_NE) ? 16: 32;
msg_Info( p_enc, "using %d channels at %d Hz samplerate (bitrate %d kBps, "
"%d bits per sample)\n",
p_enc->fmt_out.audio.i_channels,
(int)xdm->dparams.sampleRate,
((int)xdm->dparams.bitRate) >> 13 /* / (8*1024)*/,
(int)xdm->dparams.inputBitsPerSample );
if( AUDENC_control( xdm->handle, XDM_SETPARAMS, &xdm->dparams, &status )
!= AUDENC_EOK )
......@@ -188,6 +186,20 @@ static inline int davinci_InitAudioBuffers( encoder_t *p_enc )
return VLC_EGENERIC;
}
return VLC_SUCCESS;
}
static inline int davinci_InitAudioBuffers( encoder_t *p_enc )
{
encoder_sys_t *p_sys = p_enc->p_sys;
xdm_sys_t *xdm = p_sys->xdm;
int i_ret = VLC_SUCCESS;
AUDENC_Status status;
memset( &status, 0, sizeof( status ) );
status.size = sizeof( status );
/* Configure buffers */
if( AUDENC_control( xdm->handle, XDM_GETBUFINFO, &xdm->dparams, &status )
!= AUDENC_EOK )
......@@ -226,19 +238,58 @@ static block_t *EncodeAudio( encoder_t *p_enc, aout_buffer_t *p_buffer )
block_t *p_block;
int i_ret;
if( davinci_SetDynamicParams( p_enc ) != VLC_SUCCESS )
{
msg_Warn( p_enc, "Failed setting dynamic params." );
}
if( xdm->in.numBufs == 0 || xdm->out.numBufs == 0 )
{
msg_Info( p_enc, "using %d channels at %d Hz samplerate (bitrate %d kBps, "
"%d bits per sample)\n",
p_enc->fmt_out.audio.i_channels,
(int)xdm->dparams.sampleRate,
((int)xdm->dparams.bitRate) >> 13 /* / (8*1024)*/,
(int)xdm->dparams.inputBitsPerSample );
if( davinci_InitAudioBuffers( p_enc ) != VLC_SUCCESS )
return NULL;
}
/* NOTE: assume interleaved channels */
if( xdm->i_size == 0 )
{ /* buffer is filled in one go */
memcpy( xdm->in.bufs[0], p_buffer->p_buffer, p_buffer->i_nb_bytes );
if( p_buffer->i_nb_bytes < (uint32_t)xdm->in.bufSizes[0] )
{
xdm->i_size = p_buffer->i_nb_bytes;
xdm->i_pts = p_buffer->start_date;
return NULL; /* wait till buffer is filled */
}
xdm->i_pts = 0;
}
else
{
/* there is a remainder */
size_t i_remainder = (uint32_t)xdm->in.bufSizes[0] - xdm->i_size;
if( i_remainder > p_buffer->i_nb_bytes )
i_remainder = p_buffer->i_nb_bytes;
if( xdm->i_size > 0 )
memcpy( xdm->in.bufs[0], xdm->p_buffer, xdm->i_size );
memcpy( xdm->in.bufs[0] + xdm->i_size, p_buffer->p_buffer, i_remainder );
/* keep remainder part of buffer */
if( i_remainder < (size_t)xdm->in.bufSizes[0] )
{
memcpy( xdm->p_buffer, p_buffer->p_buffer + i_remainder, p_buffer->i_nb_bytes - i_remainder );
xdm->i_size = (p_buffer->i_nb_bytes - i_remainder);
}
}
/* Configure input */
memset( &in_args, 0, sizeof( in_args ) );
in_args.size = sizeof( in_args );
/* NOTE: assume interleaved channels */
memcpy( xdm->in.bufs[0], p_buffer->p_buffer, p_buffer->i_nb_bytes );
/* Configure output */
memset( &out_args, 0, sizeof( out_args ) );
out_args.size = sizeof( out_args );
......
......@@ -62,6 +62,7 @@
* Encoder
*/
/* video settings */
#define ENC_KEYINT_TEXT N_( "Ratio of key frames" )
#define ENC_KEYINT_LONGTEXT N_( "Number of frames " \
"that will be coded for one key frame." )
......@@ -85,6 +86,19 @@
#define ENC_CBR_LONGTEXT N_( "Use constant bitrate encoding. If disabled, " \
"then variable bitrate encoding is used resulting in higher bandwidth savings." )
/* audio settings */
#define ENC_PROFILE_TEXT N_( "Specify AAC audio profile to use" )
#define ENC_PROFILE_LONGTEXT N_( "Specify the AAC audio profile to use " \
"for encoding the audio bitstream. It takes the following options: " \
"low (LC), sbr (HE) and ps (HEv2) (default: low)" )
/* */
#ifdef ENABLE_SOUT
static const char *const enc_aac_profile_list[] = { "low", "sbr", "ps" };
static const char *const enc_aac_profile_list_text[] = {
N_("low"), N_("sbr"), N_("ps") };
#endif
/* */
#define MODULE_DESCRIPTION N_( "Various audio and video decoders/encoders" \
"delivered by TI Davinci library. This includes MPEG4, H264, VC-1, "\
......@@ -125,25 +139,28 @@ vlc_module_begin()
/* encoder settings - XDM 0.9 only */
add_integer( ENC_CFG_PREFIX "quality", 0, NULL, ENC_QUALITY_TEXT,
ENC_QUALITY_LONGTEXT, true )
ENC_QUALITY_LONGTEXT, false )
change_integer_range( 0, 3 )
/* encoder settings - XDM 1.0 only */
add_bool( ENC_CFG_PREFIX "cbr", true, NULL, ENC_CBR_TEXT,
ENC_CBR_LONGTEXT, true )
ENC_CBR_LONGTEXT, false )
/* video encoder settings - XDM all versions */
add_integer( ENC_CFG_PREFIX "keyint", 0, NULL, ENC_KEYINT_TEXT,
ENC_KEYINT_LONGTEXT, false )
add_bool( ENC_CFG_PREFIX "interlace", false, NULL, ENC_INTERLACE_TEXT,
ENC_INTERLACE_LONGTEXT, true )
ENC_INTERLACE_LONGTEXT, false )
add_integer( ENC_CFG_PREFIX "rc", 1, NULL, ENC_RC_TEXT,
ENC_RC_LONGTEXT, true )
ENC_RC_LONGTEXT, false )
change_integer_range( 0, 5 )
add_integer( ENC_CFG_PREFIX "tolerance", 0, NULL, ENC_VT_TEXT,
ENC_VT_LONGTEXT, true )
ENC_VT_LONGTEXT, false )
/* audio encoder settings */
add_string( ENC_CFG_PREFIX "aac-profile", "low", NULL,
ENC_PROFILE_TEXT, ENC_PROFILE_LONGTEXT, false )
change_string_list( enc_aac_profile_list, enc_aac_profile_list_text, 0 )
#endif
#if 0
......
......@@ -44,7 +44,11 @@
/*****************************************************************************
* Encoder
*****************************************************************************/
static const char *const ppsz_enc_options[] = {
"aac-profile", "cbr", "engine", "fourcc", "keyint", "interlace", "quality",
"rc", "tolerance",
NULL
};
/*****************************************************************************
*
......@@ -97,6 +101,8 @@ int OpenEncoder( vlc_object_t *p_this )
davinci_PrintAvailableAlgorithms( p_this, p_sys->psz_ti_engine );
config_ChainParse( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg );
/* Initialize random stuff */
switch( i_cat )
{
......@@ -134,9 +140,7 @@ error:
(i_cat == AUDIO_ES) ? "audio" : "other",
p_sys->psz_codec, psz_namecodec );
if( p_sys->engine ) Engine_close( p_sys->engine );
free( p_sys->psz_ti_engine );
free( p_sys );
CloseEncoder( p_this );
return VLC_EGENERIC;
}
......@@ -179,7 +183,8 @@ void CloseEncoder( vlc_object_t *p_this )
Engine_close( p_sys->engine );
/* Exit the codec engine */
CERuntime_exit(); /* FIXME: Should this be done only once (if we have encoder + decoder runing) */
/* FIXME: Should this be done only once (if we have encoder + decoder runing) */
CERuntime_exit();
free( p_sys->psz_ti_engine );
free( p_sys );
......
......@@ -65,7 +65,7 @@
#define DAVINCI_ENC_H264 "h264enc"
#define DAVINCI_ENC_VC1 "vc1enc"
#define DAVINCI_ENC_AAC "aaclcenc"
#define DAVINCI_ENC_AAC "aacheenc"
#define DAVINCI_ENC_G711 "g711enc"
#define DAVINCI_NONE ""
......
......@@ -93,6 +93,8 @@ void CloseEncoderVideo( encoder_t *p_enc )
encoder_sys_t *p_sys = p_enc->p_sys;
xdm_sys_t *xdm = p_sys->xdm;
if( !xdm ) return;
/* Delete video encoder */
if( p_enc->fmt_out.i_cat == VIDEO_ES )
VIDENC_delete( xdm->handle );
......
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