X-Git-Url: http://git.maemo.org/git/?a=blobdiff_plain;ds=sidebyside;f=mardrone%2FARDrone_SDK_Version_1_8_20110726%2FARDroneLib%2FVLIB%2Fvideo_codec.c;fp=mardrone%2FARDrone_SDK_Version_1_8_20110726%2FARDroneLib%2FVLIB%2Fvideo_codec.c;h=94fec70b07d8d1e0d63531fa19e2ff4417ff5ddc;hb=9ec9bc13b75d30bc45535c54a652934debfcea92;hp=0000000000000000000000000000000000000000;hpb=ae0a3c2dc0898400aca0dd6b439c5db8044db7b2;p=mardrone diff --git a/mardrone/ARDrone_SDK_Version_1_8_20110726/ARDroneLib/VLIB/video_codec.c b/mardrone/ARDrone_SDK_Version_1_8_20110726/ARDroneLib/VLIB/video_codec.c new file mode 100644 index 0000000..94fec70 --- /dev/null +++ b/mardrone/ARDrone_SDK_Version_1_8_20110726/ARDroneLib/VLIB/video_codec.c @@ -0,0 +1,260 @@ +#include +#include +#include +#include +#include + +#include +#include + +#ifdef _ELINUX +#include "dma_malloc.h" +#define vp_os_aligned_malloc(A,B) dma_malloc(A) +#define vp_os_aligned_free(A) dma_free(A) +#endif + +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; + 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) +{ + 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 + video_codec_open_private( controller, codec_type, TRUE ); + + } + return C_OK; +} + +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 }; + + 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 )) ) + { + video_codec_type_select(controller,ex_stream); // to be verified + video_decode_blockline( controller, &blockline, got_image ); + } + + return C_OK; +} + + +C_RESULT video_decode_blockline( video_controller_t* controller, vp_api_picture_t* blockline, bool_t* got_image ) +{ + video_codec_type_select(controller,&controller->in_stream); + return controller->video_codec->decode_blockline( controller, blockline, got_image ); +}