Commit e73a6ebc authored by Antoine Cellerier's avatar Antoine Cellerier Committed by Jean-Paul Saman

Move davinci stuff to its own directory and split the different modules. Start...

Move davinci stuff to its own directory and split the different modules. Start implementing audio dec module (unfinished but most of the code should be in there).
Signed-off-by: Jean-Paul Saman's avatarJean-Paul Saman <jean-paul.saman@m2x.nl>
parent 96de7fa2
......@@ -5995,6 +5995,7 @@ AC_CONFIG_FILES([
modules/codec/Makefile
modules/codec/avcodec/Makefile
modules/codec/cmml/Makefile
modules/codec/davinci/Makefile
modules/codec/dmo/Makefile
modules/codec/shine/Makefile
modules/codec/subtitles/Makefile
......
SUBDIRS = cmml dmo avcodec shine subtitles spudec wmafixed xvmc
SUBDIRS = cmml dmo avcodec shine subtitles spudec wmafixed xvmc davinci
SOURCES_a52 = a52.c a52.h
SOURCES_dts = dts.c
SOURCES_flac = flac.c
......@@ -38,7 +38,6 @@ SOURCES_kate = kate.c
SOURCES_schroedinger = schroedinger.c
SOURCES_libass = libass.c
SOURCES_aes3 = aes3.c
SOURCES_davinci = davinci.c
libvlc_LTLIBRARIES += \
liba52_plugin.la \
......@@ -57,4 +56,3 @@ libvlc_LTLIBRARIES += \
libsvcdsub_plugin.la \
libinvmem_plugin.la \
$(NULL)
SOURCES_davinci = \
davinci.c \
davinci.h \
auddec.c \
viddec.c \
videnc.c \
$(NULL)
/*****************************************************************************
* auddec.c: audio decoder module using the DaVinci DSP.
*****************************************************************************
* Copyright (C) 2008 the VideoLAN team
* $Id$
*
* Authors: Antoine Cellerier <dionoea at videolan dot org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include "davinci.h"
#include <ti/sdo/ce/audio/auddec.h>
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static aout_buffer_t *DecodeAudioBlock( decoder_t *, block_t ** );
/*****************************************************************************
* Audio decoder
*****************************************************************************/
struct decoder_sys_t
{
Engine_Handle e;
AUDDEC_Handle d;
XDM_BufDesc in;
XDM_BufDesc out;
};
/*****************************************************************************
*
*****************************************************************************/
int OpenAudioDecoder( vlc_object_t *p_this )
{
#if 0
decoder_t *p_dec = (decoder_t *)p_this;
decoder_sys_t *p_sys;
Engine_Error err;
const char *psz_codec;
AUDDEC_Params params;
switch( p_dec->fmt_in.i_codec )
{
CASE_MP3
psz_codec = "mp3dec";
break;
CASE_AAC
psz_codec = "aacdec";
break;
default:
return VLC_EGENERIC;
}
/* Allocate our private structure */
p_dec->p_sys = (decoder_sys_t *)malloc( sizeof( decoder_sys_t ) );
if( !p_dec->p_sys )
return VLC_ENOMEM;
p_sys = p_dec->p_sys;
memset( p_sys, 0, sizeof( decoder_sys_t ) );
/* Initialize the codec engine */
CERuntime_init();
/* Create an engine handle */
p_sys->e = Engine_open( "decode", NULL /*&Engine_ATTRS*/, &err );
if( err != Engine_EOK )
{
msg_Err( p_dec, ppsz_engine_error[err] );
goto error;
}
PrintAvailableAlgorithms( p_this, "decode" );
/* Create audio decoder */
params.size = sizeof( params );
params.maxSampleRate = 48000; /* in Hz */
params.maxBitrate = 256000; /* in kbps */
params.maxNoOfCh = IAUDIO_SEVEN_ONE; /* 7.1 */
params.dataEndianness = XDM_BYTE; /* FIXME? */
p_sys->d = AUDDEC_create( p_sys->e, (String)psz_codec, &params );
if( !p_sys->d )
{
msg_Err( p_dec, "Failed to create audio decoder (%s)", psz_codec );
goto error;
}
/* Set output properties */
/* Set callbacks */
p_dec->pf_decode_audio = DecodeAudioBlock;
#ifdef DEBUG_DAVINCI
msg_Info( p_dec, "Wooooohooo!" );
#endif
return VLC_SUCCESS;
error:
if( p_sys->e ) Engine_close( p_sys->e );
free( p_sys );
#endif
return VLC_EGENERIC;
}
/*****************************************************************************
*
*****************************************************************************/
void CloseAudioDecoder( vlc_object_t *p_this )
{
decoder_t *p_dec = (decoder_t *)p_this;
decoder_sys_t *p_sys = p_dec->p_sys;
/* Close our codec handle */
AUDDEC_delete( p_sys->d );
/* Close our engine handle */
Engine_close( p_sys->e );
/* Exit the codec engine */
CERuntime_exit();
/* Free 'DaVinci compliant' buffers */
FreeBuffer( &p_sys->in );
FreeBuffer( &p_sys->out );
free( p_sys );
}
/*****************************************************************************
*
*****************************************************************************/
static aout_buffer_t *DecodeAudioBlock( decoder_t *p_dec, block_t **pp_block )
{
#if 0
decoder_sys_t *p_sys = p_dec->p_sys;
block_t *p_block;
aout_buffer_t *p_out = NULL;
AUDDEC_InArgs in_args;
AUDDEC_OutArgs out_args;
AUDDEC_DynamicParams dparams;
AUDDEC_Status status;
int i;
if( !pp_block || !*pp_block ) return NULL;
p_block = *pp_block;
#ifdef DEBUG_DAVINCI
msg_Err( p_dec, "DecodeAudioBlock starts now!" );
#endif
memset( &in_args, 0, sizeof( in_args ) );
memset( &out_args, 0, sizeof( out_args ) );
/* Configure audio decoder */
dparams.size = sizeof( dparams );
memset( &status, 0, sizeof( status ) );
status.size = sizeof( status );
if( p_sys->in.numBufs == 0 || p_sys->out.numBufs == 0 )
{
if( AUDDEC_control( p_sys->d, XDM_GETBUFINFO, &dparams, &status )
!= VIDDEC_EOK )
{
msg_Err( p_dec, "Failed to get buffer info" );
goto error;
}
/* Allocate input buffer */
if( AllocateBuffer( p_dec, status.bufInfo.minNumInBufs,
status.bufInfo.minInBufSize, &p_sys->in )
!= VLC_SUCCESS )
{
msg_Err( p_dec, "Failed to allocate input buffer" );
goto error;
}
/* Allocate output buffer */
if( AllocateBuffer( p_dec, status.bufInfo.minNumOutBufs,
status.bufInfo.minOutBufSize, &p_sys->out )
!= VLC_SUCCESS )
{
msg_Err( p_dec, "Failed to allocate output buffer" );
goto error;
}
}
/* Setup input arguments */
in_args.size = sizeof( in_args );
in_args.numBytes = __MIN( p_block->i_buffer, p_sys->in.bufSizes[0] );
/* Setup input buffer */
#ifdef DEBUG_DAVINCI
if( p_block->i_buffer > p_sys->in.bufSizes[0] )
msg_Dbg( p_dec, "Woah! Not enough room to store the whole block" );
#endif
memcpy( p_sys->in.bufs[0], p_block->p_buffer, in_args.numBytes );
/* Setup output arguments */
out_args.size = sizeof( out_args );
/* Decode the audio */
i = AUDDEC_process( p_sys->d, &p_sys->in, &p_sys->out, &in_args, &out_args );
if( i != VIDDEC_EOK )
{
msg_Err( p_dec, "Audio decoding failed (Error code: %d, "
"Extended error: %x)", i, (int)out_args.extendedError );
PrintExtendedError( p_dec, out_args.extendedError );
goto error;
}
if( VIDDEC_control( p_sys->d, XDM_GETSTATUS, &dparams, &status ) != AUDDEC_EOK )
{
msg_Err( p_dec, "Failed to get decoder status" );
goto error;
}
p_block->p_buffer += out_args.bytesConsumed;
p_block->i_buffer -= out_args.bytesConsumed;
p_dec->fmt_out.audio.i_rate = status.sampleRate;
switch( status.numChannels )
{
case IAUDIO_MONO:
i = AOUT_VAR_MONO;
break;
case IAUDIO_STEREO:
i = AOUT_VAR_STEREO;
break;
case IAUDIO_THREE_ZERO:
i = 3; /* FIXME? */
break;
case IAUDIO_FIVE_ZERO:
i = AOUT_VAR_3F2R;
break;
case IAUDIO_FIVE_ONE:
i = AOUT_VAR_5_1;
break;
case IAUDIO_SEVEN_ONE:
i = AOUT_VAR_7_1;
break;
default:
msg_Warn( p_dec, "Unknown numChannels (%d)", status.numChannels );
i = status.numChannels;
break;
}
p_dec->fmt_out.audio.i_physical_channels =
p_dec->fmt_out.audio.i_original_channels =
p_dec->fmt_out.audio.i_channels = i;
p_dec->fmt_out.audio.i_bitspersample = status.outputBitsPerSample;
p_out = p_dec->pf_aout_buffer_new( p_dec, status.frameLen /
p_dec->fmt_out.audio.i_channels );
p_out->start_date =
p_out->end_date =
p_out->p_buffer =
return p_out;
error:
if( p_out && p_out->pf_release )
p_out->pf_release( p_out );
block_Release( p_block );
#endif
return NULL;
}
/*****************************************************************************
* davinci.c: decoder and encoder modules using the DaVinci DSP.
*****************************************************************************
* Copyright (C) 2008 the VideoLAN team
* $Id$
*
* Authors: Antoine Cellerier <dionoea at videolan dot org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include "davinci.h"
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin();
set_category( CAT_INPUT );
set_subcategory( SUBCAT_INPUT_VCODEC );
set_description( _("DaVinci DSP video decoder") );
set_capability( "decoder", 1337 );
set_callbacks( OpenVideoDecoder, CloseVideoDecoder );
add_submodule();
set_description( _("DaVinci DSP audio decoder") );
set_capability( "decoder", 1337 );
set_callbacks( OpenAudioDecoder, CloseAudioDecoder );
add_submodule();
set_description( _("DaVinci DSP video encoder" ) );
set_capability( "encoder", 1337 );
set_callbacks( OpenVideoEncoder, CloseVideoEncoder );
vlc_module_end();
/*****************************************************************************
* Misc utils
*****************************************************************************/
#include <ti/sdo/ce/osal/Memory.h>
int __AllocateBuffer( vlc_object_t *p_this, XDAS_Int32 i_num,
XDAS_Int32 *pi_sizes, XDM_BufDesc *buf )
{
int i;
#ifdef DEBUG_DAVINCI
msg_Info( p_this, "Allocating buffers:" );
#endif
buf->numBufs = i_num;
buf->bufs = (XDAS_Int8 **)malloc( buf->numBufs * sizeof( XDAS_Int8 * ) );
if( !buf->bufs )
{
buf->numBufs = 0;
return VLC_ENOMEM;
}
buf->bufSizes = (XDAS_Int32 *)malloc( buf->numBufs * sizeof( XDAS_Int32 ) );
if( !buf->bufSizes )
{
free( buf->bufs );
buf->numBufs = 0;
return VLC_ENOMEM;
}
for( i = 0; i < i_num; i++ )
{
#ifdef DEBUG_DAVINCI
msg_Info( p_this, " %d: size %d Bytes", i, (int)pi_sizes[i] );
#endif
buf->bufSizes[i] = pi_sizes[i];
buf->bufs[i] = Memory_contigAlloc( pi_sizes[i], Memory_DEFAULTALIGNMENT );
if( !buf->bufs[i] )
{
#ifdef DEBUG_DAVINCI
msg_Err( p_this, "Failed to allocate buffer" );
#endif
for( i--; i >= 0; i-- )
{
Memory_contigFree( buf->bufs[i], buf->bufSizes[i] );
free( buf->bufs );
free( buf->bufSizes );
buf->numBufs = 0;
return VLC_ENOMEM;
}
}
}
return VLC_SUCCESS;
}
void FreeBuffer( XDM_BufDesc *buf )
{
if( buf->numBufs != 0 )
{
int i;
for( i = 0; i < buf->numBufs; i++ )
Memory_contigFree( buf->bufs[i], buf->bufSizes[i] );
free( buf->bufs );
free( buf->bufSizes );
buf->numBufs = 0;
}
}
void __PrintExtendedError( vlc_object_t *p_this, XDAS_Int32 error )
{
if( XDM_ISAPPLIEDCONCEALMENT( error ) )
msg_Err( p_this, " Applied bit concealment" );
if( XDM_ISINSUFFICIENTDATA( error ) )
msg_Err( p_this, " Insufficient data" );
if( XDM_ISCORRUPTEDDATA( error ) )
msg_Err( p_this, " Corrupted data" );
if( XDM_ISCORRUPTEDHEADER( error ) )
msg_Err( p_this, " Corrupted header" );
if( XDM_ISUNSUPPORTEDINPUT( error ) )
msg_Err( p_this, " Unsupported input" );
if( XDM_ISUNSUPPORTEDPARAM( error ) )
msg_Err( p_this, " Unsupported param" );
if( XDM_ISFATALERROR( error ) )
msg_Err( p_this, " Fatal error" );
}
void __PrintAvailableAlgorithms( vlc_object_t *p_this, const char *psz_engine )
{
int i = 0;
Engine_AlgInfo info;
info.algInfoSize = sizeof( info );
msg_Dbg( p_this, "Available algorithms in engine `%s':", psz_engine );
while( Engine_getAlgInfo( (String)psz_engine, &info, i ) == Engine_EOK )
{
const char **psz_type = info.typeTab;
i++;
msg_Dbg( p_this, " %d: %s (%s)", i, info.name, info.isLocal?"local":"remote" );
if( *psz_type )
{
msg_Dbg( p_this, " Inheritance hierarchy:" );
for( ; !*psz_type; psz_type++ )
msg_Dbg( p_this, " %s", *psz_type );
}
}
}
/*****************************************************************************
* davinci.h: decoder and encoder modules using the DaVinci DSP.
*****************************************************************************
* Copyright (C) 2008 the VideoLAN team
* $Id$
*
* Authors: Antoine Cellerier <dionoea at videolan dot org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef VLC_DAVINCI_H
#define VLC_DAVINCI_H
#include <vlc/vlc.h>
#include <vlc/decoder.h>
#include <gnu/targets/std.h>
#include <xdc/std.h>
#include <ti/xdais/xdas.h>
#include <ti/xdais/dm/xdm.h>
#include <ti/sdo/ce/CERuntime.h>
#include <ti/sdo/ce/Engine.h>
#define DEBUG_DAVINCI
int OpenVideoDecoder( vlc_object_t * );
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 __AllocateBuffer( vlc_object_t *, XDAS_Int32, XDAS_Int32 *, XDM_BufDesc * );
#define AllocateBuffer( a, b, c, d ) __AllocateBuffer( VLC_OBJECT( a ), b, c, d )
void FreeBuffer( XDM_BufDesc * );
void __PrintExtendedError( vlc_object_t *, XDAS_Int32 );
#define PrintExtendedError( a, b ) __PrintExtendedError( VLC_OBJECT( a ), b )
void __PrintAvailableAlgorithms( vlc_object_t *, const char * );
#define PrintAvailableAlgorithms( a, b ) __PrintAvailableAlgorithms( VLC_OBJECT( a ), b )
/*****************************************************************************
* Common stuff
*****************************************************************************/
static const char *ppsz_engine_error[] = {
[Engine_EOK] = "Ok",
[Engine_EEXIST] = "Engine name doesn't exist",
[Engine_ENOMEM] = "Can't allocate engine memory",
[Engine_EDSPLOAD] = "Can't load the DSP",
[Engine_ENOCOMM] = "Can't create communication connection to DSP",
[Engine_ENOSERVER] = "Can't locate the server on the DSP",
[Engine_ECOMALLOC] = "Can't allocate communication buffer",
[Engine_ERUNTIME] = "Engine runtime failure",
[Engine_ECODECCREATE] = "Engine codec creation failed",
[Engine_ECODECSTART] = "Engine codec start failed",
[Engine_EINVAL] = "Bad parameter",
[Engine_EBADSERVER] = "Incompatible server specified",
[Engine_ENOTAVAIL] = "Service not available",
//[Engine_EWRONGSTATE] = "Call can't be made at this time",
//[Engine_EINUSE] = "Call can't be made at this time because a required resource is in use",
//[Engine_ENOTFOUND] = "Entity was not found",
};
/* FOURCC codes copied from libavcodec module */
#define CASE_MPEG1 \
case VLC_FOURCC('m','p','e','g'): \
case VLC_FOURCC('m','p','g','1'): \
case VLC_FOURCC('P','I','M','1'):
#define CASE_MPEG2 \
case VLC_FOURCC('m','p','g','v'): \
case VLC_FOURCC('m','p','2','v'): \
case VLC_FOURCC('M','P','E','G'): \
case VLC_FOURCC('m','p','g','2'): \
case VLC_FOURCC('h','d','v','1'): \
case VLC_FOURCC('h','d','v','2'): \
case VLC_FOURCC('h','d','v','3'): \
case VLC_FOURCC('h','d','v','5'): \
case VLC_FOURCC('m','x','5','n'): \
case VLC_FOURCC('m','x','5','p'): \
case VLC_FOURCC('m','x','4','n'): \
case VLC_FOURCC('m','x','4','p'): \
case VLC_FOURCC('m','x','3','n'): \
case VLC_FOURCC('m','x','3','p'): \
case VLC_FOURCC('x','d','v','2'): \
case VLC_FOURCC('A','V','m','p'): \
case VLC_FOURCC('V','C','R','2'): \
case VLC_FOURCC('M','M','E','S'): \
case VLC_FOURCC('m','m','e','s'):
#define CASE_MPEG4 \
case VLC_FOURCC('D','I','V','X'): \
case VLC_FOURCC('d','i','v','x'): \
case VLC_FOURCC('M','P','4','S'): \
case VLC_FOURCC('M','P','4','s'): \
case VLC_FOURCC('M','4','S','2'): \
case VLC_FOURCC('m','4','s','2'): \
case VLC_FOURCC('x','v','i','d'): \
case VLC_FOURCC('X','V','I','D'): \
case VLC_FOURCC('X','v','i','D'): \
case VLC_FOURCC('X','V','I','X'): \
case VLC_FOURCC('x','v','i','x'): \
case VLC_FOURCC('D','X','5','0'): \
case VLC_FOURCC('d','x','5','0'): \
case VLC_FOURCC('B','L','Z','0'): \
case VLC_FOURCC('B','X','G','M'): \
case VLC_FOURCC('m','p','4','v'): \
case VLC_FOURCC('M','P','4','V'): \
case VLC_FOURCC( 4 , 0 , 0 , 0 ): \
case VLC_FOURCC('m','4','c','c'): \
case VLC_FOURCC('M','4','C','C'): \
case VLC_FOURCC('F','M','P','4'): \
case VLC_FOURCC('f','m','p','4'): \
case VLC_FOURCC('3','I','V','2'): \
case VLC_FOURCC('3','i','v','2'): \
case VLC_FOURCC('U','M','P','4'): \
case VLC_FOURCC('W','V','1','F'): \
case VLC_FOURCC('S','E','D','G'): \
case VLC_FOURCC('R','M','P','4'): \
case VLC_FOURCC('H','D','X','4'): \
case VLC_FOURCC('h','d','x','4'): \
case VLC_FOURCC('S','M','P','4'): \
case VLC_FOURCC('f','v','f','w'): \
case VLC_FOURCC('F','V','F','W'):
#define CASE_H264 \
case VLC_FOURCC('a','v','c','1'): \
case VLC_FOURCC('A','V','C','1'): \
case VLC_FOURCC('h','2','6','4'): \
case VLC_FOURCC('H','2','6','4'): \
case VLC_FOURCC('x','2','6','4'): \
case VLC_FOURCC('X','2','6','4'): \
case VLC_FOURCC('V','S','S','H'): \
case VLC_FOURCC('V','S','S','W'): \
case VLC_FOURCC('v','s','s','h'): \
case VLC_FOURCC('D','A','V','C'): \
case VLC_FOURCC('d','a','v','c'):
#define CASE_VC1 \
case VLC_FOURCC('W','V','C','1'): \
case VLC_FOURCC('w','v','c','1'):
#define CASE_MP3 \
case VLC_FOURCC('m','p','3',' '): \
case VLC_FOURCC('.','m','p','3'): \
case VLC_FOURCC('M','P','3',' '): \
case VLC_FOURCC('L','A','M','E'):
#define CASE_AAC \
case VLC_FOURCC('m','p','4','a'):
#endif
/*****************************************************************************
* viddec.c: video decoder module using the DaVinci DSP.
*****************************************************************************
* Copyright (C) 2008 the VideoLAN team
* $Id$
*
* Authors: Antoine Cellerier <dionoea at videolan dot org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include "davinci.h"
#include <ti/sdo/ce/video/viddec.h>
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static picture_t *DecodeVideoBlock( decoder_t *, block_t ** );
/*****************************************************************************
* Video decoder
*****************************************************************************/
struct decoder_sys_t
{
Engine_Handle e;
VIDDEC_Handle d;
XDM_BufDesc in;
XDM_BufDesc out;
};
/*****************************************************************************
* OpenDecoder: probe the decoder and return score
*****************************************************************************/
int OpenVideoDecoder( vlc_object_t *p_this )
{
decoder_t *p_dec = (decoder_t*)p_this;
decoder_sys_t *p_sys;
Engine_Error err;
const char *psz_codec;
VIDDEC_Params params;
switch( p_dec->fmt_in.i_codec )
{
#if 0
CASE_MPEG1
psz_codec = "mpegdec"; /* FIXME */
break;
#endif
CASE_MPEG2
psz_codec = "mpeg2dec";
break;
CASE_MPEG4
psz_codec = "mpeg4dec";
break;
CASE_H264
psz_codec = "h264dec";
break;
#if 0
CASE_VC1
psz_codec = "vc1dec"; /* FIXME */
break;
#endif
default:
return VLC_EGENERIC;
}
/* Allocate our private structure */
p_dec->p_sys = (decoder_sys_t *)malloc( sizeof( decoder_sys_t ) );
if( !p_dec->p_sys )
return VLC_ENOMEM;
p_sys = p_dec->p_sys;
memset( p_sys, 0, sizeof( decoder_sys_t ) );
/* Initialize the codec engine */
CERuntime_init();
/* Create an engine handle */
p_sys->e = Engine_open( "decode", NULL /*&Engine_ATTRS*/, &err );
if( err != Engine_EOK )
{
msg_Err( p_dec, ppsz_engine_error[err] );
goto error;
}
PrintAvailableAlgorithms( p_this, "decode" );
/* Create video decoder */
params.size = sizeof( VIDDEC_Params );
params.maxHeight = p_dec->fmt_in.video.i_height?:576;
params.maxWidth = p_dec->fmt_in.video.i_width?:720;
params.maxFrameRate = 0; /* in frames per 1000 seconds */
params.maxBitRate = 0; /* in bits per second */
params.dataEndianness = XDM_BYTE;//LE_32;
params.forceChromaFormat = XDM_YUV_420P;
//params.forceChromaFormat = XDM_YUV_422ILE;
/* Or do we want to output directly to XDM_YUV_422ILE as that's what the
* frame buffer likes? */
p_sys->d = VIDDEC_create( p_sys->e, (String)psz_codec, &params );
if( !p_sys->d )
{
msg_Err( p_dec, "Failed to create video decoder (%s)", psz_codec );
goto error;
}
/* Set output properties */
#ifdef DEBUG_DAVINCI
msg_Info( p_dec, "fmt_in.video.i_width: %d", p_dec->fmt_in.video.i_width );
msg_Info( p_dec, "fmt_in.video.i_height: %d", p_dec->fmt_in.video.i_height );
msg_Info( p_dec, "fmt_out.video.i_width: %d", p_dec->fmt_out.video.i_width );
msg_Info( p_dec, "fmt_out.video.i_height: %d", p_dec->fmt_out.video.i_height );
#endif
p_dec->fmt_out.i_cat = VIDEO_ES;
p_dec->fmt_out.i_codec = VLC_FOURCC('I','4','2','0');
//p_dec->fmt_out.i_codec = VLC_FOURCC('U','Y','V','Y');
p_dec->fmt_out.video.i_width = p_dec->fmt_in.video.i_width;
p_dec->fmt_out.video.i_height = p_dec->fmt_in.video.i_height;
p_dec->fmt_out.video.i_aspect = p_dec->fmt_in.video.i_aspect;
/* Set callbacks */
p_dec->pf_decode_video = DecodeVideoBlock;
#ifdef DEBUG_DAVINCI
msg_Info( p_dec, "Woohoo!" );
#endif
return VLC_SUCCESS;
error:
if( p_sys->e ) Engine_close( p_sys->e );
free( p_sys );
return VLC_EGENERIC;
}
/*****************************************************************************
* CloseDecoder: png decoder destruction
*****************************************************************************/
void CloseVideoDecoder( vlc_object_t *p_this )
{
decoder_t *p_dec = (decoder_t *)p_this;
decoder_sys_t *p_sys = p_dec->p_sys;
/* Close our codec handle */
VIDDEC_delete( p_sys->d );
/* Close our engine handle */
Engine_close( p_sys->e );
/* Exit the codec engine */
CERuntime_exit();
/* Free 'DaVinci compliant' buffers */
FreeBuffer( &p_sys->in );
FreeBuffer( &p_sys->out );
free( p_sys );
}
/****************************************************************************
* DecodeBlock: the whole thing
****************************************************************************/
static picture_t *DecodeVideoBlock( decoder_t *p_dec, block_t **pp_block )
{
decoder_sys_t *p_sys = p_dec->p_sys;
block_t *p_block;
picture_t *p_pic = NULL;
VIDDEC_InArgs in_args;
VIDDEC_OutArgs out_args;
VIDDEC_DynamicParams dparams;
VIDDEC_Status status;
int i;
if( !pp_block || !*pp_block ) return NULL;
p_block = *pp_block;
#ifdef DEBUG_DAVINCI
msg_Err( p_dec, "DecodeVideoBlock starts now!" );
#endif
memset( &in_args, 0, sizeof( in_args ) );
memset( &out_args, 0, sizeof( out_args ) );
/* Configure video decoder */
dparams.size = sizeof( VIDDEC_DynamicParams );
memset( &status, 0, sizeof( VIDDEC_Status ) );
status.size = sizeof( VIDDEC_Status );
if( p_sys->in.numBufs == 0 || p_sys->out.numBufs == 0 )
{
if( VIDDEC_control( p_sys->d, XDM_GETBUFINFO, &dparams, &status )
!= VIDDEC_EOK )
{
msg_Err( p_dec, "Failed to get buffer info" );
goto error;
}
/* Allocate input buffer */
if( AllocateBuffer( p_dec, status.bufInfo.minNumInBufs,
status.bufInfo.minInBufSize, &p_sys->in )
!= VLC_SUCCESS )
{
msg_Err( p_dec, "Failed to allocate input buffers" );
goto error;
}
/* Allocate output buffer(s) */
if( AllocateBuffer( p_dec, status.bufInfo.minNumOutBufs,
status.bufInfo.minOutBufSize, &p_sys->out )
!= VLC_SUCCESS )
{
FreeBuffer( &p_sys->in );
msg_Err( p_dec, "Failed to allocate output buffers" );
goto error;
}
}
if( VIDDEC_control( p_sys->d, XDM_GETSTATUS, &dparams, &status ) != VIDDEC_EOK )
{
msg_Err( p_dec, "Failed to get decoder status" );
goto error;
}
/* Setup input arguments */
in_args.size = sizeof( in_args );
in_args.numBytes = __MIN( p_block->i_buffer, p_sys->in.bufSizes[0] );
in_args.inputID = 0; /* FIXME? */
/* Setup input buffer */
#ifdef DEBUG_DAVINCI
if( p_block->i_buffer > p_sys->in.bufSizes[0] )
msg_Dbg( p_dec, "Woah! Not enough room to store the whole block" );
#endif
memcpy( p_sys->in.bufs[0], p_block->p_buffer, in_args.numBytes );
msg_Warn( p_dec, "Sending %d bytes", in_args.numBytes );
#if 0
/* This obviously doesn't work (at least for mpeg2 video */
if( status.outputHeight <= 0 || status.outputWidth <= 0 )
{
msg_Dbg( p_dec, "Output frame size unknown. Parsing header." );
dparams.decodeHeader = XDM_PARSE_HEADER; /* Only parse the header */
dparams.displayWidth = 0; /* Use the encoded image's width */
dparams.frameSkipMode = IVIDEO_NO_SKIP; /* Don't skip any frames */
if( VIDDEC_control( p_sys->d, XDM_SETPARAMS, &dparams, &status ) != VIDDEC_EOK )
{
msg_Err( p_dec, "Failed to set dynamic params (1)" );
goto error;
}
out.numBufs = 0;
if( VIDDEC_process( p_sys->d, &in, &out, &in_args, &out_args )
== VIDDEC_EFAIL )
{
msg_Err( p_dec, "Video header decoding failed" );
goto error;
}
dparams.decodeHeader = XDM_DECODE_AU; /* Decode everything */
dparams.displayWidth = 0; /* Use the encoded image's width */
dparams.frameSkipMode = IVIDEO_NO_SKIP; /* Don't skip any frames */
if( VIDDEC_control( p_sys->d, XDM_SETPARAMS, &dparams, &status ) != VIDDEC_EOK )
{
msg_Err( p_dec, "Failed to set dynamic params (2)" );
goto error;
}
if( VIDDEC_control( p_sys->d, XDM_GETSTATUS, &dparams, &status ) != VIDDEC_EOK )
{
msg_Err( p_dec, "Failed to get decoder status" );
goto error;
}
if( status.outputHeight <= 0 || status.outputWidth <= 0 )
{
msg_Err( p_dec, "Ok, we have a problem ..." );
goto error;
}
#ifdef DEBUG_DAVINCI
msg_Info( p_dec, "Frame preparsed" );
#endif
}
#endif
msg_Info( p_dec, "Frame info: " );
msg_Info( p_dec, " Width: %d", (int)status.outputWidth );
msg_Info( p_dec, " Height: %d", (int)status.outputHeight );
msg_Info( p_dec, " Content type: %s", status.contentType == IVIDEO_PROGRESSIVE ? "progressive" : status.contentType == IVIDEO_INTERLACED ? "interlaced" : "not available" );
/* Setup output arguemnts */
out_args.size = sizeof( out_args );
/* That was easy :p */
/* Decode the video */
printf("%s %s %d\n", __FILE__, __func__, __LINE__);
if( ( i = VIDDEC_process( p_sys->d, &p_sys->in, &p_sys->out, &in_args, &out_args ) )
!= VIDDEC_EOK )
{
msg_Err( p_dec, "Video decoding failed (Error code: %d, "
"Extended error: %x)", i, (int)out_args.extendedError );
PrintExtendedError( p_dec, out_args.extendedError );
goto error;
}
printf("%s %s %d\n", __FILE__, __func__, __LINE__);
#ifdef DEBUG_DAVINCI
msg_Info( p_dec, "%s %d", __func__, __LINE__ );
#endif
if( VIDDEC_control( p_sys->d, XDM_GETSTATUS, &dparams, &status ) != VIDDEC_EOK )
{
msg_Err( p_dec, "Failed to get decoder status" );
goto error;
}
#ifdef DEBUG_DAVINCI
msg_Info( p_dec, "After decoder info: " );
msg_Info( p_dec, " Width: %d", (int)status.outputWidth );
msg_Info( p_dec, " Height: %d", (int)status.outputHeight );
msg_Info( p_dec, " Content type: %s", status.contentType == IVIDEO_PROGRESSIVE ? "progressive" : status.contentType == IVIDEO_INTERLACED ? "interlaced" : "not available" );
msg_Info( p_dec, " Bytes consumed: %d", (int)out_args.bytesConsumed );
#endif
p_block->p_buffer += out_args.bytesConsumed;
p_block->i_buffer -= out_args.bytesConsumed;
p_dec->fmt_out.video.i_width = status.outputWidth;
p_dec->fmt_out.video.i_height = status.outputHeight;
p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR * status.outputWidth / status.outputHeight; /* FIXME */
p_dec->fmt_out.i_codec = VLC_FOURCC('I','4','2','0');
//p_dec->fmt_out.i_codec = VLC_FOURCC('U','Y','V','Y');
/* Get a new picture */
p_pic = p_dec->pf_vout_buffer_new( p_dec );
if( !p_pic )
{
msg_Err( p_dec, "Could not get picture" );
goto error;
}
p_pic->b_progressive = status.contentType == IVIDEO_INTERLACED ? VLC_FALSE
: VLC_TRUE;
/* Copy stuff to picture here */
#ifdef DEBUG_DAVINCI
switch( out_args.decodedFrameType )
{
case IVIDEO_NA_FRAME:
msg_Dbg( p_dec, "Unknown frame type" );
break;
case IVIDEO_I_FRAME:
msg_Dbg( p_dec, "I frame" );
break;
case IVIDEO_P_FRAME:
msg_Dbg( p_dec, "P frame" );
break;
case IVIDEO_B_FRAME:
msg_Dbg( p_dec, "B frame" );
break;
case IVIDEO_II_FRAME:
msg_Dbg( p_dec, "Interlaced I frame" );
break;
case IVIDEO_PP_FRAME:
msg_Dbg( p_dec, "Interlaced P frame" );
break;
case IVIDEO_BB_FRAME:
msg_Dbg( p_dec, "Interlaced B frame" );
break;
default:
msg_Dbg( p_dec, "Other frame type: %d", (int)out_args.decodedFrameType );
break;
}
#endif
if( p_pic->i_planes != p_sys->out.numBufs )
{
msg_Err( p_dec, "Ahem ... looks like I assumed something wrong. Please investigate." );
goto error;
}
for( i = 0; i < p_pic->i_planes; i++ )
{
plane_t *p = p_pic->p+i;
memcpy( p->p_pixels, p_sys->out.bufs[i], p->i_pitch * p->i_visible_lines );
}
p_pic->date = p_block->i_pts > 0 ? p_block->i_pts : p_block->i_dts;
#ifdef DEBUG_DAVINCI
msg_Info( p_dec, "Yay! Frame decoded correctly" );
#endif
return p_pic;
error:
if( p_pic && p_pic->pf_release )
p_pic->pf_release( p_pic );
block_Release( p_block ); /* Do we really need this everytime? (like if buffer memory allocation fails we could keep the block) */
return NULL;
}
/*****************************************************************************
* videnc.c: video encoder module using the DaVinci DSP.
*****************************************************************************
* Copyright (C) 2008 the VideoLAN team
* $Id$
*
* Authors: Antoine Cellerier <dionoea at videolan dot org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include "davinci.h"
#include <ti/sdo/ce/video/videnc.h>
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static block_t *EncodeVideo( encoder_t *, picture_t * );
/*****************************************************************************
* Video encoder
*****************************************************************************/
struct encoder_sys_t
{
Engine_Handle e;
VIDENC_Handle c;
XDM_BufDesc in;
XDM_BufDesc out;
};
/*****************************************************************************
*
*****************************************************************************/
int OpenVideoEncoder( vlc_object_t *p_this )
{
encoder_t *p_enc = (encoder_t *)p_this;
encoder_sys_t *p_sys;
const char *psz_codec;
Engine_Error err;
VIDENC_Params params;
switch( p_enc->fmt_out.i_codec )
{
#if 0
CASE_MPEG1
psz_codec = "mpegenc"; /* FIXME */
break;
CASE_MPEG2
psz_codec = "mpeg2enc"; /* FIXME */
break;
#endif
CASE_MPEG4
psz_codec = "mpeg4enc";
break;
CASE_H264
psz_codec = "h264enc";
break;
#if 0
CASE_VC1
psz_codec = "vc1enc"; /* FIXME */
break;
#endif
default:
return VLC_EGENERIC;
}
/* Allocate our private structure */
p_enc->p_sys = (encoder_sys_t *)malloc( sizeof( encoder_sys_t ) );
if( !p_enc->p_sys )
return VLC_ENOMEM;
p_sys = p_enc->p_sys;
memset( p_sys, 0, sizeof( encoder_sys_t ) );
/* Initialize the codec engine */
CERuntime_init();
/* Create an engine handle */
p_sys->e = Engine_open( "encode", NULL /*&Engine_ATTRS*/, &err );
if( err != Engine_EOK )
{
msg_Err( p_enc, ppsz_engine_error[err] );
goto error;
}
PrintAvailableAlgorithms( p_this, "encode" );
/* Configure encoder */
params.size = sizeof( params );
params.encodingPreset = 0; /* Use default */
params.rateControlPreset = 0; /* Use default */
params.maxHeight = p_enc->fmt_in.video.i_height;
params.maxWidth = p_enc->fmt_in.video.i_width;
params.maxFrameRate = p_enc->fmt_out.video.i_frame_rate_base ?
p_enc->fmt_out.video.i_frame_rate * 1000 /
p_enc->fmt_out.video.i_frame_rate_base :
0; /* Frames per 1000 seconds */
params.maxBitRate = p_enc->fmt_out.i_bitrate
+ p_enc->i_tolerance; /* Bits per second. FIXME? */
params.dataEndianness = XDM_BYTE;
params.maxInterFrameInterval = p_enc->i_iframes; /* FIXME? */
switch( p_enc->fmt_in.video.i_chroma )
{
case VLC_FOURCC('I','4','2','0'):
params.inputChromaFormat = XDM_YUV_420P;
break;
case VLC_FOURCC('I','4','1','1'):
params.inputChromaFormat = XDM_YUV_411P;
break;
case VLC_FOURCC('I','4','2','2'):
params.inputChromaFormat = XDM_YUV_422P;
break;
case VLC_FOURCC('I','4','4','4'):
params.inputChromaFormat = XDM_YUV_444P;
break;
case VLC_FOURCC('Y','U','Y','V'):
params.inputChromaFormat = XDM_YUV_422IBE; /* FIXME ? */
break;
case VLC_FOURCC('U','Y','V','Y'):
params.inputChromaFormat = XDM_YUV_422ILE; /* FIXME ? */
break;
case VLC_FOURCC('G','R','E','Y'):
params.inputChromaFormat = XDM_GRAY;
break;
#if 0
/* FIXME: not sure about this one */
case VLC_FOURCC('R','V','2','4'):
case VLC_FOURCC('R','V','3','2'):
params.inputChromaFormat = XDM_RGB;
break;
#endif
default:
msg_Err( p_enc, "Unsupported input chroma (%4.4s).",
(const char *)&p_enc->fmt_in.video.i_chroma );
goto error;
}
params.inputContentType = IVIDEO_PROGRESSIVE; /* FIXME: we don't know if it's progressive or interlaced until we get the first picture (p_pic->b_progressive) */
/* 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)", psz_codec );
goto error;
}
/* Initialize random stuff */
p_enc->pf_encode_video = EncodeVideo;
/* Holy bananas! We made it! */
msg_Info( p_enc, "Woohoooooooo!" );
return VLC_SUCCESS;
error:
if( p_sys->e ) Engine_close( p_sys->e );
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 */
FreeBuffer( &p_sys->in );
FreeBuffer( &p_sys->out );
free( p_sys );
}
/*****************************************************************************
*
*****************************************************************************/
static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pic )
{
encoder_sys_t *p_sys = p_enc->p_sys;
block_t *p_block;
int i;
VIDENC_InArgs in_args;
VIDENC_OutArgs out_args;
if( p_sys->in.numBufs == 0 || p_sys->out.numBufs == 0 )
{
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 ?
p_enc->fmt_out.video.i_frame_rate * 1000 /
p_enc->fmt_out.video.i_frame_rate_base :
30; /* Frames per 1000 seconds */
dparams.targetFrameRate = dparams.refFrameRate; /* FIXME? */
dparams.targetBitRate = p_enc->fmt_out.i_bitrate;
dparams.intraFrameInterval = p_enc->i_iframes;
dparams.generateHeader = XDM_ENCODE_AU; /* FIXME? */
dparams.captureWidth = p_pic->p->i_pitch / p_pic->p->i_pixel_pitch; /* FIXME? */
dparams.forceIFrame = 0;
if( VIDENC_control( p_sys->c, XDM_SETPARAMS, &dparams, &status )
!= VIDENC_EOK )
{
msg_Err( p_enc, "Failed to set encoder parameters" );
goto error;
}
/* Configure buffers */
if( VIDENC_control( p_sys->c, XDM_GETBUFINFO, &dparams, &status )
!= VIDENC_EOK )
{
msg_Err( p_enc, "Failed to get buffer info" );
goto error;
}
/* Allocate input buffer(s) */
if( AllocateBuffer( p_enc, status.bufInfo.minNumInBufs,
status.bufInfo.minInBufSize, &p_sys->in )
!= VLC_SUCCESS )
{
msg_Err( p_enc, "Failed to allocate input buffers" );
goto error;
}
/* Allocate output buffer */
if( AllocateBuffer( p_enc, status.bufInfo.minNumOutBufs,
status.bufInfo.minOutBufSize, &p_sys->out )
!= VLC_SUCCESS )
{
msg_Err( p_enc, "Failed to allocate input buffers" );
goto error;
}
}
/* Copy input picture */
if( p_pic->i_planes != p_sys->in.numBufs )
{
msg_Err( p_enc, "Ahem ... looks like I assumed something wrong. Please investigate." );
goto error;
}
for( i = 0; i < p_pic->i_planes; i++ )
{
plane_t *p = p_pic->p+i;
memcpy( p_sys->in.bufs[i], p->p_pixels, p->i_pitch * p->i_visible_lines );
}
/* Configure input */
in_args.size = sizeof( in_args );
/* Heh, that was useless ... */
/* Configure output */
memset( &out_args, 0, sizeof( out_args ) );
out_args.size = sizeof( out_args );
/* Encode the video */
i = VIDENC_process( p_sys->c, &p_sys->in, &p_sys->out,
&in_args, &out_args );
if( i != VIDENC_EOK )
{
msg_Err( p_enc, "Video encoding failed (Error code: %d, "
"Extended erorr: %x)", i, (int)out_args.extendedError );
PrintExtendedError( p_enc, out_args.extendedError );
goto error;
}
/* Print some info */
msg_Info( p_enc, "Encoder info:" );
msg_Info( p_enc, " Bytes generated: %d", (int)out_args.bytesGenerated );
/* Put everything in the block */
if( out_args.bytesGenerated <= 0 )
goto error;
p_block = block_New( p_enc, out_args.bytesGenerated );
if( !p_block ) goto error;
memcpy( p_block->p_buffer, p_sys->out.bufs[0], out_args.bytesGenerated );
switch( out_args.encodedFrameType )
{
case IVIDEO_I_FRAME:
case IVIDEO_II_FRAME:
p_block->i_flags |= BLOCK_FLAG_TYPE_I;
break;
case IVIDEO_P_FRAME:
case IVIDEO_PP_FRAME:
p_block->i_flags |= BLOCK_FLAG_TYPE_P;
break;
case IVIDEO_B_FRAME:
case IVIDEO_BB_FRAME:
p_block->i_flags |= BLOCK_FLAG_TYPE_B;
break;
default:
msg_Warn( p_enc, "Unknown frame type" );
p_block->i_flags |= BLOCK_FLAG_TYPE_PB; /* Wild guess */
break;
}
p_block->i_dts = p_block->i_pts = p_pic->date;
/* Shamelessly copied from ffmpeg/encoder.c */
p_block->i_length = I64C(1000000) *
p_enc->fmt_in.video.i_frame_rate_base /
p_enc->fmt_in.video.i_frame_rate;
/* Looks like we're done */
#ifdef DEBUG_DAVINCI
msg_Info( p_enc, "Yay! Frame encoded correctly" );
#endif
return p_block;
error:
return NULL;
}
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