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 @@ ...@@ -29,9 +29,12 @@
#include <gnu/targets/std.h> #include <gnu/targets/std.h>
#include <xdc/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/viddec.h>
#include <ti/sdo/ce/CERuntime.h> #include <ti/sdo/ce/CERuntime.h>
#define DEBUG_DAVINCI
/***************************************************************************** /*****************************************************************************
* *
*****************************************************************************/ *****************************************************************************/
...@@ -39,15 +42,21 @@ struct decoder_sys_t ...@@ -39,15 +42,21 @@ struct decoder_sys_t
{ {
Engine_Handle e; Engine_Handle e;
VIDDEC_Handle d; VIDDEC_Handle d;
XDM_BufDesc in;
XDM_BufDesc out;
}; };
/***************************************************************************** /*****************************************************************************
* Local prototypes * Local prototypes
*****************************************************************************/ *****************************************************************************/
static int OpenVideoDecoder ( vlc_object_t * ); static int OpenVideoDecoder( vlc_object_t * );
static void CloseVideoDecoder ( 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 * Module descriptor
...@@ -87,21 +96,23 @@ static int OpenVideoDecoder( vlc_object_t *p_this ) ...@@ -87,21 +96,23 @@ static int OpenVideoDecoder( vlc_object_t *p_this )
decoder_t *p_dec = (decoder_t*)p_this; decoder_t *p_dec = (decoder_t*)p_this;
decoder_sys_t *p_sys; decoder_sys_t *p_sys;
Engine_Error err; Engine_Error err;
//IVIDEO_Format //i_format; //IVIDEO_Format i_format;
const char *psz_codec; const char *psz_codec;
VIDDEC_Params params; VIDDEC_Params params;
switch( p_dec->fmt_in.i_codec ) switch( p_dec->fmt_in.i_codec )
{ {
/* FOURCC codes copied from libavcodec module */ /* 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','e','g'):
case VLC_FOURCC('m','p','g','1'): case VLC_FOURCC('m','p','g','1'):
case VLC_FOURCC('P','I','M','1'): case VLC_FOURCC('P','I','M','1'):
//i_format = IVIDEO_MPEG1; //i_format = IVIDEO_MPEG1;
psz_codec = "mpegdec"; /* FIXME */ psz_codec = "mpegdec"; /* FIXME */
break; break;
#endif
case VLC_FOURCC('m','p','g','v'):
case VLC_FOURCC('m','p','2','v'): case VLC_FOURCC('m','p','2','v'):
case VLC_FOURCC('M','P','E','G'): case VLC_FOURCC('M','P','E','G'):
case VLC_FOURCC('m','p','g','2'): case VLC_FOURCC('m','p','g','2'):
...@@ -181,6 +192,7 @@ static int OpenVideoDecoder( vlc_object_t *p_this ) ...@@ -181,6 +192,7 @@ static int OpenVideoDecoder( vlc_object_t *p_this )
psz_codec = "h264dec"; psz_codec = "h264dec";
break; break;
#if 0
case VLC_FOURCC('W','V','C','1'): case VLC_FOURCC('W','V','C','1'):
case VLC_FOURCC('w','v','c','1'): case VLC_FOURCC('w','v','c','1'):
//i_format = IVIDEO_VC1SP; //i_format = IVIDEO_VC1SP;
...@@ -188,6 +200,7 @@ static int OpenVideoDecoder( vlc_object_t *p_this ) ...@@ -188,6 +200,7 @@ static int OpenVideoDecoder( vlc_object_t *p_this )
//i_format = IVIDEO_VC1AP; //i_format = IVIDEO_VC1AP;
psz_codec = "vc1dec"; /* FIXME */ psz_codec = "vc1dec"; /* FIXME */
break; break;
#endif
default: default:
return VLC_EGENERIC; return VLC_EGENERIC;
...@@ -215,14 +228,16 @@ static int OpenVideoDecoder( vlc_object_t *p_this ) ...@@ -215,14 +228,16 @@ static int OpenVideoDecoder( vlc_object_t *p_this )
/* Create video decoder */ /* Create video decoder */
params.size = sizeof( VIDDEC_Params ); params.size = sizeof( VIDDEC_Params );
params.maxHeight = p_dec->fmt_in.video.i_height; params.maxHeight = p_dec->fmt_in.video.i_height?:576;
params.maxWidth = p_dec->fmt_in.video.i_width; params.maxWidth = p_dec->fmt_in.video.i_width?:720;
params.maxFrameRate = 30 * 1000; /* in frames per 1000 seconds */ params.maxFrameRate = 0; /* in frames per 1000 seconds */
params.maxBitRate = 10 * 1000 * 1000; /* in bits per second */ params.maxBitRate = 0; /* in bits per second */
params.dataEndianness = XDM_LE_32; params.dataEndianness = XDM_BYTE;//LE_32;
params.forceChromaFormat = XDM_YUV_420P; 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? */ * frame buffer likes? */
p_sys->d = VIDDEC_create( p_sys->e, (String)psz_codec, &params ); p_sys->d = VIDDEC_create( p_sys->e, (String)psz_codec, &params );
if( !p_sys->d ) if( !p_sys->d )
{ {
...@@ -231,16 +246,26 @@ static int OpenVideoDecoder( vlc_object_t *p_this ) ...@@ -231,16 +246,26 @@ static int OpenVideoDecoder( vlc_object_t *p_this )
} }
/* Set output properties */ /* 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_cat = VIDEO_ES;
p_dec->fmt_out.i_codec = VLC_FOURCC('I','4','2','0'); 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_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_height = p_dec->fmt_in.video.i_height;
p_dec->fmt_out.video.i_aspect = p_dec->fmt_in.video.i_aspect; p_dec->fmt_out.video.i_aspect = p_dec->fmt_in.video.i_aspect;
/* Set callbacks */ /* Set callbacks */
p_dec->pf_decode_video = DecodeVideoBlock; p_dec->pf_decode_video = DecodeVideoBlock;
#ifdef DEBUG_DAVINCI
msg_Info( p_dec, "Woohoo!" );
#endif
return VLC_SUCCESS; return VLC_SUCCESS;
error: error:
...@@ -264,7 +289,7 @@ static void CloseVideoDecoder( vlc_object_t *p_this ) ...@@ -264,7 +289,7 @@ static void CloseVideoDecoder( vlc_object_t *p_this )
Engine_close( p_sys->e ); Engine_close( p_sys->e );
/* Exit the codec engine */ /* Exit the codec engine */
/* FIXME: not available in ticel it seems CERuntime_exit(); */ CERuntime_exit();
free( p_sys ); free( p_sys );
} }
...@@ -277,61 +302,189 @@ static picture_t *DecodeVideoBlock( decoder_t *p_dec, block_t **pp_block ) ...@@ -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; decoder_sys_t *p_sys = p_dec->p_sys;
block_t *p_block; block_t *p_block;
picture_t *p_pic = NULL; picture_t *p_pic = NULL;
XDM_BufDesc in;
XDM_BufDesc out;
VIDDEC_InArgs in_args; VIDDEC_InArgs in_args;
VIDDEC_OutArgs out_args; VIDDEC_OutArgs out_args;
VIDDEC_DynamicParams dparams;
VIDDEC_Status status;
int i; int i;
if( !pp_block || !*pp_block ) return NULL; if( !pp_block || !*pp_block ) return NULL;
memset( &in, 0, sizeof( in ) ); #ifdef DEBUG_DAVINCI
memset( &out, 0, sizeof( out ) ); msg_Err( p_dec, "DecodeVideoBlock starts now!" );
#endif
memset( &in_args, 0, sizeof( in_args ) ); memset( &in_args, 0, sizeof( in_args ) );
memset( &out_args, 0, sizeof( out_args ) ); memset( &out_args, 0, sizeof( out_args ) );
p_block = *pp_block; 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 */ /* Setup input buffer */
in.numBufs = 1; if( p_block->i_buffer > p_sys->in.bufSizes[0] )
in.bufs = (XDAS_Int8 **)malloc( in.numBufs * sizeof( XDAS_Int8 * ) ); {
in.bufSizes = (XDAS_Int32 *)malloc( in.numBufs * sizeof( XDAS_Int32 ) ); #ifdef DEBUG_DAVINCI
in.bufs[0] = p_block->p_buffer; msg_Dbg( p_dec, "Woah! Not enough room to store the whole block" );
in.bufSizes[0] = p_block->i_buffer; #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 */ /* Setup input arguments */
in_args.size = sizeof( in_args ); 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 */ in_args.inputID = 0; /* FIXME */
/* Get a new picture */ #if 0
p_pic = p_dec->pf_vout_buffer_new( p_dec ); /* This obviously doesn't work (at least for mpeg2 video */
if( !p_pic ) goto error; if( status.outputHeight <= 0 || status.outputWidth <= 0 )
/* 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++ )
{ {
out.bufs[i] = p_pic->p[i].p_pixels; msg_Dbg( p_dec, "Output frame size unknown. Parsing header." );
out.bufSizes[i] = p_pic->p[i].i_lines * p_pic->p[i].i_pitch;
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 */ /* Setup output arguemnts */
out_args.size = sizeof( out_args ); out_args.size = sizeof( out_args );
/* That was easy :p */
/* Decode the video */ /* Decode the video */
if( VIDDEC_process( p_sys->d, &in, &out, &in_args, &out_args ) if( ( i = VIDDEC_process( p_sys->d, &p_sys->in, &p_sys->out, &in_args, &out_args ) )
== VIDDEC_EFAIL ) != 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; 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 */ /* Copy stuff to picture here */
#ifdef DEBUG_DAVINCI
switch( out_args.decodedFrameType ) switch( out_args.decodedFrameType )
{ {
case IVIDEO_NA_FRAME: case IVIDEO_NA_FRAME:
...@@ -356,18 +509,88 @@ static picture_t *DecodeVideoBlock( decoder_t *p_dec, block_t **pp_block ) ...@@ -356,18 +509,88 @@ static picture_t *DecodeVideoBlock( decoder_t *p_dec, block_t **pp_block )
msg_Dbg( p_dec, "Interlaced B frame" ); msg_Dbg( p_dec, "Interlaced B frame" );
break; break;
default: 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; 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; 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: error:
if( p_pic && p_pic->pf_release ) p_pic->pf_release( p_pic ); if( p_pic && p_pic->pf_release )
free( in.bufs ); p_pic->pf_release( p_pic );
free( in.bufSizes ); block_Release( p_block ); /* Do we really need this everytime? (like if buffer memory allocation fails we could keep the block) */
free( out.bufs ); return NULL;
free( out.bufSizes ); }
block_Release( p_block );
return p_pic; 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