ArDrone SDK 1.8 added
[mardrone] / mardrone / ARDrone_SDK_Version_1_8_20110726 / ARDroneLib / VLIB / P263 / p263_codec.c
1 #include <VLIB/Platform/video_utils.h>
2 #include <VLIB/Platform/video_config.h>
3
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"
9
10 #include <VP_Os/vp_os_malloc.h>
11 #include <VP_Os/vp_os_assert.h>
12
13 static int32_t first_init = 1;
14
15 const p263_codec_t p263_codec = {
16   p263_encode_blockline,
17   p263_decode_blockline,
18   p263_update,
19   p263_cache,
20   { 0 }
21 };
22
23 void p263_codec_alloc( video_controller_t* controller )
24 {
25   video_codec_t* video_codec;
26
27   if( first_init == 1 )
28   {
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 );
32
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 );
36
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 );
40
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 );
44
45     first_init = 0;
46   }
47
48   video_codec = (video_codec_t*) vp_os_malloc( sizeof(p263_codec) );
49
50   vp_os_memcpy(video_codec, &p263_codec, sizeof(p263_codec));
51
52   controller->video_codec     = video_codec;
53 }
54
55 void p263_codec_free( video_controller_t* controller )
56 {
57   p263_codec_t* p263_codec = (p263_codec_t*) controller->video_codec;
58
59   vp_os_free( p263_codec );
60 }
61
62 static INLINE video_macroblock_t* p263_unquantize_idct( video_controller_t* controller, video_macroblock_t* mb, int32_t num_macro_blocks )
63 {
64   video_unquantize( controller, mb, num_macro_blocks );
65   video_idct_compute(mb->data, mb->data, num_macro_blocks);
66
67   return mb+num_macro_blocks;
68 }
69
70 C_RESULT p263_packet( video_controller_t* controller )
71 {
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;
79
80   switch( controller->mode )
81   {
82   case VIDEO_ENCODE:
83     break;
84
85   case VIDEO_DECODE:
86     // TODO Fill first gob with picture header's data
87     video_align8( stream );
88     video_read_data( stream, &start_code, 22 );
89
90     controller->blockline = start_code & 0x1F;
91     start_code &= ~0x1F; // TODO Check if compiler use arm instruction bic
92
93     if( start_code == PICTURE_START_CODE )
94     {
95       picture_complete = TRUE;
96       if( controller->blockline == 0 )
97       {
98         picture_complete = FALSE;
99         p263_read_picture_layer( controller, stream );
100
101         picture_layer->gobs = (p263_gob_layer_t*) controller->gobs;
102         gob = &picture_layer->gobs[controller->blockline];
103
104         gob->gquant = picture_layer->pquant;
105       }
106       else if( controller->blockline < 0x1F )
107       {
108         picture_complete = FALSE;
109         p263_read_gob_layer( controller, stream );
110       }
111
112       controller->picture_complete = picture_complete;
113
114       if( picture_complete != TRUE )
115       {
116         num_mb = controller->mb_blockline;
117         mb = picture_layer->gobs[controller->blockline].macroblocks;
118
119         for( ; num_mb > 0; num_mb-- )
120         {
121           p263_read_mb_layer( controller, stream, mb++ );
122         }
123       }
124     }
125     break;
126
127   default:
128     break;
129   }
130
131   return C_OK;
132 }
133
134 C_RESULT p263_encode_blockline( video_controller_t* controller, const vp_api_picture_t* blockline, bool_t picture_complete )
135 {
136   return C_OK;
137 }
138
139 C_RESULT p263_decode_blockline( video_controller_t* controller, vp_api_picture_t* picture, bool_t* got_image )
140 {
141   video_codec_t* video_codec;
142   vp_api_picture_t blockline = { 0 };
143   int16_t *in = NULL;
144   int32_t num_macro_blocks = 0;
145   video_macroblock_t* macroblock = NULL;
146   video_picture_context_t blockline_ctx;
147   video_gob_t*  gobs;
148
149   controller->mode  = VIDEO_DECODE;
150   video_codec       = controller->video_codec;
151
152   blockline                   = *picture;
153   blockline.height            = MB_HEIGHT_Y;
154   blockline.complete          = 1;
155   blockline.vision_complete   = 0;
156
157   picture->complete  = controller->picture_complete;
158
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;
162
163   // At least a complete blockline is found
164   while( !controller->picture_complete && controller->in_stream.index < (controller->in_stream.used >> 2) )
165   {
166     p263_packet( controller );
167
168     if( !controller->picture_complete )
169     {
170       blockline.blockline  = controller->blockline;
171
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;
175
176       picture->blockline  = controller->blockline;
177       num_macro_blocks    = controller->mb_blockline;
178
179       gobs        = &controller->gobs[controller->blockline];
180       macroblock  = &controller->gobs[controller->blockline].macroblocks[0];
181       in          = macroblock->data;
182
183       if( gobs->quant != controller->quant )
184       {
185         controller->quant = gobs->quant;
186         video_quantizer_update( controller );
187       }
188
189       while( num_macro_blocks > MAX_NUM_MACRO_BLOCKS_PER_CALL )
190       {
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 );
193
194         num_macro_blocks -= MAX_NUM_MACRO_BLOCKS_PER_CALL;
195       }
196
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 );
199
200       video_blockline_from_macro_blocks(&blockline_ctx, in, controller->mb_blockline, picture->format);
201
202       // Update controller according to video statistics
203       video_controller_update( controller, controller->picture_complete );
204
205       // Perform motion compensation
206       if( controller->use_me == TRUE )
207       {
208       }
209     }
210   }
211
212   if( controller->picture_complete )
213   {
214     picture->complete   = controller->picture_complete;
215     picture->blockline  = 0;
216
217     controller->picture_complete  = 0;
218     controller->in_stream.length  = 32;
219     //controller->num_frames++;
220
221     *got_image = TRUE;
222   }
223   else
224   {
225     controller->in_stream.used  = 0;
226     controller->in_stream.index = 0;
227   }
228
229   return C_OK;
230 }
231
232 C_RESULT p263_update( video_controller_t* controller )
233 {
234   return C_OK;
235 }
236
237 static C_RESULT p263_flush_stream( video_stream_t* out, video_stream_t* in )
238 {
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;
244
245   if( in->length != 32 )
246   {
247     // flush & reset internal stream
248     video_write_data( in, 0, in->length+1 );
249     in->length = 32;
250   }
251
252   out_stream_size = out->size & ~3; // Round to the highest times of 4 available
253
254   offset = in->index - (in->used >> 2);
255   size = ( in->used < out_stream_size ) ? in->used : out_stream_size;
256
257   vp_os_memcpy(out->bytes, in->bytes + offset, size);
258
259   out->index  = size >> 2;
260   out->used   = size;
261
262   in->used -= size;
263
264   return C_OK;
265 }
266
267 static C_RESULT p263_load_stream( video_stream_t* out, video_stream_t* in )
268 {
269   // We cache as many blockline as possible
270   C_RESULT res;
271   bool_t found, last_zero, last_zero_temp;
272   uint32_t *dst, *src;
273
274   int32_t value, nb_dwords;
275   uint32_t in_index = (in->used >> 2) - 1;
276
277   // -> start looking for last blockline's end
278   found     = FALSE;
279
280   if( in->index == 0 ) // First call, we look for full blocklines
281   {
282     last_zero = FALSE;
283
284     while( (in_index > in->index) && !found )
285     {
286       value = in->bytes[in_index];
287
288       last_zero_temp = (value & 0xFF) == 0; // 0x??????00
289       found = last_zero_temp & last_zero;
290
291       if( !found )
292       {
293         last_zero = last_zero_temp;
294         value >>= 8;
295
296         last_zero_temp = (value & 0xFF) == 0; // 0x????00??
297         found = last_zero_temp & last_zero;
298
299         if( !found )
300         {
301           last_zero = last_zero_temp;
302           value >>= 8;
303
304           last_zero_temp = (value & 0xFF) == 0; // 0x??00????
305           found = last_zero_temp & last_zero;
306
307           if( !found )
308           {
309             in_index--; // Handle both the special case where blockline is dword aligned &
310                         // blockline start is still not found
311
312             last_zero = last_zero_temp;
313             value >>= 8;
314
315             last_zero_temp = (value & 0xFF) == 0; // 0x00??????
316             found = last_zero_temp & last_zero;
317
318             if( !found )
319             {
320               last_zero = last_zero_temp;
321             }
322           }
323         }
324       }
325     }
326   }
327
328   in_index++;
329
330   dst   = &out->bytes[0];
331   dst  += out->used/4;
332
333   src   = &in->bytes[0];
334   src  += in->index;
335
336   // configure parameters for memcpy
337   if( !found )
338   {
339     // cache all data
340     // if out->used is non zero then we have already a partial blockline in cache
341     nb_dwords = (in->used >> 2) - in->index;
342
343     res = C_FAIL;
344   }
345   else
346   {
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;
350
351     res = C_OK;
352   }
353
354   if( out->used + nb_dwords*4 >= out->size )
355   { // Saturates value
356     nb_dwords = out->size*4 - out->used;
357   }
358
359   if( out->endianess == in->endianess )
360   {
361     video_copy32( dst, src, nb_dwords );
362   }
363   else
364   {
365     // swap copy
366     video_copy32_swap( dst, src, nb_dwords );
367   }
368
369   out->used += nb_dwords*4;
370   in->index  = in_index;
371
372   VP_OS_ASSERT( out->used <= out->size );
373
374   return res;
375 }
376
377 C_RESULT p263_cache( video_controller_t* controller, video_stream_t* ex_stream)
378 {
379   C_RESULT res;
380
381   video_stream_t* in_stream = &controller->in_stream;
382
383   switch( controller->mode )
384   {
385   case VIDEO_ENCODE:
386     res = p263_flush_stream( ex_stream, in_stream );
387     break;
388
389   case VIDEO_DECODE:
390     res = p263_load_stream( in_stream, ex_stream );
391     break;
392
393   default:
394     res = C_FAIL;
395     break;
396   }
397
398   return res;
399 }