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

Rewrite davinci codec

parent 5e3df08c
......@@ -4501,11 +4501,11 @@ AC_ARG_ENABLE(fb,
dnl
dnl Linux DaVinci resizer and chroma conversion module
dnl
AC_ARG_ENABLE(davinciresizer,
[ --enable-davinciresizer Linux davinci resizer and chroma conversion support (default disabled on Linux)])
if test "${enable_davinciresizer}" = "yes"
AC_ARG_ENABLE(davinci-resizer,
[ --enable-davinci-resizer Linux davinci resizer and chroma conversion support (default disabled on Linux)])
if test "${enable_davinci_resizer}" = "yes"
then
VLC_ADD_PLUGINS([davinci_resizer])
VLC_ADD_PLUGIN([davinci_resizer])
VLC_ADD_CFLAGS([davinci_resizer],[-I${KNL_INSTALL_DIR}/include])
fi
......@@ -4513,17 +4513,16 @@ dnl
dnl Linux DaVinci codec module
dnl
AC_ARG_ENABLE(davinci,
[ --enable-davinci Linux davinci codec support (default disabled on
Linux)])
[ --enable-davinci Linux davinci codec support (default disabled on Linux)])
if test "${enable_davinci}" = "yes"
then
if ! which ticel-config >/dev/null 2>&1; then
echo "ticel-config not found, required for davinci !"
exit 1
fi
VLC_ADD_PLUGINS([davinci])
VLC_ADD_PLUGIN([davinci])
VLC_ADD_CFLAGS([davinci],[`ticel-config --cflags`])
VLC_ADD_LDFLAGS([davinci],[`ticel-config --libs`])
VLC_ADD_LIBS([davinci],[`ticel-config --libs`])
fi
dnl
......
/*****************************************************************************
* davinci.c: 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 <vlc/vlc.h>
#include <vlc/decoder.h>
#include <gnu/targets/std.h>
#include <xdc/std.h>
#include <ti/sdo/ce/osal/Memory.h>
#include <ti/sdo/ce/video/viddec.h>
#include <ti/sdo/ce/video/videnc.h>
#include <ti/sdo/ce/CERuntime.h>
#define DEBUG_DAVINCI
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int OpenVideoDecoder( vlc_object_t * );
static void CloseVideoDecoder( vlc_object_t * );
static picture_t *DecodeVideoBlock( decoder_t *, block_t ** );
static int OpenVideoEncoder( vlc_object_t * );
static void CloseVideoEncoder( vlc_object_t * );
static block_t *EncodeVideo( encoder_t *, picture_t * );
static int __AllocateBuffer( vlc_object_t *, XDAS_Int32, XDAS_Int32 *, XDM_BufDesc * );
#define AllocateBuffer( a, b, c, d ) __AllocateBuffer( VLC_OBJECT( a ), b, c, d )
static void FreeBuffer( XDM_BufDesc * );
/*****************************************************************************
* 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 video encoder" ) );
set_capability( "encoder", 1337 );
set_callbacks( OpenVideoEncoder, CloseVideoEncoder );
vlc_module_end();
/*****************************************************************************
* 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'):
/*****************************************************************************
* 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
*****************************************************************************/
static 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_EGENERIC;
}
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;
}
/* 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
*****************************************************************************/
static 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;
#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 ) );
p_block = *pp_block;
/* 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 );
#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 erorr: %x)", i, (int)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;
}
/*****************************************************************************
* Video encoder
*****************************************************************************/
struct encoder_sys_t
{
Engine_Handle e;
VIDENC_Handle c;
XDM_BufDesc in;
XDM_BufDesc out;
};
/*****************************************************************************
*
*****************************************************************************/
static 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_EGENERIC;
}
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;
}
/* 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;
}
/*****************************************************************************
*
*****************************************************************************/
static 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 );
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;
}
/*****************************************************************************
* Misc utils
*****************************************************************************/
static 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;
}
static 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;
}
}
SOURCES_davinci = \
davinci.c \
davinci.h \
auddec.c \
viddec.c \
videnc.c \
resizer.c \
reziser.h \
audio.c \
video.c \
fourcc.c \
$(NULL)
# Davinci speed hack
# resizer.c \
# reziser.h
if ENABLE_SOUT
SOURCES_davinci += encoder.c
endif
EXTRA_libdavinci_plugin_la_SOURCES = \
encoder.c \
$(NULL)
/*****************************************************************************
* auddec.c: audio decoder module using the DaVinci DSP.
* audio.c: audio decoder module using the DaVinci DSP.
*****************************************************************************
* Copyright (C) 2008 M2X BV
* Copyright (C) 2008-2009 M2X BV
* $Id$
*
* Authors: Antoine Cellerier <dionoea at videolan dot org>
* Jean-Paul Saman <jean-paul.saman at m2x dot nl>
*
* 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
......@@ -24,9 +25,18 @@
/*****************************************************************************
* Preamble
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include <vlc_aout.h>
#include <vlc_codec.h>
#include "davinci.h"
#include <ti/sdo/ce/audio/auddec.h>
#include <assert.h>
/* Define this to use PTS from the block corresponding to the first byte in
......@@ -52,6 +62,7 @@ struct block_tracker_t
struct decoder_sys_t
{
char *psz_ti_engine;
Engine_Handle e;
AUDDEC_Handle d;
......@@ -75,79 +86,56 @@ int OpenAudioDecoder( vlc_object_t *p_this )
decoder_t *p_dec = (decoder_t *)p_this;
decoder_sys_t *p_sys;
Engine_Error err;
char *psz_codec = NULL;
AUDDEC_Params params;
int i_cat;
const char *psz_codec;
const char *psz_namecodec;
psz_codec = config_GetPsz( p_this, "davinci-auddec-codec" );
if( psz_codec && !*psz_codec )
if( !GetDavinciDecoder( p_dec->fmt_in.i_codec, &i_cat,
&psz_codec, &psz_namecodec ) )
{
free( psz_codec );
psz_codec = NULL;
}
if( psz_codec )
{
char *psz_fourcc = config_GetPsz( p_this, "davinci-auddec-fourcc" );
if( strlen( psz_fourcc ) != 4 || p_dec->fmt_in.i_codec !=
VLC_FOURCC(psz_fourcc[0],psz_fourcc[1],psz_fourcc[2],psz_fourcc[3]))
{
free( psz_codec );
free( psz_fourcc );
return VLC_EGENERIC;
}
free( psz_fourcc );
msg_Dbg( p_this, "Forcing use of audio decoder `%s'", psz_codec );
}
else
{
switch( p_dec->fmt_in.i_codec )
{
CASE_MP3
psz_codec = strdup( "mp3dec" );
break;
CASE_AAC
psz_codec = strdup( "aacdec" );
break;
default:
msg_Dbg( p_dec, "Unsupported codec : %4.4s",(char*)&p_dec->fmt_in.i_codec );
return VLC_EGENERIC;
}
msg_Dbg( p_dec, "Unsupported codec : %4.4s",(char*)&p_dec->fmt_in.i_codec );
return VLC_EGENERIC;
}
/* Allocate our private structure */
p_dec->p_sys = (decoder_sys_t *)malloc( sizeof( decoder_sys_t ) );
p_dec->p_sys = p_sys = (decoder_sys_t *)calloc( 1, 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 ) );
p_sys->psz_ti_engine = var_CreateGetString( p_dec, DEC_CFG_PREFIX "engine" );
if( !p_sys->psz_ti_engine )
{
free( p_sys );
return VLC_ENOMEM;
}
/* Initialize the codec engine */
CERuntime_init();
/* Create an engine handle */
p_sys->e = Engine_open( TI_ENGINE, NULL /*&Engine_ATTRS*/, &err );
p_sys->e = Engine_open( p_sys->psz_ti_engine, NULL /*&Engine_ATTRS*/, &err );
if( err != Engine_EOK )
{
msg_Err( p_dec, "Error while opening engine `%s': %s",
TI_ENGINE, ppsz_engine_error[err] );
p_sys->psz_ti_engine, ppsz_engine_error[err] );
goto error;
}
PrintAvailableAlgorithms( p_this, TI_ENGINE );
PrintAvailableAlgorithms( p_this, p_sys->psz_ti_engine );
/* Create audio decoder */
params.size = sizeof( params );
params.maxSampleRate = 0; /* Use default. in Hz */
params.maxBitrate = 0; /* Use default. in kbps */
params.maxNoOfCh = 0; /* Use default */
params.dataEndianness = XDM_BYTE; /* FIXME? */
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 );
msg_Err( p_dec, "Failed to create audio decoder (%s) for %s",
psz_codec, psz_namecodec );
goto error;
}
......@@ -163,16 +151,15 @@ int OpenAudioDecoder( vlc_object_t *p_this )
}
p_dec->fmt_out.i_cat = AUDIO_ES;
p_dec->fmt_out.i_codec =
p_dec->fmt_out.audio.i_format = AOUT_FMT_S16_NE;
p_dec->fmt_out.audio.i_format = AOUT_FMT_S16_NE;
p_dec->fmt_out.audio.i_bitspersample = 16;
free( psz_codec );
return VLC_SUCCESS;
error:
if( p_sys->e ) Engine_close( p_sys->e );
free( p_sys->psz_ti_engine );
free( p_sys );
free( psz_codec );
return VLC_EGENERIC;
}
......@@ -197,9 +184,55 @@ void CloseAudioDecoder( vlc_object_t *p_this )
FreeBuffer( &p_sys->in );
FreeBuffer( &p_sys->out );
free( p_sys->psz_ti_engine );
free( p_sys );
}
static int InitXDMAudioDecoder( decoder_t *p_dec, AUDDEC_DynamicParams *dparams )
{
decoder_sys_t *p_sys = p_dec->p_sys;
AUDDEC_Status status;
/* Configure audio decoder */
/*if( AUDDEC_control( p_sys->d, XDM_RESET, &dparams, &status )
!= AUDDEC_EOK )
{
msg_Err( p_dec, "Failed to reset decoder" );
goto error;
}*/
dparams->outputFormat = IAUDIO_INTERLEAVED;
if( AUDDEC_control( p_sys->d, XDM_SETPARAMS, dparams, &status ) != AUDDEC_EOK )
{
msg_Err( p_dec, "Failed to set dynamic decoder parameters" );
return VLC_EGENERIC;
}
if( AUDDEC_control( p_sys->d, XDM_GETBUFINFO, dparams, &status ) != AUDDEC_EOK )
{
msg_Err( p_dec, "Failed to get buffer info" );
return VLC_EGENERIC;
}
/* 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" );
return VLC_EGENERIC;
}
/* 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" );
return VLC_EGENERIC;
}
return VLC_EGENERIC;
}
/*****************************************************************************
*
*****************************************************************************/
......@@ -213,7 +246,7 @@ static aout_buffer_t *DecodeAudioBlock( decoder_t *p_dec, block_t **pp_block )
AUDDEC_DynamicParams dparams;
AUDDEC_Status status;
int i;
vlc_bool_t b_reject = VLC_FALSE;
bool b_reject = false;
if( !pp_block || !*pp_block ) return NULL;
p_block = *pp_block;
......@@ -228,73 +261,25 @@ static aout_buffer_t *DecodeAudioBlock( decoder_t *p_dec, block_t **pp_block )
memset( &in_args, 0, sizeof( in_args ) );
memset( &out_args, 0, sizeof( out_args ) );
memset( &dparams, 0, sizeof( dparams ) );
dparams.size = sizeof( dparams );
memset( &status, 0, sizeof( status ) );
status.size = sizeof( status );
if( p_sys->in.numBufs == 0 || p_sys->out.numBufs == 0 )
{
/* Configure audio decoder */
/*if( AUDDEC_control( p_sys->d, XDM_RESET, &dparams, &status )
!= AUDDEC_EOK )
{
msg_Err( p_dec, "Failed to reset decoder" );
goto error;
}*/
dparams.outputFormat = IAUDIO_INTERLEAVED;
if( AUDDEC_control( p_sys->d, XDM_SETPARAMS, &dparams, &status )
!= AUDDEC_EOK )
{
msg_Err( p_dec, "Failed to set dynamic decoder parameters" );
goto error;
}
if( AUDDEC_control( p_sys->d, XDM_GETBUFINFO, &dparams, &status )
!= AUDDEC_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" );
if( InitXDMAudioDecoder( p_dec, &dparams ) == VLC_EGENERIC )
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;
}
/*if( p_dec->fmt_in.i_extra > 0 )
{
#ifdef TRACK_PTS
p_sys->p_tracked_blocks[p_sys->i_tracked_blocks].i_pts = p_block->i_pts;
p_sys->p_tracked_blocks[p_sys->i_tracked_blocks].i_left = p_dec->fmt_in.i_extra;
p_sys->i_tracked_blocks++;
#endif
memcpy( p_sys->in.bufs[0]+p_sys->i_buffer, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra );
p_sys->i_buffer += p_dec->fmt_in.i_extra;
}*/
}
/* Setup input arguments */
in_args.size = sizeof( in_args );
in_args.numBytes = __MIN( p_sys->i_buffer + p_block->i_buffer,
p_sys->in.bufSizes[0] );
(size_t)p_sys->in.bufSizes[0] );
/* Setup input buffer */
int i_used = in_args.numBytes - p_sys->i_buffer;
assert( p_sys->i_buffer + p_block->i_buffer <= p_sys->in.bufSizes[0] );
assert( p_sys->i_buffer + p_block->i_buffer <= (size_t)p_sys->in.bufSizes[0] );
if( i_used > 0 )
{
......@@ -334,7 +319,7 @@ static aout_buffer_t *DecodeAudioBlock( decoder_t *p_dec, block_t **pp_block )
else
{
msg_Err( p_dec, "Rejecting frame" );
b_reject = VLC_TRUE;
b_reject = true;
}
}
......@@ -427,24 +412,25 @@ static aout_buffer_t *DecodeAudioBlock( decoder_t *p_dec, block_t **pp_block )
goto error;
}
p_out = p_dec->pf_aout_buffer_new( p_dec, b_reject ? 0 : status.frameLen /
p_out = decoder_NewAudioBuffer( p_dec, b_reject ? 0 : status.frameLen /
p_dec->fmt_out.audio.i_channels );
if( !p_out )
{
block_Release( p_block );
p_sys->i_buffer = 0;
return NULL;
}
p_out->start_date = aout_DateGet( &p_sys->date );
p_out->end_date = aout_DateIncrement( &p_sys->date, b_reject ? 0 : status.frameLen / p_dec->fmt_out.audio.i_channels );
p_out->end_date = aout_DateIncrement( &p_sys->date, b_reject ?
0 : status.frameLen / p_dec->fmt_out.audio.i_channels );
memcpy( p_out->p_buffer, p_sys->out.bufs[0], p_out->i_nb_bytes );
/*if( p_block->i_buffer == 0 )
{
block_Release( p_block );
*pp_block = NULL;
}*/
return p_out;
error:
if( p_out && p_out->pf_release )
p_out->pf_release( p_out );
if( p_out )
decoder_DeleteAudioBuffer( p_dec, p_out );
block_Release( p_block );
p_sys->i_buffer = 0;
return NULL;
......
/*****************************************************************************
* davinci.c: decoder and encoder modules using the DaVinci DSP.
*****************************************************************************
* Copyright (C) 2008 M2X BV
* Copyright (C) 2008-2009 M2X BV
* $Id$
*
* Authors: Antoine Cellerier <dionoea at videolan dot org>
......@@ -24,6 +24,14 @@
/*****************************************************************************
* Preamble
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_codec.h>
#include "davinci.h"
/*****************************************************************************
......@@ -31,14 +39,21 @@
*****************************************************************************/
/*
* Decoder
* Davinci common
*/
#define VIDDEC_CHROMA_TEXT N_( "Decoder output chroma" )
#define VIDDEC_CHROMA_LONGTEXT N_( \
"Force video decoder to output in specific chroma" )
#define DAVINCI_ENGINE_TEXT N_( "DSP firmware library" )
#define DAVINCI_ENGINE_LONGTEXT N_( \
"Specifiy which DSP firmware library to use. By default " \
"a combined encoder/decoder library \"encodedecode\" is used." )
/*
* Decoder
*/
#define VIDDEC_FULLSCREEN_TEXT N_( "Resize video to fullscreen" )
#define DAVINCI_FOURCC_TEXT N_( "Decoder output fourcc/chroma" )
#define DAVINCI_FOURCC_LONGTEXT N_( \
"Force audio/video decoder to output in specific fourcc/chroma" )
/*
* Encoder
......@@ -63,47 +78,65 @@
#define ENC_QUALITY_LONGTEXT N_( "Encoder qualtiy setting preset. " \
"ranges from 0..3 (0=encoders default, 1=high quality, 2=speed, 3=user defined" )
vlc_module_begin();
/* video decoder */
set_category( CAT_INPUT );
set_subcategory( SUBCAT_INPUT_VCODEC );
set_description( _("DaVinci DSP video decoder") );
set_capability( "decoder", 1337 );
set_callbacks( OpenVideoDecoder, CloseVideoDecoder );
#ifdef DAVINCI_HACK
add_bool( DEC_CFG_PREFIX "fullscreen", VLC_TRUE, NULL,
VIDDEC_FULLSCREEN_TEXT, VIDDEC_FULLSCREEN_TEXT, VLC_FALSE );
#endif
add_string( DEC_CFG_PREFIX "chroma", "", NULL,
VIDDEC_CHROMA_TEXT, VIDDEC_CHROMA_LONGTEXT, VLC_TRUE );
#define MODULE_DESCRIPTION N_( "Various audio and video decoders/encoders" \
"delivered by TI Davinci library. This includes MPEG4, H264, VC-1, "\
"MPEG1, MPEG2, AAC and MP3 codecs")
vlc_module_begin()
/* audio/video decoder */
set_shortname( "Davinci" )
add_shortcut( "davinci" )
set_category( CAT_INPUT )
set_subcategory( SUBCAT_INPUT_SCODEC )
set_description( N_("DaVinci DSP audio/video decoder") )
set_help( MODULE_DESCRIPTION )
set_capability( "decoder", 1337 )
set_section( N_("Decoding") , NULL )
set_callbacks( OpenVideoDecoder, CloseVideoDecoder )
add_string( DEC_CFG_PREFIX "engine", "encodedecode", NULL,
DAVINCI_ENGINE_TEXT, DAVINCI_ENGINE_LONGTEXT, true )
add_string( DEC_CFG_PREFIX "fourcc", "", NULL,
DAVINCI_FOURCC_TEXT, DAVINCI_FOURCC_LONGTEXT, true )
/* audio decoder */
add_submodule();
add_submodule()
add_shortcut( "davinci" )
set_description( _("DaVinci DSP audio decoder") );
set_capability( "decoder", 0 );
set_callbacks( OpenAudioDecoder, CloseAudioDecoder );
#ifdef ENABLE_SOUT
/* video encoder */
add_submodule();
set_description( _("DaVinci DSP video encoder" ) );
set_capability( "encoder", 1337 );
set_callbacks( OpenVideoEncoder, CloseVideoEncoder );
add_submodule()
add_shortcut( "davinci" )
set_description( N_("DaVinci DSP video encoder" ) )
set_capability( "encoder", 1337 )
set_section( N_("Encoding") , NULL )
set_callbacks( OpenVideoEncoder, CloseVideoEncoder )
add_integer( ENC_CFG_PREFIX "keyint", 0, NULL, ENC_KEYINT_TEXT,
ENC_KEYINT_LONGTEXT, VLC_FALSE );
add_bool( ENC_CFG_PREFIX "interlace", VLC_FALSE, NULL, ENC_INTERLACE_TEXT,
ENC_INTERLACE_LONGTEXT, VLC_TRUE );
ENC_KEYINT_LONGTEXT, false )
add_bool( ENC_CFG_PREFIX "interlace", false, NULL, ENC_INTERLACE_TEXT,
ENC_INTERLACE_LONGTEXT, true )
add_integer( ENC_CFG_PREFIX "rc", 1, NULL, ENC_RC_TEXT,
ENC_RC_LONGTEXT, VLC_TRUE );
change_integer_range( 0, 5 );
ENC_RC_LONGTEXT, true )
change_integer_range( 0, 5 )
add_integer( ENC_CFG_PREFIX "tolerance", 0, NULL, ENC_VT_TEXT,
ENC_VT_LONGTEXT, VLC_TRUE );
ENC_VT_LONGTEXT, true )
add_integer( ENC_CFG_PREFIX "quality", 0, NULL, ENC_QUALITY_TEXT,
ENC_QUALITY_LONGTEXT, VLC_TRUE );
change_integer_range( 0, 3 );
vlc_module_end();
ENC_QUALITY_LONGTEXT, true )
change_integer_range( 0, 3 )
#endif
#if 0
/* video filter submodule */
add_submodule ()
set_capability( "video filter2", 0 )
set_callbacks( OpenResizer, CloseResizer )
set_description( N_("Davinci resizer video filter") )
add_shortcut( "davinci-resizer" )
#endif
vlc_module_end()
/*****************************************************************************
* Memory utils
......@@ -225,40 +258,3 @@ void __PrintAvailableAlgorithms( vlc_object_t *p_this, const char *psz_engine )
}
}
}
XDAS_Int32 VlcChromaToXdm( vlc_fourcc_t i_chroma )
{
switch( i_chroma )
{
case VLC_FOURCC('I','4','2','0'):
return XDM_YUV_420P;
case VLC_FOURCC('I','4','1','1'):
return XDM_YUV_411P;
case VLC_FOURCC('I','4','2','2'):
return XDM_YUV_422P;
case VLC_FOURCC('I','4','4','4'):
return XDM_YUV_444P;
case VLC_FOURCC('Y','U','Y','V'):
return XDM_YUV_422IBE; /* FIXME ? */
case VLC_FOURCC('U','Y','V','Y'):
return XDM_YUV_422ILE; /* FIXME ? */
case VLC_FOURCC('G','R','E','Y'):
return XDM_GRAY;
#if 0
/* FIXME: not sure about this one */
case VLC_FOURCC('R','V','2','4'):
case VLC_FOURCC('R','V','3','2'):
return XDM_RGB;
#endif
default:
return XDM_CHROMA_NA;
}
}
/*****************************************************************************
* davinci.h: decoder and encoder modules using the DaVinci DSP.
*****************************************************************************
* Copyright (C) 2008 M2X BV
* Copyright (C) 2008-2009 M2X BV
* $Id$
*
* Authors: Antoine Cellerier <dionoea at videolan dot org>
* Jean-Paul Saman <jean-paul.saman at m2x dot nl>
*
* 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
......@@ -24,9 +25,6 @@
#ifndef VLC_DAVINCI_H
#define VLC_DAVINCI_H
#include <vlc/vlc.h>
#include <vlc/decoder.h>
#define XDM_INCLUDE_DOT9_SUPPORT /* Support old 0.9 API */
#include <gnu/targets/std.h>
#include <xdc/std.h>
......@@ -35,12 +33,10 @@
#include <ti/sdo/ce/CERuntime.h>
#include <ti/sdo/ce/Engine.h>
#define DEBUG_DAVINCI
#define DAVINCI_HACK /* directly resize and output the decoded video */
#define TI_ENGINE "encodedecode"
#undef DEBUG_DAVINCI
#define ENC_CFG_PREFIX "davinci-videnc-"
#define DEC_CFG_PREFIX "davinci-viddec-"
#define ENC_CFG_PREFIX "sout-davinci-"
#define DEC_CFG_PREFIX "davinci-"
int OpenVideoDecoder( vlc_object_t * );
void CloseVideoDecoder( vlc_object_t * );
......@@ -57,132 +53,15 @@ void FreeBuffer( XDM_BufDesc * );
const char *davinci_GetExtendedError( XDAS_Int32 );
void __PrintAvailableAlgorithms( vlc_object_t *, const char * );
#define PrintAvailableAlgorithms( a, b ) __PrintAvailableAlgorithms( VLC_OBJECT( a ), b )
XDAS_Int32 VlcChromaToXdm( vlc_fourcc_t );
/*****************************************************************************
* Common stuff
*****************************************************************************/
extern const char *ppsz_engine_error[];
/* 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'): \
/* MSMPEG4 v1 (Not sure that we should include these) */ \
case VLC_FOURCC('D','I','V','1'): \
case VLC_FOURCC('d','i','v','1'): \
case VLC_FOURCC('M','P','G','4'): \
case VLC_FOURCC('m','p','g','4'): \
/* MSMPEG4 v2 (Not sure that we should include these) */ \
case VLC_FOURCC('D','I','V','2'): \
case VLC_FOURCC('d','i','v','2'): \
case VLC_FOURCC('M','P','4','2'): \
case VLC_FOURCC('m','p','4','2'): \
/* MSMPEG4 v3 (Not sure that we should include these) */ \
case VLC_FOURCC('M','P','G','3'): \
case VLC_FOURCC('m','p','g','3'): \
case VLC_FOURCC('d','i','v','3'): \
case VLC_FOURCC('M','P','4','3'): \
case VLC_FOURCC('m','p','4','3'): \
case VLC_FOURCC('D','I','V','3'): \
case VLC_FOURCC('D','I','V','4'): \
case VLC_FOURCC('d','i','v','4'): \
case VLC_FOURCC('D','I','V','5'): \
case VLC_FOURCC('d','i','v','5'): \
case VLC_FOURCC('D','I','V','6'): \
case VLC_FOURCC('d','i','v','6'): \
case VLC_FOURCC('C','O','L','1'): \
case VLC_FOURCC('c','o','l','1'): \
case VLC_FOURCC('C','O','L','0'): \
case VLC_FOURCC('c','o','l','0'): \
case VLC_FOURCC('A','P','4','1'): \
case VLC_FOURCC('3','I','V','D'): \
case VLC_FOURCC('3','i','v','d'): \
case VLC_FOURCC('3','V','I','D'): \
case VLC_FOURCC('3','v','i','d'):
#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','g','a'): \
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'):
bool GetDavinciDecoder( vlc_fourcc_t, int *, const char **, const char ** );
bool GetDavinciEncoder( vlc_fourcc_t, int *, const char **, const char ** );
bool GetVlcFourcc( const char *, int *, vlc_fourcc_t *, const char ** );
XDAS_Int32 VlcChromaToXdm( vlc_fourcc_t );
#endif
/*****************************************************************************
* videnc.c: video encoder module using the DaVinci DSP.
* encoder.c: video encoder module using the DaVinci DSP.
*****************************************************************************
* Copyright (C) 2008 M2X BV
* Copyright (C) 2008-2009 M2X BV
* $Id$
*
* Authors: Antoine Cellerier <dionoea at videolan dot org>
* Rafaël Carré <rcarre@m2x.nl>
* Jean-Paul Saman <jean-paul.saman at m2x dot nl>
*
* 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
......@@ -25,11 +26,22 @@
/*****************************************************************************
* Preamble
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include <vlc_vout.h>
#include <vlc_aout.h>
#include <vlc_sout.h>
#include <vlc_codec.h>
#include "davinci.h"
#include <assert.h>
#include <ti/sdo/ce/video/videnc.h>
#include <assert.h>
/*****************************************************************************
* Local prototypes
*****************************************************************************/
......@@ -40,6 +52,8 @@ static block_t *EncodeVideo( encoder_t *, picture_t * );
*****************************************************************************/
struct encoder_sys_t
{
char *psz_ti_engine;
Engine_Handle e;
VIDENC_Handle c;
......@@ -50,102 +64,36 @@ struct encoder_sys_t
/*****************************************************************************
*
*****************************************************************************/
static void picfree( picture_t *p_pic )
{
if( p_pic->i_type == MEMORY_PICTURE )
free( p_pic->p_data_orig );
free( p_pic );
}
static picture_t * NewEncoderBuffer( encoder_t *p_enc, decoder_t *p_dec )
{
p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
picture_t *p_pic = malloc(sizeof(picture_t));
if( !p_pic ) return NULL;
if( !p_enc->p_sys->in.numBufs )
{
vout_AllocatePicture( p_dec, p_pic,
p_dec->fmt_out.video.i_chroma,
p_dec->fmt_out.video.i_width,
p_dec->fmt_out.video.i_height,
p_dec->fmt_out.video.i_aspect );
if( !p_pic->i_planes )
{
free( p_pic );
return NULL;
}
p_pic->i_type = MEMORY_PICTURE;
}
else
{
p_pic->i_planes = 1;
vout_InitPicture( p_dec, p_pic,
p_dec->fmt_out.video.i_chroma,
p_dec->fmt_out.video.i_width,
p_dec->fmt_out.video.i_height,
p_dec->fmt_out.video.i_aspect );
p_pic->p_data = p_enc->p_sys->in.bufs[0];
p_pic->p_data_orig = NULL;
p_pic->p[0].p_pixels = p_pic->p_data;
p_pic->i_type = DIRECT_PICTURE;
}
p_pic->pf_release = picfree;
p_pic->i_status = RESERVED_PICTURE;
p_pic->p_sys = NULL;
return p_pic;
}
int OpenVideoEncoder( vlc_object_t *p_this )
{
encoder_t *p_enc = (encoder_t *)p_this;
encoder_sys_t *p_sys;
char *psz_codec = NULL;
Engine_Error err;
VIDENC_Params params;
int i_cat;
const char *psz_codec;
const char *psz_namecodec;
switch( p_enc->fmt_out.i_codec )
if( !GetDavinciEncoder( p_enc->fmt_out.i_codec, &i_cat,
&psz_codec, &psz_namecodec ) )
{
#if 0
CASE_MPEG1
psz_codec = strdup( "mpegenc" ); /* FIXME */
break;
CASE_MPEG2
psz_codec = strdup( "mpeg2enc" ); /* FIXME */
break;
#endif
CASE_MPEG4
psz_codec = strdup( "mpeg4enc" );
break;
CASE_H264
psz_codec = strdup( "h264enc" );
break;
#if 0
CASE_VC1
psz_codec = strdup( "vc1enc" ); /* FIXME */
break;
#endif
default:
return VLC_EGENERIC;
msg_Dbg( p_enc, "Unsupported codec : %4.4s",(char*)&p_enc->fmt_in.i_codec );
return VLC_EGENERIC;
}
/* Allocate our private structure */
p_enc->p_sys = (encoder_sys_t *)malloc( sizeof( encoder_sys_t ) );
p_enc->p_sys = (encoder_sys_t *)calloc( 1, 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 ) );
p_sys->psz_ti_engine = var_CreateGetString( p_enc, DEC_CFG_PREFIX "engine" );
if( !p_sys->psz_ti_engine )
{
free( p_sys );
return VLC_ENOMEM;
}
/* FIXME: number of frames between 2 keyframes */
p_enc->i_iframes = var_CreateGetInteger( p_enc, ENC_CFG_PREFIX "keyint" );
......@@ -156,15 +104,15 @@ int OpenVideoEncoder( vlc_object_t *p_this )
CERuntime_init();
/* Create an engine handle */
p_sys->e = Engine_open( TI_ENGINE, NULL /*&Engine_ATTRS*/, &err );
p_sys->e = Engine_open( p_sys->psz_ti_engine, NULL /*&Engine_ATTRS*/, &err );
if( err != Engine_EOK )
{
msg_Err( p_enc, "Error while opening engine `%s': %s",
TI_ENGINE, ppsz_engine_error[err] );
p_sys->psz_ti_engine, ppsz_engine_error[err] );
goto error;
}
PrintAvailableAlgorithms( p_this, TI_ENGINE );
PrintAvailableAlgorithms( p_this, p_sys->psz_ti_engine );
/* Configure encoder */
params.size = sizeof( params );
......@@ -214,10 +162,10 @@ int OpenVideoEncoder( vlc_object_t *p_this )
params.inputChromaFormat = VlcChromaToXdm( VLC_FOURCC('I','4','2','0' ) );
}
/* FIXME: we don't know if it's progressive or interlaced
/* NOTE: we don't know if it's progressive or interlaced
* until we get the first picture (p_pic->b_progressive).
* Thus let a knowledgeable user override this setting. */
if( var_CreateGetBool( p_enc, ENC_CFG_PREFIX "interlace" ) == VLC_TRUE )
if( var_CreateGetBool( p_enc, ENC_CFG_PREFIX "interlace" ) )
params.inputContentType = IVIDEO_INTERLACED;
else
params.inputContentType = IVIDEO_PROGRESSIVE;
......@@ -226,22 +174,21 @@ int OpenVideoEncoder( vlc_object_t *p_this )
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 );
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;
p_enc->pf_enc_buffer_new = NewEncoderBuffer;
free( psz_codec );
return VLC_SUCCESS;
error:
if( p_sys->e ) Engine_close( p_sys->e );
free( p_sys );
free( psz_codec );
return VLC_EGENERIC;
error:
if( p_sys->e ) Engine_close( p_sys->e );
free( p_sys->psz_ti_engine );
free( p_sys );
return VLC_EGENERIC;
}
/*****************************************************************************
......@@ -265,12 +212,30 @@ void CloseVideoEncoder( vlc_object_t *p_this )
FreeBuffer( &p_sys->in );
FreeBuffer( &p_sys->out );
free( p_sys->psz_ti_engine );
free( p_sys );
}
/*****************************************************************************
*
*****************************************************************************/
static inline void davinci_CopyPictureToXDM( decoder_t *p_dec, XDM_BufDesc *p_buf, picture_t *p_pic )
{
/* Copy input picture */
assert( p_pic->i_planes == p_buf->numBufs );
assert( p_pic->i_planes == 1 );
for( int i = 0; i < p_pic->i_planes; i++ )
{
if( p_pic->i_type == MEMORY_PICTURE )
{
plane_t *p = p_pic->p + i;
memcpy( p_buf->bufs[i], p->p_pixels, p->i_pitch * p->i_visible_lines );
}
/* if it's our direct buffer, we have nothing to do */
}
}
static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pic )
{
encoder_sys_t *p_sys = p_enc->p_sys;
......@@ -346,6 +311,7 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pic )
}
}
#if 1
/* Copy input picture */
assert( p_pic->i_planes == p_sys->in.numBufs );
assert( p_pic->i_planes == 1 );
......@@ -359,7 +325,9 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pic )
}
/* if it's our direct buffer, we have nothing to do */
}
#else
davinci_CopyPictureToXDM( p_dec, p_sys->in, p_pic );
#endif
/* Configure input */
in_args.size = sizeof( in_args );
......@@ -412,12 +380,12 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pic )
p_block->i_dts = p_block->i_pts = p_pic->date;
/* Shamelessly copied from ffmpeg/encoder.c */
p_block->i_length = I64C(1000000) *
p_block->i_length = INT64_C(1000000) *
p_enc->fmt_in.video.i_frame_rate_base /
p_enc->fmt_in.video.i_frame_rate;
return p_block;
error:
return NULL;
error:
return NULL;
}
/*****************************************************************************
* viddec.c: video decoder module using the DaVinci DSP.
* fb.c: video decoder module using the DaVinci DSP.
*****************************************************************************
* Copyright (C) 2008 M2X BV
* Copyright (C) 2008-2009 M2X BV
* $Id$
*
* Authors: Antoine Cellerier <dionoea at videolan dot org>
* Rafaël Carré <rcarre@m2x.nl>
* Jean-Paul Saman <jean-paul.saman at m2x dot nl>
*
* 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
......@@ -25,11 +26,21 @@
/*****************************************************************************
* Preamble
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include <vlc_codec.h>
#include <vlc_vout.h>
#include <vlc_codecs.h>
#include "davinci.h"
#include <assert.h>
#include <ti/sdo/ce/video/viddec.h>
#define DAVINCI_HACK /* directly resize and output the decoded video */
#ifdef DAVINCI_HACK
#include "resizer.h"
#endif
......@@ -45,6 +56,7 @@ static picture_t *DecodeVideoBlockInner( decoder_t *, block_t **, int );
*****************************************************************************/
struct decoder_sys_t
{
char *psz_ti_engine;
Engine_Handle e;
VIDDEC_Handle d;
......@@ -60,7 +72,7 @@ struct decoder_sys_t
/* resizer */
davinci_resizer_t rsz;
vlc_bool_t b_resize;
bool b_resize;
vlc_mutex_t cb_lock;
#endif
};
......@@ -95,17 +107,13 @@ int OpenVideoDecoder( vlc_object_t *p_this )
switch( p_dec->fmt_in.i_codec )
{
/* enable the following if you bought the codecs from TI */
#if 0
CASE_VC1
psz_codec = strdup( "vc1dec" );
break;
#endif
#if 0
psz_codec = strdup( "vc1dec" );
break;
CASE_MPEG1
psz_codec = strdup( "mpegdec" );
break;
#endif
CASE_MPEG2
psz_codec = strdup( "mpeg2dec" );
......@@ -124,31 +132,38 @@ int OpenVideoDecoder( vlc_object_t *p_this )
}
/* Allocate our private structure */
p_dec->p_sys = (decoder_sys_t *)malloc( sizeof( decoder_sys_t ) );
p_dec->p_sys = (decoder_sys_t *)calloc( 1, sizeof( decoder_sys_t ) );
if( !p_dec->p_sys )
{
free( psz_codec );
return VLC_ENOMEM;
}
p_sys = p_dec->p_sys;
memset( p_sys, 0, sizeof( decoder_sys_t ) );
p_sys->psz_ti_engine = var_CreateGetString( DEC_CFG_PREFIX "engine" );
if( !p_sys->psz_ti_engine )
{
free( psz_codec );
free( p_sys );
return VLC_ENOMEM;
}
/* Initialize the codec engine */
CERuntime_init();
/* Create an engine handle */
p_sys->e = Engine_open( TI_ENGINE, NULL /*&Engine_ATTRS*/, &err );
p_sys->e = Engine_open( p_sys->psz_ti_engine, NULL /*&Engine_ATTRS*/, &err );
if( err != Engine_EOK )
{
msg_Err( p_dec, "Error while opening engine `%s': %s",
TI_ENGINE, ppsz_engine_error[err] );
p_sys->psz_ti_engine, ppsz_engine_error[err] );
goto error;
}
PrintAvailableAlgorithms( p_this, TI_ENGINE );
PrintAvailableAlgorithms( p_this, p_sys->psz_ti_engine );
/* Get user supplied chroma setting */
psz_chroma = config_GetPsz( p_dec, "davinci-viddec-chroma" );
psz_chroma = config_GetPsz( p_dec, DEC_CFG_PREFIX "chroma" );
if( psz_chroma && strlen( psz_chroma ) == 4 )
{
i_chroma = VLC_FOURCC( psz_chroma[0], psz_chroma[1],
......@@ -204,8 +219,8 @@ int OpenVideoDecoder( vlc_object_t *p_this )
goto error;
}
p_sys->b_resize = var_CreateGetBool( p_dec, "davinci-viddec-fullscreen" );
var_AddCallback( p_dec, "davinci-viddec-fullscreen", fullscreen_cb, p_sys );
p_sys->b_resize = var_GetBool( p_dec->p_libvlc, "fullscreen" );
var_AddCallback( p_dec->p_libvlc, "fullscreen", fullscreen_cb, p_sys );
vlc_mutex_init( p_this, &p_sys->cb_lock );
#endif
......@@ -213,13 +228,14 @@ int OpenVideoDecoder( vlc_object_t *p_this )
p_dec->pf_decode_video = DecodeVideoBlock;
/* DaVinci decoder needs complete frames */
p_dec->b_need_packetized = VLC_TRUE;
p_dec->b_need_packetized = true;
free( psz_codec );
return VLC_SUCCESS;
error:
if( p_sys->e ) Engine_close( p_sys->e );
free( p_sys->psz_ti_engine );
free( p_sys );
free( psz_codec );
return VLC_EGENERIC;
......@@ -257,6 +273,7 @@ void CloseVideoDecoder( vlc_object_t *p_this )
FreeBuffer( &p_sys->in );
FreeBuffer( &p_sys->out );
free( p_sys->psz_ti_engine );
free( p_sys );
}
......@@ -278,7 +295,7 @@ static picture_t *DecodeVideoBlockInner( decoder_t *p_dec, block_t **pp_block, i
VIDDEC_Status status;
int i;
if( !p_sys->p_packetizer &&
if( !p_sys->p_packetizer &&
p_dec->fmt_in.i_codec == VLC_FOURCC( 'a', 'v', 'c', '1' ) )
{
p_sys->p_packetizer = vlc_object_create( p_dec, VLC_OBJECT_PACKETIZER );
......@@ -311,8 +328,7 @@ static picture_t *DecodeVideoBlockInner( decoder_t *p_dec, block_t **pp_block, i
if( p_sys->p_packetizer && !i_extra )
{
block_t *p_new_block = p_sys->p_packetizer->pf_packetize(
p_sys->p_packetizer, &p_block );
block_t *p_new_block = p_sys->p_packetizer->pf_packetize( p_sys->p_packetizer, &p_block );
*pp_block = p_block = p_new_block; /* keep refernce to packetized blk */
if( !p_block )
......@@ -444,8 +460,8 @@ static picture_t *DecodeVideoBlockInner( decoder_t *p_dec, block_t **pp_block, i
msg_Err( p_dec, "Could not get picture" );
goto error;
}
p_pic->b_progressive = status.contentType == IVIDEO_INTERLACED ? VLC_FALSE
: VLC_TRUE;
p_pic->b_progressive = status.contentType == IVIDEO_INTERLACED ? false
: true;
#endif
#ifdef DEBUG_DAVINCI
switch( out_args.decodedFrameType )
......@@ -497,7 +513,7 @@ static picture_t *DecodeVideoBlockInner( decoder_t *p_dec, block_t **pp_block, i
#else
vlc_mutex_lock( &p_sys->cb_lock );
vlc_bool_t b_resize = p_sys->b_resize;
bool b_resize = p_sys->b_resize;
vlc_mutex_unlock( &p_sys->cb_lock );
Resize( p_dec, b_resize, &p_sys->rsz, &p_sys->fb, p_sys->out );
......
/*****************************************************************************
* fourcc.c: davinci <-> libvlc conversion routines
*****************************************************************************
* Copyright (C) 2009 M2X BV
* $Id$
*
* Authors: Jean-Paul Saman <jpsaman@videolan.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.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <vlc_common.h>
#include <vlc_codec.h>
#include "davinci.h"
/*****************************************************************************
* Codec fourcc -> davinic_id mapping
*****************************************************************************/
/* Enable codecs by changing #undef in #define here below */
#undef DAVINCI_HAS_MPEG1_CODEC
#define DAVINCI_HAS_MPEG2_CODEC
#define DAVINCI_HAS_MPEG4_CODEC
#define DAVINCI_HAS_H264_CODEC
#define DAVINCI_HAS_VC1_CODEC
#undef DAVINCI_HAS_MP3_CODEC
#undef DAVINCI_HAS_AAC_CODEC
/* decoders */
#define DAVINCI_DEC_MPEG1 "mpegdec"
#define DAVINCI_DEC_MPEG2 "mpeg2dec"
#define DAVINCI_DEC_MPEG4 "mpeg4dec"
#define DAVINCI_DEC_H264 "h264dec"
#define DAVINCI_DEC_VC1 "vc1dec"
#define DAVINIC_DEC_MP3 "mp3dec"
#define DAVINCI_DEC_AAC "aacdec"
/* encoders */
#define DAVINCI_ENC_MPEG1 "mpegenc"
#define DAVINCI_ENC_MPEG2 "mpeg2enc"
#define DAVINCI_ENC_MPEG4 "mpeg4enc"
#define DAVINCI_ENC_H264 "h264enc"
#define DAVINCI_ENC_VC1 "vc1enc"
#define DAVINIC_NONE ""
static const struct
{
vlc_fourcc_t i_fourcc;
const char psz_decoder[10];
const char psz_encoder[10];
int i_cat;
const char psz_name[36];
} codecs_table[] =
{
/*
* Video Codecs
*/
#ifdef DAVINCI_HAS_MPEG1_CODEC
/* MPEG-1 Video */
{ VLC_FOURCC('m','p','1','v'), DAVINCI_DEC_MPEG1, DAVINCI_ENC_MPEG1,
VIDEO_ES, "MPEG-1 Video" },
{ VLC_FOURCC('m','p','e','g'), DAVINCI_DEC_MPEG1, DAVINCI_ENC_MPEG1,
VIDEO_ES, "MPEG-1 Video" },
{ VLC_FOURCC('m','p','g','1'), DAVINCI_DEC_MPEG1, DAVINCI_ENC_MPEG1,
VIDEO_ES, "MPEG-1 Video" },
{ VLC_FOURCC('P','I','M','1'), DAVINCI_DEC_MPEG1, DAVINCI_ENC_MPEG1,
VIDEO_ES, "Pinnacle DC1000 (MPEG-1 Video)" },
#endif
#ifdef DAVINCI_HAS_MPEG2_CODEC
/* MPEG-2 Video */
{ VLC_FOURCC('m','p','2','v'), DAVINCI_DEC_MPEG2, DAVINCI_ENC_MPEG2,
VIDEO_ES, "MPEG-2 Video" },
{ VLC_FOURCC('M','P','E','G'), DAVINCI_DEC_MPEG2, DAVINCI_ENC_MPEG2,
VIDEO_ES, "MPEG-2 Video" },
{ VLC_FOURCC('m','p','g','v'), DAVINCI_DEC_MPEG2, DAVINCI_ENC_MPEG2,
VIDEO_ES, "MPEG-2 Video" },
{ VLC_FOURCC('m','p','g','2'), DAVINCI_DEC_MPEG2, DAVINCI_ENC_MPEG2,
VIDEO_ES, "MPEG-2 Video" },
{ VLC_FOURCC('h','d','v','1'), DAVINCI_DEC_MPEG2, DAVINCI_ENC_MPEG2,
VIDEO_ES, "HDV 720p30 (MPEG-2 Video)" },
{ VLC_FOURCC('h','d','v','2'), DAVINCI_DEC_MPEG2, DAVINCI_ENC_MPEG2,
VIDEO_ES, "Sony HDV (MPEG-2 Video)" },
{ VLC_FOURCC('h','d','v','3'), DAVINCI_DEC_MPEG2, DAVINCI_ENC_MPEG2,
VIDEO_ES, "FCP HDV (MPEG-2 Video)" },
{ VLC_FOURCC('h','d','v','5'), DAVINCI_DEC_MPEG2, DAVINCI_ENC_MPEG2,
VIDEO_ES, "HDV 720p25 (MPEG-2 Video)" },
{ VLC_FOURCC('h','d','v','6'), DAVINCI_DEC_MPEG2, DAVINCI_ENC_MPEG2,
VIDEO_ES, "HDV 1080p24 (MPEG-2 Video)" },
{ VLC_FOURCC('h','d','v','7'), DAVINCI_DEC_MPEG2, DAVINCI_ENC_MPEG2,
VIDEO_ES, "HDV 1080p25 (MPEG-2 Video)" },
{ VLC_FOURCC('h','d','v','8'), DAVINCI_DEC_MPEG2, DAVINCI_ENC_MPEG2,
VIDEO_ES, "HDV 1080p30 (MPEG-2 Video)" },
{ VLC_FOURCC('m','x','5','n'), DAVINCI_DEC_MPEG2, DAVINCI_ENC_MPEG2,
VIDEO_ES, "MPEG2 IMX NTSC 525/60 50mb/s (FCP)" },
{ VLC_FOURCC('m','x','5','p'), DAVINCI_DEC_MPEG2, DAVINCI_ENC_MPEG2,
VIDEO_ES, "MPEG2 IMX PAL 625/60 50mb/s (FCP)" },
{ VLC_FOURCC('m','x','4','n'), DAVINCI_DEC_MPEG2, DAVINCI_ENC_MPEG2,
VIDEO_ES, "MPEG2 IMX NTSC 525/60 40mb/s (FCP)" },
{ VLC_FOURCC('m','x','4','p'), DAVINCI_DEC_MPEG2, DAVINCI_ENC_MPEG2,
VIDEO_ES, "MPEG2 IMX PAL 625/50 40mb/s (FCP)" },
{ VLC_FOURCC('m','x','3','n'), DAVINCI_DEC_MPEG2, DAVINCI_ENC_MPEG2,
VIDEO_ES, "MPEG2 IMX NTSC 525/60 30mb/s (FCP)" },
{ VLC_FOURCC('m','x','3','p'), DAVINCI_DEC_MPEG2, DAVINCI_ENC_MPEG2,
VIDEO_ES, "MPEG2 IMX NTSC 625/50 30mb/s (FCP)" },
{ VLC_FOURCC('x','d','v','2'), DAVINCI_DEC_MPEG2, DAVINCI_ENC_MPEG2,
VIDEO_ES, "XDCAM HD 1080i60" },
{ VLC_FOURCC('A','V','m','p'), DAVINCI_DEC_MPEG2, DAVINCI_ENC_MPEG2,
VIDEO_ES, "AVID IMX PAL" },
/* ATI VCR2 */
{ VLC_FOURCC('V','C','R','2'), DAVINCI_DEC_MPEG2, DAVINCI_ENC_MPEG2,
VIDEO_ES, "ATI VCR2 Video" },
{ VLC_FOURCC('M','M','E','S'), DAVINCI_DEC_MPEG2, DAVINCI_ENC_MPEG2,
VIDEO_ES, "Matrox MPEG-2" },
{ VLC_FOURCC('m','m','e','s'), DAVINCI_DEC_MPEG2, DAVINCI_ENC_MPEG2,
VIDEO_ES, "Matrox MPEG-2" },
{ VLC_FOURCC('P','I','M','2'), DAVINCI_DEC_MPEG2, DAVINCI_ENC_MPEG2,
VIDEO_ES, "Pinnacle DC1000 (MPEG-2 Video)" },
#endif
#ifdef DAVINCI_HAS_MPEG4_CODEC
/* MPEG-4 Video */
{ VLC_FOURCC('D','I','V','X'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('d','i','v','x'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('M','P','4','S'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('m','p','4','s'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('M','4','S','2'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('m','4','s','2'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
/* XVID flavours */
{ VLC_FOURCC('x','v','i','d'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('X','V','I','D'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('X','v','i','D'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('X','V','I','X'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('x','v','i','x'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
/* DX50 */
{ VLC_FOURCC('D','X','5','0'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('d','x','5','0'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('B','L','Z','0'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "Blizzard MPEG-4 Video" },
{ VLC_FOURCC('D','X','G','M'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "Electronic Arts Game MPEG-4 Video" },
{ VLC_FOURCC('m','p','4','v'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('M','P','4','V'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC( 4, 0, 0, 0 ), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('m','4','c','c'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('M','4','C','C'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('F','M','P','4'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('f','m','p','4'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
/* 3ivx delta 3.5 Unsupported
* putting it here gives extreme distorted images
{ VLC_FOURCC('3','I','V','1'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('3','i','v','1'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" }, */
/* 3ivx delta 4 */
{ VLC_FOURCC('3','I','V','2'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('3','i','v','2'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('U','M','P','4'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "UB MPEG-4 Video" },
{ VLC_FOURCC('W','V','1','F'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('S','E','D','G'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "Samsung MPEG-4 Video" },
{ VLC_FOURCC('R','M','P','4'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "REALmagic MPEG-4 Video" },
{ VLC_FOURCC('H','D','X','4'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "Jomigo HDX4 (MPEG-4 Video)" },
{ VLC_FOURCC('h','d','x','4'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "Jomigo HDX4 (MPEG-4 Video)" },
{ VLC_FOURCC('S','M','P','4'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "Samsung SMP4 (MPEG-4 Video)" },
{ VLC_FOURCC('s','m','p','4'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "Samsung SMP4 (MPEG-4 Video)" },
{ VLC_FOURCC('f','v','f','w'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "FFmpeg MPEG-4" },
{ VLC_FOURCC('F','V','F','W'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "FFmpeg MPEG-4" },
{ VLC_FOURCC('F','F','D','S'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "FFDShow MPEG-4" },
{ VLC_FOURCC('V','I','D','M'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "vidm 4.01 codec" },
{ VLC_FOURCC('D','C','O','D'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('f','m','p','4'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('M','V','X','M'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('P','M','4','V'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('f','m','p','4'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('M','4','T','3'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('G','E','O','X'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('D','M','K','2'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('D','I','G','I'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('I','N','M','C'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('S','N','4','0'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
{ VLC_FOURCC('E','P','H','V'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MPEG-4 Video" },
/* MSMPEG4 v1 */
{ VLC_FOURCC('D','I','V','1'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v1" },
{ VLC_FOURCC('d','i','v','1'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v1" },
{ VLC_FOURCC('M','P','G','4'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v1" },
{ VLC_FOURCC('m','p','g','4'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v1" },
{ VLC_FOURCC('m','p','4','1'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v1" },
/* MSMPEG4 v2 */
{ VLC_FOURCC('D','I','V','2'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v2" },
{ VLC_FOURCC('d','i','v','2'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v2" },
{ VLC_FOURCC('M','P','4','2'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v2" },
{ VLC_FOURCC('m','p','4','2'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v2" },
/* MSMPEG4 v3 / M$ mpeg4 v3 */
{ VLC_FOURCC('M','P','G','3'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v3" },
{ VLC_FOURCC('m','p','g','3'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v3" },
{ VLC_FOURCC('d','i','v','3'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v3" },
{ VLC_FOURCC('M','P','4','3'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v3" },
{ VLC_FOURCC('m','p','4','3'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v3" },
/* DivX 3.20 */
{ VLC_FOURCC('D','I','V','3'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v3" },
{ VLC_FOURCC('D','I','V','4'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v3" },
{ VLC_FOURCC('d','i','v','4'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v3" },
{ VLC_FOURCC('D','I','V','5'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v3" },
{ VLC_FOURCC('d','i','v','5'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v3" },
{ VLC_FOURCC('D','I','V','6'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v3" },
{ VLC_FOURCC('d','i','v','6'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v3" },
/* Cool Codec */
{ VLC_FOURCC('C','O','L','1'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v3" },
{ VLC_FOURCC('c','o','l','1'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v3" },
{ VLC_FOURCC('C','O','L','0'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v3" },
{ VLC_FOURCC('c','o','l','0'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v3" },
/* AngelPotion stuff */
{ VLC_FOURCC('A','P','4','1'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v3" },
/* 3ivx doctered divx files */
{ VLC_FOURCC('3','I','V','D'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v3" },
{ VLC_FOURCC('3','i','v','d'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v3" },
/* who knows? */
{ VLC_FOURCC('3','V','I','D'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v3" },
{ VLC_FOURCC('3','v','i','d'), DAVINCI_DEC_MPEG4, DAVINCI_ENC_MPEG4,
VIDEO_ES, "MS MPEG-4 Video v3" },
#endif
#ifdef DAVINCI_HAS_H264_CODEC
/* h264 */
{ VLC_FOURCC('h','2','6','4'), DAVINCI_DEC_H264, DAVINCI_ENC_H264,
VIDEO_ES, "H264 - MPEG-4 AVC (part 10)" },
{ VLC_FOURCC('H','2','6','4'), DAVINCI_DEC_H264, DAVINCI_ENC_H264,
VIDEO_ES, "H264 - MPEG-4 AVC (part 10)" },
{ VLC_FOURCC('x','2','6','4'), DAVINCI_DEC_H264, DAVINCI_ENC_H264,
VIDEO_ES, "H264 - MPEG-4 AVC (part 10)" },
{ VLC_FOURCC('X','2','6','4'), DAVINCI_DEC_H264, DAVINCI_ENC_H264,
VIDEO_ES, "H264 - MPEG-4 AVC (part 10)" },
/* avc1: special case h264 */
{ VLC_FOURCC('a','v','c','1'), DAVINCI_DEC_H264, DAVINCI_ENC_H264,
VIDEO_ES, "H264 - MPEG-4 AVC (part 10)" },
{ VLC_FOURCC('A','V','C','1'), DAVINCI_DEC_H264, DAVINCI_ENC_H264,
VIDEO_ES, "H264 - MPEG-4 AVC (part 10)" },
{ VLC_FOURCC('V','S','S','H'), DAVINCI_DEC_H264, DAVINCI_ENC_H264,
VIDEO_ES, "Vanguard VSS H264" },
{ VLC_FOURCC('V','S','S','W'), DAVINCI_DEC_H264, DAVINCI_ENC_H264,
VIDEO_ES, "Vanguard VSS H264" },
{ VLC_FOURCC('v','s','s','h'), DAVINCI_DEC_H264, DAVINCI_ENC_H264,
VIDEO_ES, "Vanguard VSS H264" },
{ VLC_FOURCC('D','A','V','C'), DAVINCI_DEC_H264, DAVINCI_ENC_H264,
VIDEO_ES, "Dicas MPEGable H.264/MPEG-4 AVC" },
{ VLC_FOURCC('d','a','v','c'), DAVINCI_DEC_H264, DAVINCI_ENC_H264,
VIDEO_ES, "Dicas MPEGable H.264/MPEG-4 AVC" },
#endif
#ifdef DAVINCI_HAS_VC1_CODEC
/* vc-1 */
{ VLC_FOURCC('W','V','C','1'), DAVINCI_DEC_VC1, DAVINCI_ENC_VC1,
VIDEO_ES, "Windows Media Video VC1" },
{ VLC_FOURCC('w','v','c','1'), DAVINCI_DEC_VC1, DAVINCI_ENC_VC1,
VIDEO_ES, "Windows Media Video VC1" },
{ VLC_FOURCC('v','c','-','1'), DAVINCI_DEC_VC1, DAVINCI_ENC_VC1,
VIDEO_ES, "Windows Media Video VC1" },
{ VLC_FOURCC('V','C','-','1'), DAVINCI_DEC_VC1, DAVINCI_ENC_VC1,
VIDEO_ES, "Windows Media Video VC1" },
{ VLC_FOURCC('W','M','V','1'), DAVINCI_DEC_VC1, DAVINCI_ENC_VC1,
VIDEO_ES, "Windows Media Video VC1" },
/* WMVA is the VC-1 codec before the standardization proces,
it is not bitstream compatible and deprecated */
{ VLC_FOURCC('W','M','V','A'), DAVINCI_DEC_VC1, DAVINCI_ENC_VC1,
VIDEO_ES, "Windows Media Video Advanced Profile" },
#endif
/*
* Audio Codecs
*/
#ifdef DAVINCI_HAS_MP3_CODEC
/* MPEG Audio layer 1/2/3 */
{ VLC_FOURCC('m','p','g','a'), DAVINIC_DEC_MP3, DAVINIC_NONE,
AUDIO_ES, "MPEG Audio layer 1/2" },
{ VLC_FOURCC('m','p','3',' '), DAVINIC_DEC_MP3, DAVINIC_NONE,
AUDIO_ES, "MPEG Audio layer 1/2/3" },
{ VLC_FOURCC('.','m','p','3'), DAVINIC_DEC_MP3, DAVINIC_NONE,
AUDIO_ES, "MPEG Audio layer 1/2/3" },
{ VLC_FOURCC('M','P','3',' '), DAVINIC_DEC_MP3, DAVINIC_NONE,
AUDIO_ES, "MPEG Audio layer 1/2/3" },
{ VLC_FOURCC('L','A','M','E'), DAVINIC_DEC_MP3, DAVINIC_NONE,
AUDIO_ES, "MPEG Audio layer 1/2/3" },
#endif
#ifdef DAVINCI_HAS_AAC_CODEC
/* AAC audio */
{ VLC_FOURCC('m','p','4','a'), DAVINCI_DEC_AAC, DAVINIC_NONE,
AUDIO_ES, "MPEG AAC Audio" },
{ VLC_FOURCC('a','a','c',' '), DAVINCI_DEC_AAC, DAVINIC_NONE,
AUDIO_ES, "MPEG AAC Audio" },
#endif
{ 0, "", "", 0, "" }
};
bool GetDavinciDecoder( vlc_fourcc_t i_fourcc, int *pi_cat,
const char **ppsz_codec, const char **ppsz_name )
{
for( unsigned i = 0; codecs_table[i].i_fourcc != 0; i++ )
{
if( codecs_table[i].i_fourcc == i_fourcc )
{
if( pi_cat ) *pi_cat = codecs_table[i].i_cat;
if( ppsz_codec ) *ppsz_codec = (char *)codecs_table[i].psz_decoder;
if( ppsz_name ) *ppsz_name = (char *)codecs_table[i].psz_name;
return true;
}
}
return false;
}
bool GetDavinciEncoder( vlc_fourcc_t i_fourcc, int *pi_cat,
const char **ppsz_codec, const char **ppsz_name )
{
for( unsigned i = 0; codecs_table[i].i_fourcc != 0; i++ )
{
if( codecs_table[i].i_fourcc == i_fourcc )
{
if( pi_cat ) *pi_cat = codecs_table[i].i_cat;
if( ppsz_codec ) *ppsz_codec = (char *)codecs_table[i].psz_encoder;
if( ppsz_name ) *ppsz_name = (char *)codecs_table[i].psz_name;
return true;
}
}
return false;
}
bool GetVlcFourcc( const char *ppsz_codec, int *pi_cat,
vlc_fourcc_t *pi_fourcc, const char **ppsz_name )
{
for( unsigned i = 0; codecs_table[i].i_fourcc != 0; i++ )
{
if( strncmp( codecs_table[i].psz_decoder, ppsz_codec, 10 ) == 0 )
{
if( pi_cat ) *pi_cat = codecs_table[i].i_cat;
if( pi_fourcc ) *pi_fourcc = codecs_table[i].i_fourcc;
if( ppsz_name ) *ppsz_name = codecs_table[i].psz_name;
return true;
}
else if( strncmp( codecs_table[i].psz_encoder, ppsz_codec, 10 ) == 0 )
{
if( pi_cat ) *pi_cat = codecs_table[i].i_cat;
if( pi_fourcc ) *pi_fourcc = codecs_table[i].i_fourcc;
if( ppsz_name ) *ppsz_name = codecs_table[i].psz_name;
return true;
}
}
return false;
}
XDAS_Int32 VlcChromaToXdm( vlc_fourcc_t i_chroma )
{
switch( i_chroma )
{
case VLC_FOURCC('I','4','2','0'):
return XDM_YUV_420P;
case VLC_FOURCC('I','4','1','1'):
return XDM_YUV_411P;
case VLC_FOURCC('I','4','2','2'):
return XDM_YUV_422P;
case VLC_FOURCC('I','4','4','4'):
return XDM_YUV_444P;
case VLC_FOURCC('Y','U','Y','V'):
return XDM_YUV_422IBE; /* FIXME ? */
case VLC_FOURCC('U','Y','V','Y'):
return XDM_YUV_422ILE; /* FIXME ? */
case VLC_FOURCC('G','R','E','Y'):
return XDM_GRAY;
#if 0
/* FIXME: not sure about this one */
case VLC_FOURCC('R','V','2','4'):
case VLC_FOURCC('R','V','3','2'):
return XDM_RGB;
#endif
default:
return XDM_CHROMA_NA;
}
}
/*****************************************************************************
* resizer.c: Resize pictures directly into framebuffer (DaVinci specific)
*****************************************************************************
* Copyright (C) 2008 M2X BV
* Copyright (C) 2008-2009 M2X BV
*
* Authors: Rafaël Carré <rcarre@m2x.nl>
* Jean-Paul Saman <jean-paul.saman at m2x dot nl>
*
* 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
......@@ -233,7 +234,7 @@ static void get_coeffs( short coefs[32], unsigned int i_in,
}
}
void Resize( decoder_t *p_dec, vlc_bool_t b_scale, davinci_resizer_t *rsz,
void Resize( decoder_t *p_dec, bool b_scale, davinci_resizer_t *rsz,
davinci_fb_t *fb, XDM_BufDesc out )
{
if( !rsz->i_yuyv )
......@@ -481,7 +482,7 @@ void DavinciClose( davinci_fb_t *fb, davinci_resizer_t *rsz )
for( i = 0 ; i < i_display_size ; i++ )
((uint32_t*)fb->p_map)[i] = 0x10801080;
munmap( fb->p_map, i_display_size );
}
......
/*****************************************************************************
* resizer.c: Resize pictures directly into framebuffer (DaVinci specific)
*****************************************************************************
* Copyright (C) 2008 M2X BV
* Copyright (C) 2008-2009 M2X BV
*
* Authors: Rafaël Carré <rcarre@m2x.nl>
*
......@@ -64,10 +64,10 @@ typedef struct
unsigned int i_out_width;
unsigned int i_out_height;
vlc_bool_t b_direct;
bool b_direct;
} davinci_resizer_t;
void Resize( decoder_t *, vlc_bool_t, davinci_resizer_t *, davinci_fb_t *,
void Resize( decoder_t *, bool, davinci_resizer_t *, davinci_fb_t *,
XDM_BufDesc );
int DavinciInit( decoder_t *, davinci_fb_t *, davinci_resizer_t * );
void DavinciClose( davinci_fb_t *, davinci_resizer_t * );
......
/*****************************************************************************
* video.c: video decoder module using the DaVinci DSP.
*****************************************************************************
* Copyright (C) 2008-2009 M2X BV
* $Id$
*
* Authors: Antoine Cellerier <dionoea at videolan dot org>
* Rafaël Carré <rcarre@m2x.nl>
* Jean-Paul Saman <jean-paul.saman at m2x dot nl>
*
* 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
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include <vlc_codec.h>
#include <vlc_vout.h>
#include <vlc_codecs.h>
#include "davinci.h"
#include <ti/sdo/ce/video/viddec.h>
#include <assert.h>
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static picture_t *DecodeVideoBlock( decoder_t *, block_t ** );
static picture_t *DecodeVideoBlockInner( decoder_t *, block_t **, int );
/*****************************************************************************
* Video decoder
*****************************************************************************/
struct decoder_sys_t
{
char *psz_ti_engine;
Engine_Handle e;
VIDDEC_Handle d;
XDM_BufDesc in;
XDM_BufDesc out;
decoder_t *p_packetizer; /* for avc1 -> h264 */
};
/*****************************************************************************
* 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;
int i_cat;
char *psz_chroma = NULL;
const char *psz_codec = NULL;
const char *psz_namecodec = NULL;
vlc_fourcc_t i_chroma = VLC_FOURCC('U','Y','V','Y');
VIDDEC_Params params;
if( !GetDavinciDecoder( p_dec->fmt_in.i_codec, &i_cat,
&psz_codec, &psz_namecodec ) )
return VLC_EGENERIC;
/* Allocate our private structure */
p_dec->p_sys = (decoder_sys_t *)calloc( 1, sizeof( decoder_sys_t ) );
if( !p_dec->p_sys )
return VLC_ENOMEM;
p_sys = p_dec->p_sys;
p_sys->psz_ti_engine = var_CreateGetString( p_dec, DEC_CFG_PREFIX "engine" );
if( !p_sys->psz_ti_engine )
{
free( p_sys );
return VLC_ENOMEM;
}
/* Initialize the codec engine */
CERuntime_init();
/* Create an engine handle */
p_sys->e = Engine_open( p_sys->psz_ti_engine, NULL /*&Engine_ATTRS*/, &err );
if( err != Engine_EOK )
{
msg_Err( p_dec, "Error while opening engine `%s': %s",
p_sys->psz_ti_engine, ppsz_engine_error[err] );
goto error;
}
PrintAvailableAlgorithms( p_this, p_sys->psz_ti_engine );
/* Get user supplied chroma setting */
psz_chroma = var_CreateGetString( p_dec, DEC_CFG_PREFIX "fourcc" );
if( psz_chroma && strlen( psz_chroma ) == 4 )
{
i_chroma = VLC_FOURCC( psz_chroma[0], psz_chroma[1],
psz_chroma[2], psz_chroma[3] );
msg_Dbg( p_dec, "Forcing output chroma to `%s'", psz_chroma );
}
free( psz_chroma );
/* Create video decoder */
params.size = sizeof( VIDDEC_Params );
/* TODO change the params when HD codecs are available */
params.maxHeight = p_dec->fmt_in.video.i_height ?: 576 /*720*/;
params.maxWidth = p_dec->fmt_in.video.i_width ?: 720 /*1280*/;
/* The application should set the parameters to 0 to use the algorithm's default values. */
params.maxFrameRate = 0;
params.maxBitRate = 0;
msg_Dbg( p_dec, "Creating decoder for %dx%d codec %4.4s in chroma %4.4s",
(int)params.maxWidth, (int)params.maxHeight,
(const char *)&p_dec->fmt_in.i_codec,
(char*)&i_chroma
);
params.dataEndianness = XDM_BYTE;
params.forceChromaFormat = VlcChromaToXdm( i_chroma );
if( params.forceChromaFormat == XDM_CHROMA_NA )
{
msg_Err( p_dec, "Unsupported output chroma (%4.4s).",
(const char *)&i_chroma );
goto error;
}
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) for %s",
psz_codec, psz_namecodec );
goto error;
}
/* Set output properties */
p_dec->fmt_out.i_cat = VIDEO_ES;
p_dec->fmt_out.i_codec =
p_dec->fmt_out.video.i_chroma = i_chroma;
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;
/* DaVinci decoder needs complete frames */
p_dec->b_need_packetized = true;
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;
}
/*****************************************************************************
* 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;
if( p_sys->p_packetizer->p_module )
module_unneed( p_sys->p_packetizer, p_sys->p_packetizer->p_module );
if( p_sys->p_packetizer )
{
vlc_object_detach( p_sys->p_packetizer );
vlc_object_release( p_sys->p_packetizer );
}
/* 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->psz_ti_engine );
free( p_sys );
}
static inline void davinci_CopyXDMPicture( decoder_t *p_dec, picture_t *p_pic, XDM_BufDesc *p_buf )
{
/* Copy stuff to picture here */
assert( p_pic->i_planes == p_buf->numBufs );
for( int i = 0; i < p_pic->i_planes; i++ )
{
plane_t *p = p_pic->p + i;
memcpy( p->p_pixels, p_buf->bufs[i], p->i_pitch * p->i_visible_lines );
}
}
/****************************************************************************
* DecodeBlock: the whole thing
****************************************************************************/
static picture_t *DecodeVideoBlock( decoder_t *p_dec, block_t **pp_block )
{
return DecodeVideoBlockInner( p_dec, pp_block, 0 );
}
static picture_t *DecodeVideoBlockInner( decoder_t *p_dec, block_t **pp_block, int i_extra )
{
decoder_sys_t *p_sys = p_dec->p_sys;
block_t *p_block;
VIDDEC_InArgs in_args;
VIDDEC_OutArgs out_args;
VIDDEC_DynamicParams dparams;
VIDDEC_Status status;
if( !p_sys->p_packetizer &&
p_dec->fmt_in.i_codec == VLC_FOURCC( 'a', 'v', 'c', '1' ) )
{
p_sys->p_packetizer = vlc_object_create( p_dec, sizeof( decoder_t ) );
vlc_object_attach( p_sys->p_packetizer, p_dec );
if( p_sys->p_packetizer )
{
p_sys->p_packetizer->pf_decode_audio = NULL;
p_sys->p_packetizer->pf_decode_video = NULL;
p_sys->p_packetizer->pf_decode_sub = NULL;
p_sys->p_packetizer->pf_packetize = NULL;
es_format_Copy( &p_sys->p_packetizer->fmt_in, &p_dec->fmt_in );
p_sys->p_packetizer->p_module = module_need( p_sys->p_packetizer,
"packetizer", NULL, false );
if( !p_sys->p_packetizer->p_module )
{
vlc_object_detach( p_sys->p_packetizer );
vlc_object_release( p_sys->p_packetizer );
p_sys->p_packetizer = NULL;
}
es_format_Copy( &p_dec->fmt_in, &p_sys->p_packetizer->fmt_out );
}
}
if( !pp_block || !*pp_block ) return NULL;
p_block = *pp_block;
if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
{
block_Release( p_block );
return NULL;
}
if( p_sys->p_packetizer && !i_extra )
{
block_t *p_new_block = p_sys->p_packetizer->pf_packetize( p_sys->p_packetizer, &p_block );
*pp_block = p_block = p_new_block; /* keep reference to packetized blk */
if( !p_block )
return NULL;
}
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( i_extra + p_block->i_buffer,
(size_t)p_sys->in.bufSizes[0] );
in_args.inputID = 1;
/* Setup input buffer */
assert( p_block->i_buffer <= (size_t)p_sys->in.bufSizes[0] );
if( i_extra > 0 )
{
memcpy( p_sys->in.bufs[0], p_dec->fmt_in.p_extra, i_extra );
}
memcpy( p_sys->in.bufs[0] + i_extra, p_block->p_buffer,
in_args.numBytes - i_extra );
#ifdef DEBUG_DAVINCI
msg_Dbg( p_dec, "Frame is %d bytes (%d extra), %dx%d, type %s",
(int)in_args.numBytes, i_extra, (int)status.outputWidth,
(int)status.outputHeight,
status.contentType == IVIDEO_PROGRESSIVE ? "progressive" :
status.contentType == IVIDEO_INTERLACED ? "interlaced" :
"unknown" );
#endif
/* Setup output arguemnts */
out_args.size = sizeof( out_args );
/* Decode the video */
if( VIDDEC_process( p_sys->d, &p_sys->in, &p_sys->out, &in_args, &out_args ) != VIDDEC_EOK )
{
msg_Err( p_dec, "Video decoding failed: %s",
davinci_GetExtendedError(out_args.extendedError ) );
#if 0
if( (unsigned int)out_args.extendedError == 0x402 )
{
printf("frame was %d bytes\n",(unsigned int)in_args.numBytes);
unsigned int j;
for(j=0;j<(unsigned int)in_args.numBytes;j++)
printf("%.2x ",p_sys->in.bufs[0][j]&0xff);
printf("\n");
CERuntime_exit();
abort();
}
#endif
if( i_extra == 0 && p_dec->fmt_in.i_extra > 0 )
{
msg_Dbg( p_dec, "Trying again with p_extra" );
return DecodeVideoBlockInner( p_dec, pp_block, p_dec->fmt_in.i_extra );
}
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( in_args.numBytes > out_args.bytesConsumed )
msg_Err( p_dec, "%d bytes were not consumed", (int)(out_args.bytesConsumed - in_args.numBytes) );
p_block->p_buffer += out_args.bytesConsumed - i_extra;
p_block->i_buffer -= out_args.bytesConsumed - i_extra;
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 */
/* Get a new picture */
picture_t *p_pic = decoder_NewPicture( p_dec );
if( !p_pic )
{
msg_Err( p_dec, "Could not get picture" );
goto error;
}
p_pic->b_progressive = (status.contentType == IVIDEO_INTERLACED) ?
false : true;
#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 1
/* Copy stuff to picture here */
assert( p_pic->i_planes == p_sys->out.numBufs );
for( int 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 );
}
#else
davinci_CopyXDMPicture( p_dec, p_pic, p_sys->out );
#endif
/* */
p_pic->date = p_block->i_pts > 0 ? p_block->i_pts : p_block->i_dts;
if( p_block->i_buffer == 0 )
{
block_Release( p_block );
*pp_block = NULL;
}
return p_pic;
error:
if( p_pic )
decoder_DeletePicture( p_dec, p_pic );
block_Release( p_block );
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