ArDrone SDK 1.8 added
[mardrone] / mardrone / ARDrone_SDK_Version_1_8_20110726 / ARDroneLib / VLIB / video_quantizer.c
1 #include <VLIB/video_quantizer.h>
2 #include <VLIB/Platform/video_utils.h>
3
4 C_RESULT video_quantizer_init( video_controller_t* controller )
5 {
6   // Init quantizer's value
7   // This value is between 1 and 31
8   // TODO: this is not true in case of P264 but P264 don't use the video_quantizer functions. To be fixed
9
10   int32_t quant = controller->quant;
11
12   if( quant < 1 )
13     quant = 1;
14   else if( quant >= 32 )
15     quant = 31;
16
17   if( controller->picture_type == VIDEO_PICTURE_INTRA )
18   {
19     controller->Qp    = 0;
20     controller->invQp = (1 << 16) / (2*quant);
21   }
22   else // VIDEO_PICTURE_INTER
23   {
24     controller->Qp    = quant / 2;
25     controller->invQp = (1 << 16) / (2*quant);
26   }
27
28   controller->dquant = 0;
29
30   return C_OK;
31 }
32
33 C_RESULT video_quantizer_update( video_controller_t* controller )
34 {
35   // Update quantizer's value
36   int32_t quant = controller->quant;
37
38   if( quant < 1 )
39     quant = 1;
40   else if( quant >= 32 )
41     quant = 31;
42
43   if( controller->picture_type == VIDEO_PICTURE_INTRA )
44   {
45     controller->Qp    = 0;
46     controller->invQp = (1 << 16) / (2*quant);
47   }
48   else // VIDEO_PICTURE_INTER
49   {
50     controller->Qp    = quant / 2;
51     controller->invQp = (1 << 16) / (2*quant);
52   }
53
54   controller->dquant = 0;
55
56   return C_OK;
57 }
58
59 C_RESULT video_quantize( video_controller_t* controller, video_macroblock_t* macroblock, int32_t num_macro_blocks )
60 {
61   int32_t sum_y, sum_c, dc0, dc1, dc2, dc3, dcb, dcr;
62   int16_t *y0;
63
64   y0  = macroblock->data;
65
66   while( num_macro_blocks > 0 )
67   {
68     if( controller->do_azq == TRUE )
69     {
70       int16_t *y1, *y2, *y3, *cb, *cr;
71
72       y1  = y0 + MCU_BLOCK_SIZE;
73       y2  = y1 + MCU_BLOCK_SIZE;
74       y3  = y2 + MCU_BLOCK_SIZE;
75       cb  = y3 + MCU_BLOCK_SIZE;
76       cr  = cb + MCU_BLOCK_SIZE;
77
78       // Test for azq (all zero quantized) in luma blocks
79       dc0 = *y0;
80       dc1 = *y1;
81       dc2 = *y2;
82       dc3 = *y3;
83       dcb = *cb;
84       dcr = *cr;
85
86       sum_y = dc0 + dc1 + dc2 + dc3;
87       sum_c = dcb + dcr;
88     }
89     else
90     {
91       sum_y = 0x7F000000;
92       sum_c = 0x7F000000;
93     }
94
95     macroblock->azq = (sum_y < controller->aq) & (sum_c < controller->bq);
96     macroblock->dquant = controller->dquant;
97
98     // Perform quantification on coefficients if necessary
99     if( !macroblock->azq )
100     {
101       RTMON_USTART(VIDEO_VLIB_DOQUANTIZE);
102       if( controller->picture_type == VIDEO_PICTURE_INTRA ) // intra
103       {
104         y0 = do_quantize_intra_mb(y0, controller->quant, &macroblock->num_coeff_y0);
105       }
106       else
107       {
108         y0 = do_quantize_inter_mb(y0, controller->Qp, controller->invQp, &macroblock->num_coeff_y0);
109       }
110       RTMON_USTOP(VIDEO_VLIB_DOQUANTIZE);
111     }
112
113     macroblock++;
114     num_macro_blocks--;
115
116     if( macroblock->azq )
117     {
118       y0  = macroblock->data;
119     }
120   }
121
122   return C_OK;
123 }
124
125 C_RESULT video_unquantize( video_controller_t* controller, video_macroblock_t* macroblock, int32_t num_macro_blocks )
126 {
127   int16_t *dst;
128
129   controller->quant += macroblock->dquant;
130
131   dst  = macroblock->data;
132
133   while( num_macro_blocks > 0 )
134   {
135     // TODO Check generated code
136
137     if( !macroblock->azq )
138       do_unquantize(dst, controller->picture_type, controller->quant, macroblock->num_coeff_y0);
139
140     dst += MCU_BLOCK_SIZE;
141
142     if( !macroblock->azq )
143       do_unquantize(dst, controller->picture_type, controller->quant, macroblock->num_coeff_y1);
144
145     dst += MCU_BLOCK_SIZE;
146
147     if( !macroblock->azq )
148       do_unquantize(dst, controller->picture_type, controller->quant, macroblock->num_coeff_y2);
149
150     dst += MCU_BLOCK_SIZE;
151
152     if( !macroblock->azq )
153       do_unquantize(dst, controller->picture_type, controller->quant, macroblock->num_coeff_y3);
154
155     dst += MCU_BLOCK_SIZE;
156
157     if( !macroblock->azq )
158       do_unquantize(dst, controller->picture_type, controller->quant, macroblock->num_coeff_cb);
159
160     dst += MCU_BLOCK_SIZE;
161
162     if( !macroblock->azq )
163       do_unquantize(dst, controller->picture_type, controller->quant, macroblock->num_coeff_cr);
164
165     dst += MCU_BLOCK_SIZE;
166
167     macroblock ++;
168     num_macro_blocks--;
169   }
170
171   return C_OK;
172 }
173
174 #ifndef HAS_DO_QUANTIZE_INTRA_MB
175 int16_t* do_quantize_intra_mb(int16_t* ptr, int32_t quant, int32_t* last_ptr)
176 {
177   int32_t i, num_coeff;
178   int32_t coeff, last;
179   int32_t j;
180   if (quant == TABLE_QUANTIZATION)
181         quant = TBL_QUANT_QUALITY;
182
183   for( i = 6; i > 0; i-- )
184   {
185     coeff = *ptr;
186     last = 1;
187     num_coeff = MCU_BLOCK_SIZE-1;
188     coeff = coeff / (QUANT_I(0,quant));
189     if( coeff == 0 )
190       coeff = 1;
191     *ptr = coeff;
192     ptr++;
193     j = 1;
194
195     while( num_coeff > 0 )
196     {
197       coeff = *ptr;
198       if( coeff != 0 )
199       {
200         // TODO : division can be slow, a better implementation would consist in building an invQuant(j) table [2^16/QUANT_I(j,quant)] and computing (coeff*invQuant(j))>>16 instead of coeff / (QUANT_I(j,quant))
201         coeff = coeff / (QUANT_I(j,quant));
202
203         if( coeff != 0 )
204         {
205           last++;
206         }
207
208         *ptr = coeff;
209       }
210       ptr++;
211       num_coeff--;
212       j++;
213     }
214
215     *last_ptr++ = last;
216   }
217
218   return ptr;
219 }
220 #endif // HAS_DO_QUANTIZE_INTRA_MB
221
222 int16_t* do_quantize_inter_mb(int16_t* ptr, int32_t quant, int32_t invQuant, int32_t* last_ptr)
223 {
224   int32_t i, num_coeff;
225   int32_t coeff, sign, last;
226
227   // LEVEL = ( |COF| - QUANT/2 ) / (2*QUANT) see III.3.2.1
228
229   for( i = 6; i > 0; i-- )
230   {
231     last = 0;
232     num_coeff = MCU_BLOCK_SIZE;
233
234     while( num_coeff > 0 )
235     {
236       coeff = *ptr;
237
238       if( coeff != 0 )
239       {
240         sign = coeff < 0;
241
242         if( sign )
243           coeff = -coeff;
244
245         coeff -= quant;
246         coeff *= invQuant;
247         coeff >>= 16;
248
249         if( sign )
250           coeff = -coeff;
251
252         if( coeff != 0 )
253         {
254           last++;
255         }
256
257       }
258
259       ptr++;
260       num_coeff--;
261     }
262
263     *last_ptr++ = last;
264   }
265
266   return ptr;
267 }
268
269 #ifndef HAS_DO_UNQUANTIZE
270 C_RESULT do_unquantize(int16_t* ptr, int32_t picture_type, int32_t quant, int32_t num_coeff)
271 {
272   int32_t coeff;
273   uint32_t i=0;
274
275   if (quant == TABLE_QUANTIZATION)
276         quant = TBL_QUANT_QUALITY; // TABLE_QUANTIZATION is an old mode and is equivalent to a QUANT_I(i,2) quantization table
277
278   // table quantization mode
279   i=0;
280   do
281   {
282         coeff = *ptr;
283         if( coeff )
284         {
285           coeff *= QUANT_I (i,quant);
286           *ptr = coeff;
287           num_coeff--;
288         }
289         i++;
290         ptr++;
291   } while( num_coeff > 0 );
292
293   return C_OK;
294 }
295 #endif