X-Git-Url: http://git.maemo.org/git/?p=mardrone;a=blobdiff_plain;f=mardrone%2FARDrone_SDK_Version_1_8_20110726%2FARDroneLib%2FVLIB%2FP263%2Fp263_codec.c;fp=mardrone%2FARDrone_SDK_Version_1_8_20110726%2FARDroneLib%2FVLIB%2FP263%2Fp263_codec.c;h=5c0fa458fc6b16459c6cceb6777aedab6fa60651;hp=0000000000000000000000000000000000000000;hb=9ec9bc13b75d30bc45535c54a652934debfcea92;hpb=ae0a3c2dc0898400aca0dd6b439c5db8044db7b2 diff --git a/mardrone/ARDrone_SDK_Version_1_8_20110726/ARDroneLib/VLIB/P263/p263_codec.c b/mardrone/ARDrone_SDK_Version_1_8_20110726/ARDroneLib/VLIB/P263/p263_codec.c new file mode 100644 index 0000000..5c0fa45 --- /dev/null +++ b/mardrone/ARDrone_SDK_Version_1_8_20110726/ARDroneLib/VLIB/P263/p263_codec.c @@ -0,0 +1,399 @@ +#include +#include + +#include +#include +#include +#include +#include "p263_codec.h" + +#include +#include + +static int32_t first_init = 1; + +const p263_codec_t p263_codec = { + p263_encode_blockline, + p263_decode_blockline, + p263_update, + p263_cache, + { 0 } +}; + +void p263_codec_alloc( video_controller_t* controller ) +{ + video_codec_t* video_codec; + + if( first_init == 1 ) + { + vlc_mcbpc_ipictures_tree = huffman_alloc(VLC_MCBPC_IPICTURES_NUM, VLC_MCBPC_IPICTURES_MAX_LENGTH); + huffman_add_codes( vlc_mcbpc_ipictures_tree, &vlc_mcbpc_ipictures[0], VLC_MCBPC_IPICTURES_NUM ); + huffman_sort_codes( vlc_mcbpc_ipictures_tree ); + + vlc_cbpy_standard_tree = huffman_alloc(VLC_CBPY_STANDARD_NUM, VLC_CBPY_STANDARD_MAX_LENGTH); + huffman_add_codes( vlc_cbpy_standard_tree, &vlc_cbpy_standard[0], VLC_CBPY_STANDARD_NUM ); + huffman_sort_codes( vlc_cbpy_standard_tree ); + + vlc_tcoeff_tree = huffman_alloc(VLC_TCOEFF_NUM, VLC_TCOEFF_MAX_LENGTH); + huffman_add_codes( vlc_tcoeff_tree, &vlc_tcoeff[0], VLC_TCOEFF_NUM ); + huffman_sort_codes( vlc_tcoeff_tree ); + + mvd_vlc_tree = huffman_alloc(MVD_VLC_NUM, MVD_VLC_MAX_LENGTH); + huffman_add_codes( mvd_vlc_tree, &mvd_vlc[0], MVD_VLC_NUM ); + huffman_sort_codes( mvd_vlc_tree ); + + first_init = 0; + } + + video_codec = (video_codec_t*) vp_os_malloc( sizeof(p263_codec) ); + + vp_os_memcpy(video_codec, &p263_codec, sizeof(p263_codec)); + + controller->video_codec = video_codec; +} + +void p263_codec_free( video_controller_t* controller ) +{ + p263_codec_t* p263_codec = (p263_codec_t*) controller->video_codec; + + vp_os_free( p263_codec ); +} + +static INLINE video_macroblock_t* p263_unquantize_idct( video_controller_t* controller, video_macroblock_t* mb, int32_t num_macro_blocks ) +{ + video_unquantize( controller, mb, num_macro_blocks ); + video_idct_compute(mb->data, mb->data, num_macro_blocks); + + return mb+num_macro_blocks; +} + +C_RESULT p263_packet( video_controller_t* controller ) +{ + uint32_t start_code = 0, num_mb; + bool_t picture_complete; + video_stream_t* stream = &controller->in_stream; + video_macroblock_t* mb; + p263_gob_layer_t* gob; + p263_codec_t* p263_codec = (p263_codec_t*) controller->video_codec; + p263_picture_layer_t* picture_layer = &p263_codec->picture_layer; + + switch( controller->mode ) + { + case VIDEO_ENCODE: + break; + + case VIDEO_DECODE: + // TODO Fill first gob with picture header's data + video_align8( stream ); + video_read_data( stream, &start_code, 22 ); + + controller->blockline = start_code & 0x1F; + start_code &= ~0x1F; // TODO Check if compiler use arm instruction bic + + if( start_code == PICTURE_START_CODE ) + { + picture_complete = TRUE; + if( controller->blockline == 0 ) + { + picture_complete = FALSE; + p263_read_picture_layer( controller, stream ); + + picture_layer->gobs = (p263_gob_layer_t*) controller->gobs; + gob = &picture_layer->gobs[controller->blockline]; + + gob->gquant = picture_layer->pquant; + } + else if( controller->blockline < 0x1F ) + { + picture_complete = FALSE; + p263_read_gob_layer( controller, stream ); + } + + controller->picture_complete = picture_complete; + + if( picture_complete != TRUE ) + { + num_mb = controller->mb_blockline; + mb = picture_layer->gobs[controller->blockline].macroblocks; + + for( ; num_mb > 0; num_mb-- ) + { + p263_read_mb_layer( controller, stream, mb++ ); + } + } + } + break; + + default: + break; + } + + return C_OK; +} + +C_RESULT p263_encode_blockline( video_controller_t* controller, const vp_api_picture_t* blockline, bool_t picture_complete ) +{ + return C_OK; +} + +C_RESULT p263_decode_blockline( video_controller_t* controller, vp_api_picture_t* picture, bool_t* got_image ) +{ + video_codec_t* video_codec; + vp_api_picture_t blockline = { 0 }; + int16_t *in = NULL; + int32_t num_macro_blocks = 0; + video_macroblock_t* macroblock = NULL; + video_picture_context_t blockline_ctx; + video_gob_t* gobs; + + controller->mode = VIDEO_DECODE; + video_codec = controller->video_codec; + + blockline = *picture; + blockline.height = MB_HEIGHT_Y; + blockline.complete = 1; + blockline.vision_complete = 0; + + picture->complete = controller->picture_complete; + + blockline_ctx.y_woffset = blockline.y_line_size; + blockline_ctx.c_woffset = blockline.cb_line_size; + blockline_ctx.y_hoffset = blockline.y_line_size * MCU_HEIGHT; + + // At least a complete blockline is found + while( !controller->picture_complete && controller->in_stream.index < (controller->in_stream.used >> 2) ) + { + p263_packet( controller ); + + if( !controller->picture_complete ) + { + blockline.blockline = controller->blockline; + + blockline_ctx.y_src = picture->y_buf + blockline.blockline * MB_HEIGHT_Y * picture->y_line_size; + blockline_ctx.cb_src = picture->cb_buf + blockline.blockline * MB_HEIGHT_C * picture->cb_line_size; + blockline_ctx.cr_src = picture->cr_buf + blockline.blockline * MB_HEIGHT_C * picture->cr_line_size; + + picture->blockline = controller->blockline; + num_macro_blocks = controller->mb_blockline; + + gobs = &controller->gobs[controller->blockline]; + macroblock = &controller->gobs[controller->blockline].macroblocks[0]; + in = macroblock->data; + + if( gobs->quant != controller->quant ) + { + controller->quant = gobs->quant; + video_quantizer_update( controller ); + } + + while( num_macro_blocks > MAX_NUM_MACRO_BLOCKS_PER_CALL ) + { + // These two calls are merged to allow specific optimization in case of a software decoder + macroblock = p263_unquantize_idct( controller, macroblock, MAX_NUM_MACRO_BLOCKS_PER_CALL ); + + num_macro_blocks -= MAX_NUM_MACRO_BLOCKS_PER_CALL; + } + + // These two calls are merged to allow specific optimization in case of a software decoder + p263_unquantize_idct( controller, macroblock, num_macro_blocks ); + + video_blockline_from_macro_blocks(&blockline_ctx, in, controller->mb_blockline, picture->format); + + // Update controller according to video statistics + video_controller_update( controller, controller->picture_complete ); + + // Perform motion compensation + if( controller->use_me == TRUE ) + { + } + } + } + + if( controller->picture_complete ) + { + picture->complete = controller->picture_complete; + picture->blockline = 0; + + controller->picture_complete = 0; + controller->in_stream.length = 32; + //controller->num_frames++; + + *got_image = TRUE; + } + else + { + controller->in_stream.used = 0; + controller->in_stream.index = 0; + } + + return C_OK; +} + +C_RESULT p263_update( video_controller_t* controller ) +{ + return C_OK; +} + +static C_RESULT p263_flush_stream( video_stream_t* out, video_stream_t* in ) +{ + // They are still data in cache + // Always copy a number of bytes that is a times of 4. + // Only for the last copy, we can have exactly the number of bytes left + int32_t offset, size; + uint32_t out_stream_size; + + if( in->length != 32 ) + { + // flush & reset internal stream + video_write_data( in, 0, in->length+1 ); + in->length = 32; + } + + out_stream_size = out->size & ~3; // Round to the highest times of 4 available + + offset = in->index - (in->used >> 2); + size = ( in->used < out_stream_size ) ? in->used : out_stream_size; + + vp_os_memcpy(out->bytes, in->bytes + offset, size); + + out->index = size >> 2; + out->used = size; + + in->used -= size; + + return C_OK; +} + +static C_RESULT p263_load_stream( video_stream_t* out, video_stream_t* in ) +{ + // We cache as many blockline as possible + C_RESULT res; + bool_t found, last_zero, last_zero_temp; + uint32_t *dst, *src; + + int32_t value, nb_dwords; + uint32_t in_index = (in->used >> 2) - 1; + + // -> start looking for last blockline's end + found = FALSE; + + if( in->index == 0 ) // First call, we look for full blocklines + { + last_zero = FALSE; + + while( (in_index > in->index) && !found ) + { + value = in->bytes[in_index]; + + last_zero_temp = (value & 0xFF) == 0; // 0x??????00 + found = last_zero_temp & last_zero; + + if( !found ) + { + last_zero = last_zero_temp; + value >>= 8; + + last_zero_temp = (value & 0xFF) == 0; // 0x????00?? + found = last_zero_temp & last_zero; + + if( !found ) + { + last_zero = last_zero_temp; + value >>= 8; + + last_zero_temp = (value & 0xFF) == 0; // 0x??00???? + found = last_zero_temp & last_zero; + + if( !found ) + { + in_index--; // Handle both the special case where blockline is dword aligned & + // blockline start is still not found + + last_zero = last_zero_temp; + value >>= 8; + + last_zero_temp = (value & 0xFF) == 0; // 0x00?????? + found = last_zero_temp & last_zero; + + if( !found ) + { + last_zero = last_zero_temp; + } + } + } + } + } + } + + in_index++; + + dst = &out->bytes[0]; + dst += out->used/4; + + src = &in->bytes[0]; + src += in->index; + + // configure parameters for memcpy + if( !found ) + { + // cache all data + // if out->used is non zero then we have already a partial blockline in cache + nb_dwords = (in->used >> 2) - in->index; + + res = C_FAIL; + } + else + { + // cache only data containing full blocklines + // if out->used is non zero then we have already a partial blockline in cache + nb_dwords = in_index - in->index; + + res = C_OK; + } + + if( out->used + nb_dwords*4 >= out->size ) + { // Saturates value + nb_dwords = out->size*4 - out->used; + } + + if( out->endianess == in->endianess ) + { + video_copy32( dst, src, nb_dwords ); + } + else + { + // swap copy + video_copy32_swap( dst, src, nb_dwords ); + } + + out->used += nb_dwords*4; + in->index = in_index; + + VP_OS_ASSERT( out->used <= out->size ); + + return res; +} + +C_RESULT p263_cache( video_controller_t* controller, video_stream_t* ex_stream) +{ + C_RESULT res; + + video_stream_t* in_stream = &controller->in_stream; + + switch( controller->mode ) + { + case VIDEO_ENCODE: + res = p263_flush_stream( ex_stream, in_stream ); + break; + + case VIDEO_DECODE: + res = p263_load_stream( in_stream, ex_stream ); + break; + + default: + res = C_FAIL; + break; + } + + return res; +}