ArDrone SDK 1.8 added
[mardrone] / mardrone / ARDrone_SDK_Version_1_8_20110726 / ARDroneLib / VLIB / video_codec.c
1 #include <VLIB/video_codec.h>
2 #include <VLIB/video_quantizer.h>
3 #include <VLIB/video_packetizer.h>
4 #include <VLIB/Platform/video_utils.h>
5 #include <VLIB/Platform/video_config.h>
6
7 #include <VP_Os/vp_os_malloc.h>
8 #include <VP_Os/vp_os_print.h>
9
10 #ifdef _ELINUX
11 #include "dma_malloc.h"
12 #define vp_os_aligned_malloc(A,B) dma_malloc(A)
13 #define vp_os_aligned_free(A) dma_free(A)
14 #endif
15
16 extern C_RESULT video_utils_init( video_controller_t* controller );
17 extern C_RESULT video_utils_close( video_controller_t* controller );
18
19 extern void uvlc_codec_alloc( video_controller_t* controller );
20 extern void uvlc_codec_free( video_controller_t* controller );
21
22 extern void p263_codec_alloc( video_controller_t* controller );
23 extern void p263_codec_free( video_controller_t* controller );
24
25 extern void p264_codec_alloc( video_controller_t* controller );
26 extern void p264_codec_free( video_controller_t* controller );
27
28 static C_RESULT video_codec_open_private( video_controller_t* controller, codec_type_t codec_type, bool_t keep_stream );
29 static C_RESULT video_codec_close_private( video_controller_t* controller, bool_t keep_stream );
30
31 static C_RESULT video_codec_open_private( video_controller_t* controller, codec_type_t codec_type, bool_t keep_stream )
32 {
33   C_RESULT res;
34   // Data used to initialize macroblock's cache
35   int32_t i;
36   int16_t* cache;
37   video_macroblock_t* mb;
38
39   // Close any previously allocated codec for this controller
40   video_codec_close_private( controller, keep_stream);
41
42   controller->mode            = 0;
43   controller->use_me          = FALSE;
44   controller->do_azq          = FALSE;
45   controller->aq              = 0;
46   controller->bq              = 0;
47   controller->target_bitrate  = VLIB_DEFAULT_BITRATE;
48   controller->num_frames      = 0;
49   controller->picture_type    = 0;
50   controller->width           = 0;
51   controller->height          = 0;
52   controller->resolution_changed = FALSE;
53   controller->num_blockline   = 0;
54   controller->mb_blockline    = 0;
55   controller->blockline       = 0;
56   controller->picture_complete= 0;
57   controller->quant           = DEFAULT_QUANTIZATION;
58   controller->dquant          = 0;
59   controller->Qp              = 0;
60   controller->invQp           = 1;
61   controller->gobs            = NULL;
62   controller->cache           = NULL;
63   controller->codec_type      = 0;
64   controller->video_codec     = NULL;
65
66   if( controller->blockline_cache == NULL )
67   {
68     // We alloc two buffers to be compatible with an asynchronous DCT
69     // When a DCT will be performed on one buffer, we will be able to use the other for caching or computing purpose
70     // DCT_BUFFER_SIZE = MAX_NUM_MACRO_BLOCKS_PER_CALL * 6 * MCU_BLOCK_SIZE
71     controller->blockline_cache = (int16_t*)vp_os_aligned_malloc( 2*DCT_BUFFER_SIZE*sizeof(int16_t), VLIB_ALLOC_ALIGN );
72   }
73   if (controller->cache_mbs == NULL)
74   {
75     controller->cache_mbs = vp_os_malloc( 2 * MAX_NUM_MACRO_BLOCKS_PER_CALL * sizeof(video_macroblock_t) );
76     mb = &controller->cache_mbs[0];
77     cache = controller->blockline_cache;
78     for(i = 2*MAX_NUM_MACRO_BLOCKS_PER_CALL; i > 0; i-- )
79     {
80       mb->data = cache;
81       cache   += MCU_BLOCK_SIZE*6;
82       mb ++;
83     }
84   }
85
86   if (keep_stream == FALSE)
87     video_packetizer_init( controller );
88   video_quantizer_init( controller );
89
90   switch( codec_type )
91   {
92     case UVLC_CODEC:
93       uvlc_codec_alloc( controller );
94       break;
95
96     case P263_CODEC:
97       p263_codec_alloc( controller );
98       break;
99
100     case P264_CODEC:
101       p264_codec_alloc( controller );
102       break;
103
104     default:
105       controller->video_codec = NULL;
106       break;
107   }
108
109   if( controller->video_codec != NULL )
110   {
111     controller->codec_type = codec_type;
112     res = C_OK;
113   }
114   else
115   {
116     res = C_FAIL;
117   }
118
119   video_utils_init( controller );
120
121   return res;
122 }
123
124 C_RESULT video_codec_open( video_controller_t* controller, codec_type_t codec_type )
125 {
126   return video_codec_open_private(controller, codec_type, FALSE );
127 }
128
129 static C_RESULT video_codec_close_private( video_controller_t* controller, bool_t keep_stream )
130 {
131   video_utils_close( controller );
132
133   if( controller->blockline_cache != NULL )
134   {
135     vp_os_aligned_free( controller->blockline_cache );
136     controller->blockline_cache = NULL;
137   }
138
139   if (controller->cache_mbs != NULL)
140   {
141     vp_os_free( controller->cache_mbs );
142     controller->cache_mbs = NULL;
143   }
144
145
146   if( keep_stream == FALSE && controller->in_stream.bytes != NULL )
147     video_packetizer_close( controller );
148
149   switch( controller->codec_type )
150   {
151     case UVLC_CODEC:
152       uvlc_codec_free( controller );
153       break;
154
155     case P263_CODEC:
156       p263_codec_free( controller );
157       break;
158
159     case P264_CODEC:
160       p264_codec_free( controller );
161       break;
162
163     default:
164       break;
165   }
166
167   // Cleanup caches
168   video_controller_cleanup( controller );
169
170   return C_OK;
171 }
172
173 C_RESULT video_codec_close ( video_controller_t* controller)
174 {
175   return video_codec_close_private(controller, FALSE);
176 }
177
178 C_RESULT video_codec_type_select(video_controller_t* controller, video_stream_t* stream)
179 {
180    uint32_t codec_type = 0;
181    video_align8( stream );
182    video_peek_data( stream, &codec_type, 22 );
183    // extract codec tag
184    //codec_type = codec_type>>5;
185
186    if (codec_type != controller->codec_type)
187    {
188      PRINT("VLIB new codec %d\n",codec_type);
189      // video codec has changed, load a new codec
190      video_codec_open_private( controller, codec_type, TRUE );
191
192    }
193    return C_OK;
194 }
195
196 C_RESULT video_encode_picture( video_controller_t* controller, const vp_api_picture_t* picture, bool_t* got_image )
197 {
198   vp_api_picture_t blockline = { 0 };
199
200   controller->mode  = VIDEO_ENCODE;
201
202   video_controller_set_format( controller, picture->width, picture->height );
203
204   blockline                   = *picture;
205   blockline.height            = MB_HEIGHT_Y;
206   blockline.complete          = 1;
207   blockline.vision_complete   = 0;
208
209   // Reset internal stream for new blockline/picture
210   controller->in_stream.used  = 0;
211   controller->in_stream.index = 0;
212
213   while( !controller->picture_complete )
214   {
215     video_encode_blockline( controller, &blockline, blockline.blockline == (controller->num_blockline-1) );
216
217     blockline.y_buf  += MB_HEIGHT_Y * picture->y_line_size;
218     blockline.cb_buf += MB_HEIGHT_C * picture->cb_line_size;
219     blockline.cr_buf += MB_HEIGHT_C * picture->cr_line_size;
220
221     blockline.blockline++;
222   }
223
224   if( picture->complete )
225   {
226     video_write_data( &controller->in_stream, 0, controller->in_stream.length+1 );
227     controller->in_stream.length = 32;
228     controller->picture_complete = 0;
229     *got_image = TRUE;
230   }
231
232   return C_OK;
233 }
234
235 C_RESULT video_decode_picture( video_controller_t* controller, vp_api_picture_t* picture, video_stream_t* ex_stream, bool_t* got_image )
236 {
237   vp_api_picture_t blockline = { 0 };
238
239   controller->mode  = VIDEO_DECODE; // mandatory because of video_cache_stream
240
241   blockline                   = *picture;
242   blockline.height            = MB_HEIGHT_Y;
243   blockline.complete          = 1;
244   blockline.vision_complete   = 0;
245
246   while( VP_SUCCEEDED(video_cache_stream( controller, ex_stream )) )
247   {
248     video_codec_type_select(controller,ex_stream); // to be verified
249     video_decode_blockline( controller, &blockline, got_image );
250   }
251
252   return C_OK;
253 }
254
255
256 C_RESULT video_decode_blockline( video_controller_t* controller, vp_api_picture_t* blockline, bool_t* got_image )
257 {
258   video_codec_type_select(controller,&controller->in_stream);
259   return controller->video_codec->decode_blockline( controller, blockline, got_image );
260 }