1 /* |
|
2 * Copyright (c) 2010 Ixonos Plc. |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - Initial contribution |
|
11 * |
|
12 * Contributors: |
|
13 * Ixonos Plc |
|
14 * |
|
15 * Description: |
|
16 * Advanced Intra Coding functions (MPEG-4). |
|
17 * |
|
18 */ |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 #include "h263dConfig.h" |
|
24 |
|
25 #include "vdcaic.h" |
|
26 |
|
27 #include "errcodes.h" |
|
28 #include "debug.h" |
|
29 |
|
30 #include "zigzag.h" |
|
31 |
|
32 /* |
|
33 * |
|
34 * aicIntraDCSwitch |
|
35 * |
|
36 * Parameters: |
|
37 * intraDCVLCThr VOP-header field for QP dependent switching between |
|
38 * MPEG-4 IntraDC coding and IntraAC VLC coding of the |
|
39 * Intra DC coefficients |
|
40 * QP quantization parameter |
|
41 * |
|
42 * Function: |
|
43 * This function decides based on the input parameters if the Intra DC |
|
44 * should be decoded as MPEG-4 IntraDC (switched=0) or switched to |
|
45 * IntraAC VLC (switched=1) |
|
46 * |
|
47 * Returns: |
|
48 * switched value |
|
49 * |
|
50 * |
|
51 * |
|
52 */ |
|
53 |
|
54 u_char aicIntraDCSwitch(int intraDCVLCThr, int QP) { |
|
55 |
|
56 if ( intraDCVLCThr == 0 ) { |
|
57 return 0; |
|
58 } |
|
59 else if ( intraDCVLCThr == 7 ) { |
|
60 return 1; |
|
61 } |
|
62 else if ( QP >= intraDCVLCThr*2+11 ) { |
|
63 return 1; |
|
64 } |
|
65 else { |
|
66 return 0; |
|
67 } |
|
68 } |
|
69 |
|
70 /* |
|
71 * |
|
72 * aicDCScaler |
|
73 * |
|
74 * Parameters: |
|
75 * QP quantization parameter |
|
76 * type type of Block "1" Luminance "2" Chrominance |
|
77 * |
|
78 * Function: |
|
79 * Calculation of DC quantization scale according |
|
80 * to the incoming QP and block type |
|
81 * |
|
82 * Returns: |
|
83 * dcScaler value |
|
84 * |
|
85 * |
|
86 * |
|
87 */ |
|
88 |
|
89 int aicDCScaler (int QP, int type) { |
|
90 |
|
91 int dcScaler; |
|
92 if (type == 1) { |
|
93 if (QP > 0 && QP < 5) { |
|
94 dcScaler = 8; |
|
95 } |
|
96 else if (QP > 4 && QP < 9) { |
|
97 dcScaler = 2 * QP; |
|
98 } |
|
99 else if (QP > 8 && QP < 25) { |
|
100 dcScaler = QP + 8; |
|
101 } |
|
102 else { |
|
103 dcScaler = 2 * QP - 16; |
|
104 } |
|
105 } |
|
106 else { |
|
107 if (QP > 0 && QP < 5) { |
|
108 dcScaler = 8; |
|
109 } |
|
110 else if (QP > 4 && QP < 25) { |
|
111 dcScaler = (QP + 13) / 2; |
|
112 } |
|
113 else { |
|
114 dcScaler = QP - 6; |
|
115 } |
|
116 } |
|
117 return dcScaler; |
|
118 } |
|
119 |
|
120 /** |
|
121 * Small routine to compensate the QP value differences between the |
|
122 * predictor and current block AC coefficients |
|
123 * |
|
124 **/ |
|
125 |
|
126 static int compensateQPDiff(int val, int QP) { |
|
127 |
|
128 if (val<0) { |
|
129 return (val-(QP>>1))/QP; |
|
130 } |
|
131 else { |
|
132 return (val+(QP>>1))/QP; |
|
133 } |
|
134 } |
|
135 |
|
136 /** |
|
137 * Small routine to fill default prediction values into a dcStore entry |
|
138 * |
|
139 */ |
|
140 |
|
141 static void resetPredRow(int pred[]) |
|
142 { |
|
143 memset (pred, 0, 7 * sizeof(int)); |
|
144 } |
|
145 |
|
146 /* |
|
147 * |
|
148 * aicStart |
|
149 * |
|
150 * Parameters: |
|
151 * aicData aicData_t structure |
|
152 * instance pointer to vdcInstance_t structure |
|
153 * |
|
154 * Function: |
|
155 * This function initialises dcStore and qpStore buffers. |
|
156 * One should call aicStart in the beginning of each VOP. |
|
157 * |
|
158 * Returns: |
|
159 * Nothing |
|
160 * |
|
161 * Error codes: |
|
162 * |
|
163 * |
|
164 */ |
|
165 |
|
166 void aicStart(aicData_t *aicData, int numMBsInMBLine, int16 *error) |
|
167 { |
|
168 |
|
169 int i,j, numStoreUnits; |
|
170 int initXpos[6] = {-1, 0, -1, 0, -1, -1}; |
|
171 int initYpos[6] = {-1, -1, 0, 0, -1, -1}; |
|
172 int initXtab[6] = {1, 0, 3, 2, 4, 5}; |
|
173 int initYtab[6] = {2, 3, 0, 1, 4, 5}; |
|
174 int initZtab[6] = {3, 2, 1, 0, 4, 5}; |
|
175 |
|
176 numStoreUnits = numMBsInMBLine*2; |
|
177 |
|
178 if (!aicData->qpStore || !aicData->dcStore) { |
|
179 aicData->qpStore = (int16 *) calloc(numStoreUnits, sizeof(int16)); |
|
180 if (!aicData->qpStore) |
|
181 { |
|
182 *error = ERR_VDC_MEMORY_ALLOC; |
|
183 return; |
|
184 } |
|
185 |
|
186 /* allocate space for 3D matrix to keep track of prediction values |
|
187 for DC/AC prediction */ |
|
188 |
|
189 aicData->dcStore = (int ***)calloc(numStoreUnits, sizeof(int **)); |
|
190 if (!aicData->dcStore) |
|
191 { |
|
192 *error = ERR_VDC_MEMORY_ALLOC; |
|
193 return; |
|
194 } |
|
195 |
|
196 for (i = 0; i < numStoreUnits; i++) |
|
197 { |
|
198 aicData->dcStore[i] = (int **)calloc(6, sizeof(int *)); |
|
199 if (!aicData->dcStore[i]) |
|
200 { |
|
201 *error = ERR_VDC_MEMORY_ALLOC; |
|
202 return; |
|
203 } |
|
204 |
|
205 for (j = 0; j < 6; j++) |
|
206 { |
|
207 aicData->dcStore[i][j] = (int *)calloc(15, sizeof(int)); |
|
208 if ( !(aicData->dcStore[i][j]) ) |
|
209 { |
|
210 *error = ERR_VDC_MEMORY_ALLOC; |
|
211 return; |
|
212 } |
|
213 } |
|
214 } |
|
215 |
|
216 aicData->numMBsInMBLine = numMBsInMBLine; |
|
217 |
|
218 for (i= 0; i < 6; i++) |
|
219 { |
|
220 aicData->Xpos[i] = initXpos[i]; |
|
221 aicData->Ypos[i] = initYpos[i]; |
|
222 aicData->Xtab[i] = initXtab[i]; |
|
223 aicData->Ytab[i] = initYtab[i]; |
|
224 aicData->Ztab[i] = initZtab[i]; |
|
225 } |
|
226 |
|
227 /* 1 << (instance->bits_per_pixel - 1) */ |
|
228 aicData->midGrey = 1 << 7; |
|
229 |
|
230 aicData->ACpred_flag = 1; |
|
231 } else { |
|
232 memset(aicData->qpStore, 0, numStoreUnits * sizeof(int16)); |
|
233 } |
|
234 |
|
235 } |
|
236 |
|
237 /* |
|
238 * Clip the reconstructed coefficient when it is stored for prediction |
|
239 * |
|
240 */ |
|
241 |
|
242 #define aicClip(rec) \ |
|
243 ((rec < -2048) ? -2048 : ((rec > 2047) ? 2047 : rec)) |
|
244 |
|
245 /* |
|
246 * |
|
247 * aicBlockUpdate |
|
248 * |
|
249 * Parameters: |
|
250 * aicData aicData_t structure |
|
251 * currMBNum Current Macroblocks Number |
|
252 * |
|
253 * Function: |
|
254 * This function fills up the dcStore and qpStore of current MB. |
|
255 * |
|
256 * Returns: |
|
257 * Nothing |
|
258 * |
|
259 * Error codes: |
|
260 * None |
|
261 * |
|
262 * |
|
263 */ |
|
264 |
|
265 void aicBlockUpdate (aicData_t *aicData, int currMBNum, int blockNum, int *block, |
|
266 int pquant, int DC_coeff) |
|
267 { |
|
268 |
|
269 int n, currDCStoreIndex; |
|
270 assert(currMBNum >= 0); |
|
271 |
|
272 currDCStoreIndex = ((currMBNum / aicData->numMBsInMBLine) % 2) * aicData->numMBsInMBLine + |
|
273 (currMBNum % aicData->numMBsInMBLine); |
|
274 |
|
275 if (block != NULL) { |
|
276 |
|
277 aicData->dcStore[currDCStoreIndex][blockNum][0] = aicClip(DC_coeff); |
|
278 block[0] = aicClip(block[0]); |
|
279 |
|
280 for (n = 1; n < 8; n++) |
|
281 { |
|
282 aicData->dcStore[currDCStoreIndex][blockNum][n] = block[zigzag[n]] = aicClip(block[zigzag[n]]); |
|
283 aicData->dcStore[currDCStoreIndex][blockNum][n+7] = block[zigzag[n<<3 /**8*/]] = aicClip(block[zigzag[n<<3 /**8*/]]); |
|
284 } |
|
285 } |
|
286 |
|
287 if (blockNum == 0) |
|
288 aicData->qpStore[currDCStoreIndex]= (int16) pquant; |
|
289 } |
|
290 |
|
291 /* |
|
292 * |
|
293 * aicIsBlockValid |
|
294 * |
|
295 * Parameters: |
|
296 * aicData aicData_t structure |
|
297 * currMBNum Current Macroblocks Number |
|
298 * |
|
299 * Function: |
|
300 * This function checks if the current MB has a valid entry in the |
|
301 * dcStore and qpStore (needed in predictor validation of I-MBs in a P-VOP). |
|
302 * |
|
303 * Returns: |
|
304 * 1 if MB has a valid entry |
|
305 * 0 if MB doesn't have a valid entry |
|
306 * |
|
307 * Error codes: |
|
308 * None |
|
309 * |
|
310 * |
|
311 */ |
|
312 |
|
313 int aicIsBlockValid (aicData_t *aicData, int currMBNum) |
|
314 { |
|
315 int currDCStoreIndex; |
|
316 assert(currMBNum >= 0); |
|
317 |
|
318 currDCStoreIndex = ((currMBNum / aicData->numMBsInMBLine) % 2) * aicData->numMBsInMBLine + |
|
319 (currMBNum % aicData->numMBsInMBLine); |
|
320 |
|
321 if (aicData->qpStore[currDCStoreIndex] > 0 && aicData->qpStore[currDCStoreIndex] < 32) |
|
322 return 1; |
|
323 else |
|
324 return 0; |
|
325 } |
|
326 |
|
327 /* |
|
328 * |
|
329 * aicFree |
|
330 * |
|
331 * Parameters: |
|
332 * aicData aicData_t structure |
|
333 * numOfMBs Number of Macroblocks in VOP |
|
334 * |
|
335 * Function: |
|
336 * This function frees the dynamic memory allocated by aicStart. |
|
337 * aicFree should be called at least when exiting the main program. |
|
338 * Alternatively it can be called whenever the playing a video has |
|
339 * ended. |
|
340 * |
|
341 * Returns: |
|
342 * Nothing |
|
343 * |
|
344 * Error codes: |
|
345 * None |
|
346 * |
|
347 * |
|
348 */ |
|
349 |
|
350 void aicFree(aicData_t *aicData) |
|
351 { |
|
352 int i,j; |
|
353 |
|
354 /* Free allocated memory for 3D matrix */ |
|
355 if (aicData->dcStore) { |
|
356 for (i = 0; i < (aicData->numMBsInMBLine*2); i++) |
|
357 { |
|
358 for (j = 0; j < 6; j++) |
|
359 free((char *)aicData->dcStore[i][j]); |
|
360 free((char *)aicData->dcStore[i]); |
|
361 } |
|
362 free((char *)aicData->dcStore); |
|
363 } |
|
364 |
|
365 /* Free allocated memory for qpStore matrix */ |
|
366 if (aicData->qpStore) { |
|
367 free((char *)aicData->qpStore); |
|
368 } |
|
369 } |
|
370 |
|
371 /* |
|
372 * |
|
373 * aicDCACrecon |
|
374 * |
|
375 * Parameters: |
|
376 * aicData aicData_t structure |
|
377 * QP QP of the current MB |
|
378 * fTopMBMissing flag indicating if the block above the current block |
|
379 * is outside of the current Video Packet or not a valid |
|
380 * Intra block (in case of P-VOP decoding) |
|
381 * fLeftMBMissing flag indicating if the block left to the current block |
|
382 * is outside of the current Video Packet or not a valid |
|
383 * Intra block (in case of P-VOP decoding) |
|
384 * fBBlockOut flag indicating if the top-left neighbour block of the |
|
385 * current block is outside of the current Video Packet |
|
386 * or not a valid Intra block (in case of P-VOP decoding) |
|
387 * blockNum number of the current block in the MB |
|
388 * (0..3 luminance, 4..5 chrominance) |
|
389 * qBlock block of coefficients |
|
390 * currMBNum number of the current macroblocks in the VOP |
|
391 * |
|
392 * Function: |
|
393 * This function reconstructs the DC and AC (first column or first row or none) |
|
394 * coefficients of the current block by selecting the predictor from the |
|
395 * neighbouring blocks (or default values), and adding these predictor |
|
396 * values to qBlock. Its output is the quantized coefficient matrix in |
|
397 * normal zigzag order. |
|
398 * |
|
399 * Returns: |
|
400 * Nothing |
|
401 * |
|
402 * Error codes: |
|
403 * None |
|
404 * |
|
405 * |
|
406 */ |
|
407 |
|
408 void aicDCACrecon(aicData_t *aicData, int QP, u_char fTopMBMissing, u_char fLeftMBMissing, |
|
409 u_char fBBlockOut, int blockNum, int *qBlock, int currMBNum) |
|
410 { |
|
411 int m, n, tempDCScaler; |
|
412 int xCoordMB, yCoordMB, mbWidth, currDCStoreIndex; |
|
413 int blockA = 0, blockB = 0, blockC = 0, fBlockAExist = 0, fBlockCExist = 0; |
|
414 int gradHor, gradVer, predDC; |
|
415 int fVertical; |
|
416 int predA[7], predC[7]; |
|
417 int pcoeff[64]; |
|
418 assert(currMBNum >= 0); |
|
419 assert(qBlock != NULL); |
|
420 |
|
421 xCoordMB = currMBNum % aicData->numMBsInMBLine; |
|
422 yCoordMB = currMBNum / aicData->numMBsInMBLine; |
|
423 currDCStoreIndex = (yCoordMB % 2)*aicData->numMBsInMBLine + xCoordMB; |
|
424 mbWidth = aicData->numMBsInMBLine * ((currDCStoreIndex < aicData->numMBsInMBLine) ? -1 : 1); |
|
425 |
|
426 |
|
427 /* Find the direction of prediction and the DC prediction */ |
|
428 switch ( blockNum ) { |
|
429 case 0 : |
|
430 case 4 : |
|
431 case 5 : |
|
432 /* Y0, U, and V blocks */ |
|
433 |
|
434 |
|
435 /* Prediction blocks A (left), B (above-left), and C (above) */ |
|
436 if ( ( yCoordMB == 0 && xCoordMB == 0) || (fTopMBMissing && fLeftMBMissing) || (xCoordMB == 0 && fTopMBMissing) || (yCoordMB == 0 && fLeftMBMissing) ) { |
|
437 /* top-left edge of VOP or VP */ |
|
438 blockA = aicData->midGrey<<3 /**8*/; |
|
439 blockB = aicData->midGrey<<3 /**8*/; |
|
440 blockC = aicData->midGrey<<3 /**8*/; |
|
441 fBlockAExist = fBlockCExist = 0; |
|
442 } |
|
443 else if ( yCoordMB == 0 || fTopMBMissing ) { |
|
444 /* top row of VOP or VP, or MB on top not valid */ |
|
445 blockA = aicData->dcStore[currDCStoreIndex+aicData->Xpos[blockNum]][aicData->Xtab[blockNum]][0]; |
|
446 fBlockAExist = 1; |
|
447 if ( yCoordMB == 0 || fBBlockOut ) { |
|
448 /* B MB is out of this VP */ |
|
449 blockB = aicData->midGrey<<3 /**8*/; |
|
450 } |
|
451 else { |
|
452 blockB = aicData->dcStore[currDCStoreIndex+(aicData->Ypos[blockNum])*mbWidth+aicData->Xpos[blockNum]][aicData->Ztab[blockNum]][0]; |
|
453 } |
|
454 blockC = aicData->midGrey<<3 /**8*/; |
|
455 fBlockCExist = 0; |
|
456 } |
|
457 else if ( xCoordMB == 0 || fLeftMBMissing ) { |
|
458 /* left edge of VOP or VP, or MB on left not valid */ |
|
459 blockA = aicData->midGrey<<3 /**8*/; |
|
460 fBlockAExist = 0; |
|
461 if ( xCoordMB == 0 || fBBlockOut ) { |
|
462 /* B MB is out of this VP */ |
|
463 blockB = aicData->midGrey<<3 /**8*/; |
|
464 } |
|
465 else { |
|
466 blockB = aicData->dcStore[currDCStoreIndex+(aicData->Ypos[blockNum])*mbWidth+aicData->Xpos[blockNum]][aicData->Ztab[blockNum]][0]; |
|
467 } |
|
468 blockC = aicData->dcStore[currDCStoreIndex+(aicData->Ypos[blockNum])*mbWidth][aicData->Ytab[blockNum]][0]; |
|
469 fBlockCExist = 1; |
|
470 } |
|
471 else { |
|
472 /* Something else */ |
|
473 blockA = aicData->dcStore[currDCStoreIndex+aicData->Xpos[blockNum]][aicData->Xtab[blockNum]][0]; |
|
474 if ( fBBlockOut ) { |
|
475 /* B MB is out of this VP */ |
|
476 blockB = aicData->midGrey<<3 /**8*/; |
|
477 } |
|
478 else { |
|
479 blockB = aicData->dcStore[currDCStoreIndex+(aicData->Ypos[blockNum])*mbWidth+aicData->Xpos[blockNum]][aicData->Ztab[blockNum]][0]; |
|
480 } |
|
481 blockC = aicData->dcStore[currDCStoreIndex+(aicData->Ypos[blockNum])*mbWidth][aicData->Ytab[blockNum]][0]; |
|
482 fBlockAExist = fBlockCExist = 1; |
|
483 } |
|
484 break; |
|
485 case 1 : |
|
486 /* Y1 block */ |
|
487 |
|
488 /* Prediction block A (left) always available */ |
|
489 blockA = aicData->dcStore[currDCStoreIndex+aicData->Xpos[blockNum]][aicData->Xtab[blockNum]][0]; |
|
490 fBlockAExist = 1; |
|
491 /* Prediction blocks B (above-left) and C (above) */ |
|
492 if ( yCoordMB == 0 || fTopMBMissing ) { |
|
493 /* top row of VOP or VP */ |
|
494 blockB = aicData->midGrey<<3 /**8*/; |
|
495 blockC = aicData->midGrey<<3 /**8*/; |
|
496 fBlockCExist = 0; |
|
497 } |
|
498 else { |
|
499 blockB = aicData->dcStore[currDCStoreIndex+(aicData->Ypos[blockNum])*mbWidth+aicData->Xpos[blockNum]][aicData->Ztab[blockNum]][0]; |
|
500 blockC = aicData->dcStore[currDCStoreIndex+(aicData->Ypos[blockNum])*mbWidth][aicData->Ytab[blockNum]][0]; |
|
501 fBlockCExist = 1; |
|
502 } |
|
503 break; |
|
504 case 2 : |
|
505 /* Y2 block */ |
|
506 |
|
507 /* Prediction blocks A (left) and B (above-left) */ |
|
508 if ( xCoordMB == 0 || fLeftMBMissing ) { |
|
509 /* left edge or first MB in VP */ |
|
510 blockA = aicData->midGrey<<3 /**8*/; |
|
511 blockB = aicData->midGrey<<3 /**8*/; |
|
512 fBlockAExist = 0; |
|
513 } |
|
514 else { |
|
515 blockA = aicData->dcStore[currDCStoreIndex+aicData->Xpos[blockNum]][aicData->Xtab[blockNum]][0]; |
|
516 blockB = aicData->dcStore[currDCStoreIndex+(aicData->Ypos[blockNum])*mbWidth+aicData->Xpos[blockNum]][aicData->Ztab[blockNum]][0]; |
|
517 fBlockAExist = 1; |
|
518 } |
|
519 /* Prediction block C (above) always available */ |
|
520 blockC = aicData->dcStore[currDCStoreIndex+(aicData->Ypos[blockNum])*mbWidth][aicData->Ytab[blockNum]][0]; |
|
521 fBlockCExist = 1; |
|
522 break; |
|
523 case 3 : |
|
524 /* Y3 block */ |
|
525 |
|
526 /* Prediction block A (left) always available */ |
|
527 blockA = aicData->dcStore[currDCStoreIndex+aicData->Xpos[blockNum]][aicData->Xtab[blockNum]][0]; |
|
528 /* Prediction block B (above-left) always available */ |
|
529 blockB = aicData->dcStore[currDCStoreIndex+(aicData->Ypos[blockNum])*mbWidth+aicData->Xpos[blockNum]][aicData->Ztab[blockNum]][0]; |
|
530 /* Prediction block C (above) always available */ |
|
531 blockC = aicData->dcStore[currDCStoreIndex+(aicData->Ypos[blockNum])*mbWidth][aicData->Ytab[blockNum]][0]; |
|
532 fBlockAExist = fBlockCExist = 1; |
|
533 break; |
|
534 } |
|
535 |
|
536 |
|
537 |
|
538 |
|
539 gradHor = blockB - blockC; |
|
540 gradVer = blockA - blockB; |
|
541 |
|
542 if ((abs(gradVer)) < (abs(gradHor))) { |
|
543 /* Vertical prediction (from C) */ |
|
544 predDC = blockC; |
|
545 fVertical = 1; |
|
546 } |
|
547 else { |
|
548 /* Horizontal prediction (from A) */ |
|
549 predDC = blockA; |
|
550 fVertical = 0; |
|
551 } |
|
552 |
|
553 /* Now reconstruct the DC coefficient */ |
|
554 tempDCScaler = aicDCScaler(QP,(blockNum<4)?1:2); |
|
555 qBlock[0] = (u_int8) (qBlock[0] + (predDC + tempDCScaler/2) / tempDCScaler); |
|
556 |
|
557 /* Do AC prediction if required */ |
|
558 if (aicData->ACpred_flag == 1) { |
|
559 |
|
560 /* Do inverse zigzag-scanning */ |
|
561 if (fVertical) { |
|
562 for (m = 0; m < 64; m++) { |
|
563 pcoeff[m] = qBlock[zigzag_h[m]]; |
|
564 } |
|
565 } |
|
566 else { /* horizontal prediction */ |
|
567 for (m = 0; m < 64; m++) { |
|
568 pcoeff[m] = qBlock[zigzag_v[m]]; |
|
569 } |
|
570 } |
|
571 |
|
572 |
|
573 |
|
574 /* AC predictions */ |
|
575 if ( !fVertical && fBlockAExist ) { |
|
576 /* prediction from A */ |
|
577 for (m = 8; m < 15; m++) { |
|
578 predA[m-8] = compensateQPDiff(((aicData->dcStore[currDCStoreIndex+aicData->Xpos[blockNum]][aicData->Xtab[blockNum]][m]) * 2 * (aicData->qpStore[currDCStoreIndex+aicData->Xpos[blockNum]])), (QP<<1)); |
|
579 } |
|
580 } |
|
581 else if ( fVertical && fBlockCExist ) { |
|
582 /* prediction from C */ |
|
583 for (m = 1; m < 8; m++) { |
|
584 predC[m-1] = compensateQPDiff(((aicData->dcStore[currDCStoreIndex+(aicData->Ypos[blockNum])*mbWidth][aicData->Ytab[blockNum]][m]) * 2 * (aicData->qpStore[currDCStoreIndex+(aicData->Ypos[blockNum])*mbWidth])), (QP<<1)); |
|
585 } |
|
586 } |
|
587 else { |
|
588 /* Prediction not possible */ |
|
589 if ( fVertical ) { |
|
590 resetPredRow(predC); |
|
591 } |
|
592 else { |
|
593 resetPredRow(predA); |
|
594 } |
|
595 } |
|
596 |
|
597 |
|
598 |
|
599 /* AC coefficients reconstruction*/ |
|
600 if (fVertical) { /* Vertical, top row of block C */ |
|
601 for (m = 0; m < 7; m++) { |
|
602 qBlock[zigzag[(m+1)*8]] = pcoeff[(m+1)*8]; |
|
603 } |
|
604 for (m = 1; m < 8; m++) { |
|
605 qBlock[zigzag[m]] = pcoeff[m] + predC[m-1]; |
|
606 } |
|
607 } |
|
608 else { /* Horizontal, left column of block A */ |
|
609 for (m = 0; m < 7; m++) { |
|
610 qBlock[zigzag[(m+1)*8]] = pcoeff[(m+1)*8] + predA[m]; |
|
611 } |
|
612 for (m = 1; m < 8; m++) { |
|
613 qBlock[zigzag[m]] = pcoeff[m]; |
|
614 } |
|
615 } |
|
616 |
|
617 /* Copy the rest of the coefficients back to qBlock */ |
|
618 for (m = 1; m < 8; m++) { |
|
619 for (n = 1; n < 8; n++) { |
|
620 qBlock[zigzag[m*8+n]] = pcoeff[m*8+n]; |
|
621 } |
|
622 } |
|
623 } |
|
624 |
|
625 } |
|
626 |
|
627 // End of file |
|