1 #include <VLIB/Platform/video_utils.h>
2 #include <VLIB/Platform/video_config.h>
4 #include <VLIB/video_quantizer.h>
5 #include <VLIB/video_dct.h>
6 #include <VLIB/video_packetizer.h>
7 #include <VLIB/video_mem32.h>
8 #include "p263_codec.h"
10 #include <VP_Os/vp_os_malloc.h>
11 #include <VP_Os/vp_os_assert.h>
13 static int32_t first_init = 1;
15 const p263_codec_t p263_codec = {
16 p263_encode_blockline,
17 p263_decode_blockline,
23 void p263_codec_alloc( video_controller_t* controller )
25 video_codec_t* video_codec;
29 vlc_mcbpc_ipictures_tree = huffman_alloc(VLC_MCBPC_IPICTURES_NUM, VLC_MCBPC_IPICTURES_MAX_LENGTH);
30 huffman_add_codes( vlc_mcbpc_ipictures_tree, &vlc_mcbpc_ipictures[0], VLC_MCBPC_IPICTURES_NUM );
31 huffman_sort_codes( vlc_mcbpc_ipictures_tree );
33 vlc_cbpy_standard_tree = huffman_alloc(VLC_CBPY_STANDARD_NUM, VLC_CBPY_STANDARD_MAX_LENGTH);
34 huffman_add_codes( vlc_cbpy_standard_tree, &vlc_cbpy_standard[0], VLC_CBPY_STANDARD_NUM );
35 huffman_sort_codes( vlc_cbpy_standard_tree );
37 vlc_tcoeff_tree = huffman_alloc(VLC_TCOEFF_NUM, VLC_TCOEFF_MAX_LENGTH);
38 huffman_add_codes( vlc_tcoeff_tree, &vlc_tcoeff[0], VLC_TCOEFF_NUM );
39 huffman_sort_codes( vlc_tcoeff_tree );
41 mvd_vlc_tree = huffman_alloc(MVD_VLC_NUM, MVD_VLC_MAX_LENGTH);
42 huffman_add_codes( mvd_vlc_tree, &mvd_vlc[0], MVD_VLC_NUM );
43 huffman_sort_codes( mvd_vlc_tree );
48 video_codec = (video_codec_t*) vp_os_malloc( sizeof(p263_codec) );
50 vp_os_memcpy(video_codec, &p263_codec, sizeof(p263_codec));
52 controller->video_codec = video_codec;
55 void p263_codec_free( video_controller_t* controller )
57 p263_codec_t* p263_codec = (p263_codec_t*) controller->video_codec;
59 vp_os_free( p263_codec );
62 static INLINE video_macroblock_t* p263_unquantize_idct( video_controller_t* controller, video_macroblock_t* mb, int32_t num_macro_blocks )
64 video_unquantize( controller, mb, num_macro_blocks );
65 video_idct_compute(mb->data, mb->data, num_macro_blocks);
67 return mb+num_macro_blocks;
70 C_RESULT p263_packet( video_controller_t* controller )
72 uint32_t start_code = 0, num_mb;
73 bool_t picture_complete;
74 video_stream_t* stream = &controller->in_stream;
75 video_macroblock_t* mb;
76 p263_gob_layer_t* gob;
77 p263_codec_t* p263_codec = (p263_codec_t*) controller->video_codec;
78 p263_picture_layer_t* picture_layer = &p263_codec->picture_layer;
80 switch( controller->mode )
86 // TODO Fill first gob with picture header's data
87 video_align8( stream );
88 video_read_data( stream, &start_code, 22 );
90 controller->blockline = start_code & 0x1F;
91 start_code &= ~0x1F; // TODO Check if compiler use arm instruction bic
93 if( start_code == PICTURE_START_CODE )
95 picture_complete = TRUE;
96 if( controller->blockline == 0 )
98 picture_complete = FALSE;
99 p263_read_picture_layer( controller, stream );
101 picture_layer->gobs = (p263_gob_layer_t*) controller->gobs;
102 gob = &picture_layer->gobs[controller->blockline];
104 gob->gquant = picture_layer->pquant;
106 else if( controller->blockline < 0x1F )
108 picture_complete = FALSE;
109 p263_read_gob_layer( controller, stream );
112 controller->picture_complete = picture_complete;
114 if( picture_complete != TRUE )
116 num_mb = controller->mb_blockline;
117 mb = picture_layer->gobs[controller->blockline].macroblocks;
119 for( ; num_mb > 0; num_mb-- )
121 p263_read_mb_layer( controller, stream, mb++ );
134 C_RESULT p263_encode_blockline( video_controller_t* controller, const vp_api_picture_t* blockline, bool_t picture_complete )
139 C_RESULT p263_decode_blockline( video_controller_t* controller, vp_api_picture_t* picture, bool_t* got_image )
141 video_codec_t* video_codec;
142 vp_api_picture_t blockline = { 0 };
144 int32_t num_macro_blocks = 0;
145 video_macroblock_t* macroblock = NULL;
146 video_picture_context_t blockline_ctx;
149 controller->mode = VIDEO_DECODE;
150 video_codec = controller->video_codec;
152 blockline = *picture;
153 blockline.height = MB_HEIGHT_Y;
154 blockline.complete = 1;
155 blockline.vision_complete = 0;
157 picture->complete = controller->picture_complete;
159 blockline_ctx.y_woffset = blockline.y_line_size;
160 blockline_ctx.c_woffset = blockline.cb_line_size;
161 blockline_ctx.y_hoffset = blockline.y_line_size * MCU_HEIGHT;
163 // At least a complete blockline is found
164 while( !controller->picture_complete && controller->in_stream.index < (controller->in_stream.used >> 2) )
166 p263_packet( controller );
168 if( !controller->picture_complete )
170 blockline.blockline = controller->blockline;
172 blockline_ctx.y_src = picture->y_buf + blockline.blockline * MB_HEIGHT_Y * picture->y_line_size;
173 blockline_ctx.cb_src = picture->cb_buf + blockline.blockline * MB_HEIGHT_C * picture->cb_line_size;
174 blockline_ctx.cr_src = picture->cr_buf + blockline.blockline * MB_HEIGHT_C * picture->cr_line_size;
176 picture->blockline = controller->blockline;
177 num_macro_blocks = controller->mb_blockline;
179 gobs = &controller->gobs[controller->blockline];
180 macroblock = &controller->gobs[controller->blockline].macroblocks[0];
181 in = macroblock->data;
183 if( gobs->quant != controller->quant )
185 controller->quant = gobs->quant;
186 video_quantizer_update( controller );
189 while( num_macro_blocks > MAX_NUM_MACRO_BLOCKS_PER_CALL )
191 // These two calls are merged to allow specific optimization in case of a software decoder
192 macroblock = p263_unquantize_idct( controller, macroblock, MAX_NUM_MACRO_BLOCKS_PER_CALL );
194 num_macro_blocks -= MAX_NUM_MACRO_BLOCKS_PER_CALL;
197 // These two calls are merged to allow specific optimization in case of a software decoder
198 p263_unquantize_idct( controller, macroblock, num_macro_blocks );
200 video_blockline_from_macro_blocks(&blockline_ctx, in, controller->mb_blockline, picture->format);
202 // Update controller according to video statistics
203 video_controller_update( controller, controller->picture_complete );
205 // Perform motion compensation
206 if( controller->use_me == TRUE )
212 if( controller->picture_complete )
214 picture->complete = controller->picture_complete;
215 picture->blockline = 0;
217 controller->picture_complete = 0;
218 controller->in_stream.length = 32;
219 //controller->num_frames++;
225 controller->in_stream.used = 0;
226 controller->in_stream.index = 0;
232 C_RESULT p263_update( video_controller_t* controller )
237 static C_RESULT p263_flush_stream( video_stream_t* out, video_stream_t* in )
239 // They are still data in cache
240 // Always copy a number of bytes that is a times of 4.
241 // Only for the last copy, we can have exactly the number of bytes left
242 int32_t offset, size;
243 uint32_t out_stream_size;
245 if( in->length != 32 )
247 // flush & reset internal stream
248 video_write_data( in, 0, in->length+1 );
252 out_stream_size = out->size & ~3; // Round to the highest times of 4 available
254 offset = in->index - (in->used >> 2);
255 size = ( in->used < out_stream_size ) ? in->used : out_stream_size;
257 vp_os_memcpy(out->bytes, in->bytes + offset, size);
259 out->index = size >> 2;
267 static C_RESULT p263_load_stream( video_stream_t* out, video_stream_t* in )
269 // We cache as many blockline as possible
271 bool_t found, last_zero, last_zero_temp;
274 int32_t value, nb_dwords;
275 uint32_t in_index = (in->used >> 2) - 1;
277 // -> start looking for last blockline's end
280 if( in->index == 0 ) // First call, we look for full blocklines
284 while( (in_index > in->index) && !found )
286 value = in->bytes[in_index];
288 last_zero_temp = (value & 0xFF) == 0; // 0x??????00
289 found = last_zero_temp & last_zero;
293 last_zero = last_zero_temp;
296 last_zero_temp = (value & 0xFF) == 0; // 0x????00??
297 found = last_zero_temp & last_zero;
301 last_zero = last_zero_temp;
304 last_zero_temp = (value & 0xFF) == 0; // 0x??00????
305 found = last_zero_temp & last_zero;
309 in_index--; // Handle both the special case where blockline is dword aligned &
310 // blockline start is still not found
312 last_zero = last_zero_temp;
315 last_zero_temp = (value & 0xFF) == 0; // 0x00??????
316 found = last_zero_temp & last_zero;
320 last_zero = last_zero_temp;
330 dst = &out->bytes[0];
336 // configure parameters for memcpy
340 // if out->used is non zero then we have already a partial blockline in cache
341 nb_dwords = (in->used >> 2) - in->index;
347 // cache only data containing full blocklines
348 // if out->used is non zero then we have already a partial blockline in cache
349 nb_dwords = in_index - in->index;
354 if( out->used + nb_dwords*4 >= out->size )
356 nb_dwords = out->size*4 - out->used;
359 if( out->endianess == in->endianess )
361 video_copy32( dst, src, nb_dwords );
366 video_copy32_swap( dst, src, nb_dwords );
369 out->used += nb_dwords*4;
370 in->index = in_index;
372 VP_OS_ASSERT( out->used <= out->size );
377 C_RESULT p263_cache( video_controller_t* controller, video_stream_t* ex_stream)
381 video_stream_t* in_stream = &controller->in_stream;
383 switch( controller->mode )
386 res = p263_flush_stream( ex_stream, in_stream );
390 res = p263_load_stream( in_stream, ex_stream );