267 linhas
7.4 KiB
C
267 linhas
7.4 KiB
C
#include <VLIB/video_codec.h>
|
|
#include <VLIB/video_quantizer.h>
|
|
#include <VLIB/video_packetizer.h>
|
|
#include <VLIB/Platform/video_utils.h>
|
|
#include <VLIB/Platform/video_config.h>
|
|
|
|
#include <VP_Os/vp_os_malloc.h>
|
|
#include <VP_Os/vp_os_print.h>
|
|
|
|
extern C_RESULT video_utils_init( video_controller_t* controller );
|
|
extern C_RESULT video_utils_close( video_controller_t* controller );
|
|
|
|
extern void uvlc_codec_alloc( video_controller_t* controller );
|
|
extern void uvlc_codec_free( video_controller_t* controller );
|
|
|
|
extern void p263_codec_alloc( video_controller_t* controller );
|
|
extern void p263_codec_free( video_controller_t* controller );
|
|
|
|
extern void p264_codec_alloc( video_controller_t* controller );
|
|
extern void p264_codec_free( video_controller_t* controller );
|
|
|
|
static C_RESULT video_codec_open_private( video_controller_t* controller, codec_type_t codec_type, bool_t keep_stream );
|
|
static C_RESULT video_codec_close_private( video_controller_t* controller, bool_t keep_stream );
|
|
|
|
static C_RESULT video_codec_open_private( video_controller_t* controller, codec_type_t codec_type, bool_t keep_stream )
|
|
{
|
|
C_RESULT res;
|
|
// Data used to initialize macroblock's cache
|
|
int32_t i;
|
|
int16_t* cache;
|
|
video_macroblock_t* mb;
|
|
|
|
// Close any previously allocated codec for this controller
|
|
video_codec_close_private( controller, keep_stream);
|
|
|
|
controller->mode = 0;
|
|
controller->use_me = FALSE;
|
|
controller->do_azq = FALSE;
|
|
controller->aq = 0;
|
|
controller->bq = 0;
|
|
controller->target_bitrate = VLIB_DEFAULT_BITRATE;
|
|
if(codec_type == NULL_CODEC)
|
|
controller->num_frames = 0;
|
|
controller->picture_type = 0;
|
|
controller->width = 0;
|
|
controller->height = 0;
|
|
controller->resolution_changed = FALSE;
|
|
controller->num_blockline = 0;
|
|
controller->mb_blockline = 0;
|
|
controller->blockline = 0;
|
|
controller->picture_complete= 0;
|
|
controller->quant = DEFAULT_QUANTIZATION;
|
|
controller->dquant = 0;
|
|
controller->Qp = 0;
|
|
controller->invQp = 1;
|
|
controller->gobs = NULL;
|
|
controller->cache = NULL;
|
|
controller->codec_type = 0;
|
|
controller->video_codec = NULL;
|
|
|
|
if( controller->blockline_cache == NULL )
|
|
{
|
|
// We alloc two buffers to be compatible with an asynchronous DCT
|
|
// When a DCT will be performed on one buffer, we will be able to use the other for caching or computing purpose
|
|
// DCT_BUFFER_SIZE = MAX_NUM_MACRO_BLOCKS_PER_CALL * 6 * MCU_BLOCK_SIZE
|
|
controller->blockline_cache = (int16_t*)vp_os_aligned_malloc( 2*DCT_BUFFER_SIZE*sizeof(int16_t), VLIB_ALLOC_ALIGN );
|
|
}
|
|
if (controller->cache_mbs == NULL)
|
|
{
|
|
controller->cache_mbs = vp_os_malloc( 2 * MAX_NUM_MACRO_BLOCKS_PER_CALL * sizeof(video_macroblock_t) );
|
|
mb = &controller->cache_mbs[0];
|
|
cache = controller->blockline_cache;
|
|
for(i = 2*MAX_NUM_MACRO_BLOCKS_PER_CALL; i > 0; i-- )
|
|
{
|
|
mb->data = cache;
|
|
cache += MCU_BLOCK_SIZE*6;
|
|
mb ++;
|
|
}
|
|
}
|
|
|
|
if (keep_stream == FALSE)
|
|
video_packetizer_init( controller );
|
|
video_quantizer_init( controller );
|
|
|
|
switch( codec_type )
|
|
{
|
|
case UVLC_CODEC:
|
|
uvlc_codec_alloc( controller );
|
|
break;
|
|
|
|
case P263_CODEC:
|
|
p263_codec_alloc( controller );
|
|
break;
|
|
|
|
case P264_CODEC:
|
|
p264_codec_alloc( controller );
|
|
break;
|
|
|
|
default:
|
|
controller->video_codec = NULL;
|
|
break;
|
|
}
|
|
|
|
if( controller->video_codec != NULL )
|
|
{
|
|
controller->codec_type = codec_type;
|
|
res = C_OK;
|
|
}
|
|
else
|
|
{
|
|
res = C_FAIL;
|
|
}
|
|
|
|
video_utils_init( controller );
|
|
|
|
return res;
|
|
}
|
|
|
|
C_RESULT video_codec_open( video_controller_t* controller, codec_type_t codec_type )
|
|
{
|
|
return video_codec_open_private(controller, codec_type, FALSE );
|
|
}
|
|
|
|
static C_RESULT video_codec_close_private( video_controller_t* controller, bool_t keep_stream )
|
|
{
|
|
video_utils_close( controller );
|
|
|
|
if( controller->blockline_cache != NULL )
|
|
{
|
|
vp_os_aligned_free( controller->blockline_cache );
|
|
controller->blockline_cache = NULL;
|
|
}
|
|
|
|
if (controller->cache_mbs != NULL)
|
|
{
|
|
vp_os_free( controller->cache_mbs );
|
|
controller->cache_mbs = NULL;
|
|
}
|
|
|
|
|
|
if( keep_stream == FALSE && controller->in_stream.bytes != NULL )
|
|
video_packetizer_close( controller );
|
|
|
|
switch( controller->codec_type )
|
|
{
|
|
case UVLC_CODEC:
|
|
uvlc_codec_free( controller );
|
|
break;
|
|
|
|
case P263_CODEC:
|
|
p263_codec_free( controller );
|
|
break;
|
|
|
|
case P264_CODEC:
|
|
p264_codec_free( controller );
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
// Cleanup caches
|
|
video_controller_cleanup( controller );
|
|
|
|
return C_OK;
|
|
}
|
|
|
|
C_RESULT video_codec_close ( video_controller_t* controller)
|
|
{
|
|
return video_codec_close_private(controller, FALSE);
|
|
}
|
|
|
|
C_RESULT video_codec_type_select(video_controller_t* controller, video_stream_t* stream)
|
|
{
|
|
C_RESULT res = C_OK;
|
|
uint32_t codec_type = 0;
|
|
video_align8( stream );
|
|
video_peek_data( stream, &codec_type, 22 );
|
|
// extract codec tag
|
|
//codec_type = codec_type>>5;
|
|
|
|
if (codec_type != controller->codec_type)
|
|
{
|
|
PRINT("VLIB new codec %d\n",codec_type);
|
|
// video codec has changed, load a new codec
|
|
res = video_codec_open_private( controller, codec_type, TRUE );
|
|
|
|
}
|
|
return res;
|
|
}
|
|
|
|
C_RESULT video_encode_picture( video_controller_t* controller, const vp_api_picture_t* picture, bool_t* got_image )
|
|
{
|
|
vp_api_picture_t blockline = { 0 };
|
|
|
|
controller->mode = VIDEO_ENCODE;
|
|
|
|
video_controller_set_format( controller, picture->width, picture->height );
|
|
|
|
blockline = *picture;
|
|
blockline.height = MB_HEIGHT_Y;
|
|
blockline.complete = 1;
|
|
blockline.vision_complete = 0;
|
|
|
|
// Reset internal stream for new blockline/picture
|
|
controller->in_stream.used = 0;
|
|
controller->in_stream.index = 0;
|
|
|
|
while( !controller->picture_complete )
|
|
{
|
|
video_encode_blockline( controller, &blockline, blockline.blockline == (controller->num_blockline-1) );
|
|
|
|
blockline.y_buf += MB_HEIGHT_Y * picture->y_line_size;
|
|
blockline.cb_buf += MB_HEIGHT_C * picture->cb_line_size;
|
|
blockline.cr_buf += MB_HEIGHT_C * picture->cr_line_size;
|
|
|
|
blockline.blockline++;
|
|
}
|
|
|
|
if( picture->complete )
|
|
{
|
|
video_write_data( &controller->in_stream, 0, controller->in_stream.length+1 );
|
|
controller->in_stream.length = 32;
|
|
controller->picture_complete = 0;
|
|
*got_image = TRUE;
|
|
}
|
|
|
|
return C_OK;
|
|
}
|
|
|
|
C_RESULT video_decode_picture( video_controller_t* controller, vp_api_picture_t* picture, video_stream_t* ex_stream, bool_t* got_image )
|
|
{
|
|
vp_api_picture_t blockline = { 0 };
|
|
C_RESULT decodeOk = C_OK;
|
|
|
|
controller->mode = VIDEO_DECODE; // mandatory because of video_cache_stream
|
|
|
|
blockline = *picture;
|
|
blockline.height = MB_HEIGHT_Y;
|
|
blockline.complete = 1;
|
|
blockline.vision_complete = 0;
|
|
|
|
while( VP_SUCCEEDED(video_cache_stream( controller, ex_stream )) &&
|
|
C_OK == decodeOk)
|
|
{
|
|
video_codec_type_select(controller,ex_stream); // to be verified
|
|
decodeOk = video_decode_blockline( controller, &blockline, got_image );
|
|
}
|
|
|
|
return decodeOk;
|
|
}
|
|
|
|
|
|
C_RESULT video_decode_blockline( video_controller_t* controller, vp_api_picture_t* blockline, bool_t* got_image )
|
|
{
|
|
C_RESULT isCodecOK = video_codec_type_select(controller,&controller->in_stream);
|
|
if (C_OK == isCodecOK &&
|
|
NULL != controller->video_codec)
|
|
{
|
|
return controller->video_codec->decode_blockline( controller, blockline, got_image );
|
|
}
|
|
else
|
|
{
|
|
return C_FAIL;
|
|
}
|
|
}
|