Commit c55c4fb6 authored by Jean-Paul Saman's avatar Jean-Paul Saman

davinci: implement audio encoder (not tested)

parent 305d2ca1
......@@ -108,14 +108,20 @@ vlc_module_begin()
set_callbacks( OpenAudioDecoder, CloseAudioDecoder );
#ifdef ENABLE_SOUT
/* video encoder */
/* encoder */
add_submodule()
add_shortcut( "davinci" )
set_description( N_("DaVinci DSP video encoder" ) )
set_description( N_("DaVinci DSP encoder" ) )
set_capability( "encoder", 1337 )
set_section( N_("Encoding") , NULL )
set_callbacks( OpenVideoEncoder, CloseVideoEncoder )
set_callbacks( OpenEncoder, CloseEncoder )
/* encoder settings */
add_integer( ENC_CFG_PREFIX "quality", 0, NULL, ENC_QUALITY_TEXT,
ENC_QUALITY_LONGTEXT, true )
change_integer_range( 0, 3 )
/* video encoder settings */
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,
......@@ -125,9 +131,9 @@ vlc_module_begin()
change_integer_range( 0, 5 )
add_integer( ENC_CFG_PREFIX "tolerance", 0, NULL, ENC_VT_TEXT,
ENC_VT_LONGTEXT, true )
add_integer( ENC_CFG_PREFIX "quality", 0, NULL, ENC_QUALITY_TEXT,
ENC_QUALITY_LONGTEXT, true )
change_integer_range( 0, 3 )
/* audio encoder settings */
#endif
#if 0
/* video filter submodule */
......
......@@ -44,8 +44,8 @@ void CloseVideoDecoder( vlc_object_t * );
int OpenAudioDecoder( vlc_object_t * );
void CloseAudioDecoder( vlc_object_t * );
int OpenVideoEncoder( vlc_object_t * );
void CloseVideoEncoder( vlc_object_t * );
int OpenEncoder( vlc_object_t * );
void CloseEncoder( vlc_object_t * );
/*****************************************************************************
* Common stuff
......
......@@ -39,6 +39,7 @@
#include "davinci.h"
#include <ti/sdo/ce/video/videnc.h>
#include <ti/sdo/ce/audio/audenc.h>
#include <assert.h>
......@@ -46,6 +47,10 @@
* Local prototypes
*****************************************************************************/
static block_t *EncodeVideo( encoder_t *, picture_t * );
static block_t *EncodeAudio( encoder_t *, aout_buffer_t * );
static int GetVideoEncoderSettings( encoder_t *p_enc, const char *psz_codec );
static int GetAudioEncoderSettings( encoder_t *p_enc, const char *psz_codec );
/*****************************************************************************
* Video encoder
......@@ -55,8 +60,13 @@ struct encoder_sys_t
char *psz_ti_engine;
Engine_Handle e;
/* video */
VIDENC_Handle c;
/* audio */
AUDENC_Handle a;
XDM_BufDesc in;
XDM_BufDesc out;
};
......@@ -64,12 +74,11 @@ struct encoder_sys_t
/*****************************************************************************
*
*****************************************************************************/
int OpenVideoEncoder( vlc_object_t *p_this )
int OpenEncoder( vlc_object_t *p_this )
{
encoder_t *p_enc = (encoder_t *)p_this;
encoder_sys_t *p_sys;
Engine_Error err;
VIDENC_Params params;
int i_cat;
const char *psz_codec;
const char *psz_namecodec;
......@@ -99,11 +108,6 @@ int OpenVideoEncoder( vlc_object_t *p_this )
return VLC_ENOMEM;
}
/* FIXME: number of frames between 2 keyframes */
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 */
/* Initialize the codec engine */
CERuntime_init();
......@@ -118,6 +122,80 @@ int OpenVideoEncoder( vlc_object_t *p_this )
davinci_PrintAvailableAlgorithms( p_this, p_sys->psz_ti_engine );
/* Initialize random stuff */
switch( i_cat )
{
case VIDEO_ES:
if( GetVideoEncoderSettings( p_enc, psz_codec ) != VLC_SUCCESS )
goto error;
p_enc->pf_encode_video = EncodeVideo;
break;
case AUDIO_ES:
if( GetAudioEncoderSettings( p_enc, psz_codec ) != VLC_SUCCESS )
goto error;
p_enc->pf_encode_audio = EncodeAudio;
break;
default:
msg_Err( p_enc, "aborting unknown ES (%d)", i_cat );
goto error;
}
return VLC_SUCCESS;
error:
msg_Err( p_enc, "Failed to create %s encoder (%s) for %s",
(i_cat == VIDEO_ES) ? "video" :
(i_cat == AUDIO_ES) ? "audio" : "other",
psz_codec, psz_namecodec );
if( p_sys->e ) Engine_close( p_sys->e );
free( p_sys->psz_ti_engine );
free( p_sys );
return VLC_EGENERIC;
}
/*****************************************************************************
*
*****************************************************************************/
void CloseEncoder( vlc_object_t *p_this )
{
encoder_t *p_enc = (encoder_t *)p_this;
encoder_sys_t *p_sys = p_enc->p_sys;
/* Delete video encoder */
if( p_enc->fmt_out.i_cat == VIDEO_ES )
VIDENC_delete( p_sys->c );
/* Delete audio encoder */
if( p_enc->fmt_out.i_cat == AUDIO_ES )
AUDENC_delete( p_sys->a );
/* Delete codec engine handle */
Engine_close( p_sys->e );
/* Exit the codec engine */
CERuntime_exit(); /* XXX: Should this be done only once (if we have encoder + decoder runing) */
/* Free 'DaVinci compliant' buffers */
davinci_FreeBuffer( &p_sys->in );
davinci_FreeBuffer( &p_sys->out );
free( p_sys->psz_ti_engine );
free( p_sys );
}
/*****************************************************************************
* Video Encoder
*****************************************************************************/
static int GetVideoEncoderSettings( encoder_t *p_enc, const char *psz_codec )
{
encoder_sys_t *p_sys = p_enc->p_sys;
VIDENC_Params params;
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 */
/* Configure encoder */
params.size = sizeof( params );
switch( var_CreateGetInteger( p_enc, ENC_CFG_PREFIX "quality" ) )
......@@ -177,52 +255,11 @@ int OpenVideoEncoder( vlc_object_t *p_this )
/* Create encoder handle */
p_sys->c = VIDENC_create( p_sys->e, (String)psz_codec, &params );
if( !p_sys->c )
{
msg_Err( p_enc, "Failed to create video encoder (%s) for %s",
psz_codec, psz_namecodec );
goto error;
}
/* Initialize random stuff */
p_enc->pf_encode_video = EncodeVideo;
return VLC_EGENERIC;
return VLC_SUCCESS;
error:
if( p_sys->e ) Engine_close( p_sys->e );
free( p_sys->psz_ti_engine );
free( p_sys );
return VLC_EGENERIC;
}
/*****************************************************************************
*
*****************************************************************************/
void CloseVideoEncoder( vlc_object_t *p_this )
{
encoder_t *p_enc = (encoder_t *)p_this;
encoder_sys_t *p_sys = p_enc->p_sys;
/* Delete video encoder */
VIDENC_delete( p_sys->c );
/* Delete codec engine handle */
Engine_close( p_sys->e );
/* Exit the codec engine */
CERuntime_exit(); /* XXX: Should this be done only once (if we have encoder + decoder runing) */
/* Free 'DaVinci compliant' buffers */
davinci_FreeBuffer( &p_sys->in );
davinci_FreeBuffer( &p_sys->out );
free( p_sys->psz_ti_engine );
free( p_sys );
}
/*****************************************************************************
*
*****************************************************************************/
static inline void davinci_CopyPictureToXDM( encoder_t *p_enc, XDM_BufDesc *p_buf, picture_t *p_pic )
{
VLC_UNUSED( p_enc );
......@@ -238,7 +275,7 @@ static inline void davinci_CopyPictureToXDM( encoder_t *p_enc, XDM_BufDesc *p_bu
}
}
static int davinci_InitBuffers( encoder_t *p_enc )
static int davinci_InitVideoBuffers( encoder_t *p_enc )
{
encoder_sys_t *p_sys = p_enc->p_sys;
int i_ret = VLC_SUCCESS;
......@@ -253,8 +290,8 @@ static int davinci_InitBuffers( encoder_t *p_enc )
/* 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 ?
p_enc->fmt_out.video.i_frame_rate * 1000 /
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 */
......@@ -321,7 +358,7 @@ 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_InitBuffers( p_enc ) != VLC_SUCCESS )
if( davinci_InitVideoBuffers( p_enc ) != VLC_SUCCESS )
return NULL;
}
......@@ -387,3 +424,186 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pic )
return p_block;
}
/*****************************************************************************
* Audio Encoder
*****************************************************************************/
static int GetAudioEncoderSettings( encoder_t *p_enc, const char *psz_codec )
{
encoder_sys_t *p_sys = p_enc->p_sys;
AUDENC_Params params;
params.size = sizeof( params );
switch( var_CreateGetInteger( p_enc, ENC_CFG_PREFIX "quality" ) )
{
case 1: params.encodingPreset = XDM_HIGH_QUALITY; break;
case 2: params.encodingPreset = XDM_HIGH_SPEED; break;
case 3: params.encodingPreset = XDM_USER_DEFINED; break;
default:
params.encodingPreset = XDM_DEFAULT;
break;
}
params.maxBitrate = p_enc->fmt_out.i_bitrate;
params.maxSampleRate = p_enc->fmt_out.audio.i_rate;
params.maxNoOfCh = p_enc->fmt_out.audio.i_channels;
params.dataEndianness = XDM_BYTE;
msg_Info( p_enc, "audio %d channels, %d Hz (max bitrate %d kBps)\n",
(int)params.maxNoOfCh,
(int)params.maxSampleRate,
((int)params.maxBitrate) >> 13 /* / (8*1024)*/);
/* Create encoder handle */
p_sys->a = AUDENC_create( p_sys->e, (String)psz_codec, &params );
if( !p_sys->a )
return VLC_EGENERIC;
return VLC_SUCCESS;
}
static inline int davinci_InitAudioBuffers( encoder_t *p_enc )
{
encoder_sys_t *p_sys = p_enc->p_sys;
int i_ret = VLC_SUCCESS;
AUDENC_DynamicParams dparams;
AUDENC_Status status;
dparams.size = sizeof( dparams );
memset( &status, 0, sizeof( status ) );
status.size = sizeof( status );
/* Configue the encoder */
/* NOTE: assuming channels are interleaved */
dparams.inputFormat = IAUDIO_INTERLEAVED; // IAUDIO_BLOCK;
dparams.bitRate = p_enc->fmt_out.i_bitrate;
dparams.sampleRate = p_enc->fmt_out.audio.i_rate;
switch( p_enc->fmt_out.audio.i_channels )
{
case 1: dparams.numChannels = IAUDIO_MONO; /* Single channel. */
break;
case 2: dparams.numChannels = IAUDIO_STEREO; /* Two channel. */
break;
case 3: dparams.numChannels = IAUDIO_THREE_ZERO; /* Three channel. */
break;
case 5: dparams.numChannels = IAUDIO_FIVE_ZERO; /* Five channel. */
break;
case 6: dparams.numChannels = IAUDIO_FIVE_ONE; /* 5.1 channel. */
break;
case 7: dparams.numChannels = IAUDIO_SEVEN_ONE; /* 7.1 channel. */
break;
default:
msg_Warn( p_enc, "assuming stereo audio channels" );
dparams.numChannels = IAUDIO_STEREO; /**< Two channel. */
break;
}
dparams.numLFEChannels = 0; /* FIXME: What to fill in here?
* Number of LFE (Low Frequency Effects) channels in the stream. */
dparams.inputBitsPerSample = p_enc->fmt_out.audio.i_bitspersample;
//p_enc->fmt_in.i_codec == AOUT_FMT_S16_NE) ? 16: 32;
if( AUDENC_control( p_sys->c, XDM_SETPARAMS, &dparams, &status )
!= AUDENC_EOK )
{
msg_Err( p_enc, "Failed to set encoder parameters: %d @ %d Hz, "
"bitrate %d kBps, %d bits per sample",
p_enc->fmt_out.audio.i_channels,
(int)dparams.sampleRate,
((int)dparams.bitRate) >> 13 /* / (8*1024)*/,
(int)dparams.inputBitsPerSample );
return VLC_EGENERIC;
}
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)dparams.sampleRate,
((int)dparams.bitRate) >> 13 /* / (8*1024)*/,
(int)dparams.inputBitsPerSample );
/* Configure buffers */
if( AUDENC_control( p_sys->c, XDM_GETBUFINFO, &dparams, &status )
!= AUDENC_EOK )
{
msg_Err( p_enc, "Failed to get buffer info" );
return VLC_EGENERIC;
}
/* Allocate input buffer(s) */
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" );
return i_ret;
}
/* Allocate output buffer */
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" );
return i_ret;
}
return i_ret;
}
static block_t *EncodeAudio( encoder_t *p_enc, aout_buffer_t *p_buffer )
{
encoder_sys_t *p_sys = p_enc->p_sys;
AUDENC_InArgs in_args;
AUDENC_OutArgs out_args;
block_t *p_block;
int i_ret;
if( p_sys->in.numBufs == 0 || p_sys->out.numBufs == 0 )
{
if( davinci_InitAudioBuffers( p_enc ) != VLC_SUCCESS )
return NULL;
}
/* Configure input */
memset( &in_args, 0, sizeof( in_args ) );
in_args.size = sizeof( in_args );
/* NOTE: assume interleaved channels */
memcpy( p_sys->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 );
/* Encode the audio */
if( (i_ret = AUDENC_process( p_sys->c, &p_sys->in, &p_sys->out,
&in_args, &out_args )) != AUDENC_EOK )
{
msg_Err( p_enc, "Audio encoding failed (%d): %s", i_ret,
davinci_GetExtendedError( out_args.extendedError ) );
return NULL;
}
/* Print some info */
//msg_Dbg( p_enc, "Bytes generated: %d", (int)out_args.bytesGenerated );
/* Put everything in the block */
if( out_args.bytesGenerated <= 0 )
return NULL;
p_block = block_New( p_enc, out_args.bytesGenerated );
if( !p_block )
return NULL;
memcpy( p_block->p_buffer, p_sys->out.bufs[0], out_args.bytesGenerated );
/* NOTE: assumption */
p_block->i_dts = p_block->i_pts = p_buffer->start_date;
/* 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;
return p_block;
}
......@@ -34,7 +34,8 @@
* Codec fourcc -> davinic_id mapping
*****************************************************************************/
/* Enable codecs by changing #undef in #define here below */
/* Enable codecs by changing #undef in #define here below
* NOTE: Make sure it matches the codec pack you are using. */
#undef DAVINCI_HAS_MPEG1_CODEC
#define DAVINCI_HAS_MPEG2_CODEC
......
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