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

Use 'special' 'DaVinci compliant' memory buffers for the decoder. I haven't...

Use 'special' 'DaVinci compliant' memory buffers for the decoder. I haven't been able to get it to work properly but at least I got the correct video dimensions a few times.
Signed-off-by: Jean-Paul Saman's avatarJean-Paul Saman <jean-paul.saman@m2x.nl>
parent 3e8cb71c
......@@ -29,9 +29,12 @@
#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/CERuntime.h>
#define DEBUG_DAVINCI
/*****************************************************************************
*
*****************************************************************************/
......@@ -39,15 +42,21 @@ struct decoder_sys_t
{
Engine_Handle e;
VIDDEC_Handle d;
XDM_BufDesc in;
XDM_BufDesc out;
};
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int OpenVideoDecoder ( vlc_object_t * );
static void CloseVideoDecoder ( vlc_object_t * );
static int OpenVideoDecoder( vlc_object_t * );
static void CloseVideoDecoder( vlc_object_t * );
static picture_t *DecodeVideoBlock ( decoder_t *, block_t ** );
static picture_t *DecodeVideoBlock( decoder_t *, block_t ** );
static int AllocateBuffer( decoder_t *, XDAS_Int32, XDAS_Int32 *, XDM_BufDesc * );
static void FreeBuffer( XDM_BufDesc * );
/*****************************************************************************
* Module descriptor
......@@ -87,21 +96,23 @@ static int OpenVideoDecoder( vlc_object_t *p_this )
decoder_t *p_dec = (decoder_t*)p_this;
decoder_sys_t *p_sys;
Engine_Error err;
//IVIDEO_Format //i_format;
//IVIDEO_Format i_format;
const char *psz_codec;
VIDDEC_Params params;
switch( p_dec->fmt_in.i_codec )
{
/* FOURCC codes copied from libavcodec module */
case VLC_FOURCC('m','p','g','v'):
#if 0
case VLC_FOURCC('m','p','e','g'):
case VLC_FOURCC('m','p','g','1'):
case VLC_FOURCC('P','I','M','1'):
//i_format = IVIDEO_MPEG1;
psz_codec = "mpegdec"; /* FIXME */
break;
#endif
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'):
......@@ -181,6 +192,7 @@ static int OpenVideoDecoder( vlc_object_t *p_this )
psz_codec = "h264dec";
break;
#if 0
case VLC_FOURCC('W','V','C','1'):
case VLC_FOURCC('w','v','c','1'):
//i_format = IVIDEO_VC1SP;
......@@ -188,6 +200,7 @@ static int OpenVideoDecoder( vlc_object_t *p_this )
//i_format = IVIDEO_VC1AP;
psz_codec = "vc1dec"; /* FIXME */
break;
#endif
default:
return VLC_EGENERIC;
......@@ -215,14 +228,16 @@ static int OpenVideoDecoder( vlc_object_t *p_this )
/* Create video decoder */
params.size = sizeof( VIDDEC_Params );
params.maxHeight = p_dec->fmt_in.video.i_height;
params.maxWidth = p_dec->fmt_in.video.i_width;
params.maxFrameRate = 30 * 1000; /* in frames per 1000 seconds */
params.maxBitRate = 10 * 1000 * 1000; /* in bits per second */
params.dataEndianness = XDM_LE_32;
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;
/* Or do we want to output directly to XDM_YUV422ILE as that's what the
//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 )
{
......@@ -231,16 +246,26 @@ static int OpenVideoDecoder( vlc_object_t *p_this )
}
/* 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:
......@@ -264,7 +289,7 @@ static void CloseVideoDecoder( vlc_object_t *p_this )
Engine_close( p_sys->e );
/* Exit the codec engine */
/* FIXME: not available in ticel it seems CERuntime_exit(); */
CERuntime_exit();
free( p_sys );
}
......@@ -277,61 +302,189 @@ 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;
XDM_BufDesc in;
XDM_BufDesc out;
VIDDEC_InArgs in_args;
VIDDEC_OutArgs out_args;
VIDDEC_DynamicParams dparams;
VIDDEC_Status status;
int i;
if( !pp_block || !*pp_block ) return NULL;
memset( &in, 0, sizeof( in ) );
memset( &out, 0, sizeof( out ) );
#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 buffer */
in.numBufs = 1;
in.bufs = (XDAS_Int8 **)malloc( in.numBufs * sizeof( XDAS_Int8 * ) );
in.bufSizes = (XDAS_Int32 *)malloc( in.numBufs * sizeof( XDAS_Int32 ) );
in.bufs[0] = p_block->p_buffer;
in.bufSizes[0] = p_block->i_buffer;
if( p_block->i_buffer > p_sys->in.bufSizes[0] )
{
#ifdef DEBUG_DAVINCI
msg_Dbg( p_dec, "Woah! Not enough room to store the whole block" );
#endif
memcpy( p_sys->in.bufs[0], p_block->p_buffer, p_sys->in.bufSizes[0] );
}
else
{
memcpy( p_sys->in.bufs[0], p_block->p_buffer, p_block->i_buffer );
}
/* Setup input arguments */
in_args.size = sizeof( in_args );
in_args.numBytes = p_block->i_buffer;
in_args.numBytes = __MIN( p_block->i_buffer, p_sys->in.bufSizes[0] );
in_args.inputID = 0; /* FIXME */
/* Get a new picture */
p_pic = p_dec->pf_vout_buffer_new( p_dec );
if( !p_pic ) goto error;
#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." );
/* Setup output buffer */
/* XXX: Not sure about this one */
out.numBufs = p_pic->i_planes;
out.bufs = (XDAS_Int8 **)malloc( out.numBufs * sizeof( XDAS_Int8 * ) );
out.bufSizes = (XDAS_Int32 *)malloc( out.numBufs * sizeof( XDAS_Int32 ) );
for( i = 0; i < p_pic->i_planes; i++ )
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 )
{
out.bufs[i] = p_pic->p[i].p_pixels;
out.bufSizes[i] = p_pic->p[i].i_lines * p_pic->p[i].i_pitch;
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 */
if( VIDDEC_process( p_sys->d, &in, &out, &in_args, &out_args )
== VIDDEC_EFAIL )
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" );
msg_Err( p_dec, "Video decoding failed (Error code: %ld, Extended erorr: %lx)", i, out_args.extendedError );
goto error;
}
#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:
......@@ -356,18 +509,88 @@ static picture_t *DecodeVideoBlock( decoder_t *p_dec, block_t **pp_block )
msg_Dbg( p_dec, "Interlaced B frame" );
break;
default:
msg_Dbg( p_dec, "Other frame type: %d", out_args.decodedFrameType );
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;
error:
if( p_pic && p_pic->pf_release ) p_pic->pf_release( p_pic );
free( in.bufs );
free( in.bufSizes );
free( out.bufs );
free( out.bufSizes );
block_Release( p_block );
#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;
}
static int AllocateBuffer( decoder_t *p_dec, XDAS_Int32 i_num,
XDAS_Int32 *pi_sizes, XDM_BufDesc *buf )
{
int i;
msg_Info( p_dec, "Allocating buffers:" );
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++ )
{
msg_Info( p_dec, " %d: size %d Bytes", i, (int)pi_sizes[i] );
buf->bufSizes[i] = pi_sizes[i];
buf->bufs[i] = Memory_contigAlloc( pi_sizes[i], Memory_DEFAULTALIGNMENT );
if( !buf->bufs[i] )
{
msg_Err( p_dec, "Failed to allocate buffer" );
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 )
{
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;
}
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