1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18
19 #define LOG_TAG "m4v_h263"
20 #include <log/log.h>
21
22 /*
23 ------------------------------------------------------------------------------
24 INPUT AND OUTPUT DEFINITIONS
25
26 Inputs:
27 video = pointer to structure of type VideoDecData
28
29 Local Stores/Buffers/Pointers Needed:
30 roundtab16 = rounding table
31
32 Global Stores/Buffers/Pointers Needed:
33 None
34
35 Outputs:
36 None
37
38 Pointers and Buffers Modified:
39 video->currVop->yChan contents are the newly calculated luminance
40 data
41 video->currVop->uChan contents are the newly calculated chrominance
42 b data
43 video->currVop->vChan contents are the newly calculated chrominance
44 r data
45 video->pstprcTypCur contents are the updated semaphore propagation
46 values
47
48 Local Stores Modified:
49 None
50
51 Global Stores Modified:
52 None
53
54 ------------------------------------------------------------------------------
55 FUNCTION DESCRIPTION
56
57 This function performs high level motion compensation on the luminance and
58 chrominance data. It sets up all the parameters required by the functions
59 that perform luminance and chrominance prediction and it initializes the
60 pointer to the post processing semaphores of a given block. It also checks
61 the motion compensation mode in order to determine which luminance or
62 chrominance prediction functions to call and determines how the post
63 processing semaphores are updated.
64
65 */
66
67
68 /*----------------------------------------------------------------------------
69 ; INCLUDES
70 ----------------------------------------------------------------------------*/
71 #include "mp4dec_lib.h"
72 #include "motion_comp.h"
73 /*----------------------------------------------------------------------------
74 ; MACROS
75 ; Define module specific macros here
76 ----------------------------------------------------------------------------*/
77
78
79 /*----------------------------------------------------------------------------
80 ; DEFINES
81 ; Include all pre-processor statements here. Include conditional
82 ; compile variables also.
83 ----------------------------------------------------------------------------*/
84
85
86 /*----------------------------------------------------------------------------
87 ; LOCAL FUNCTION DEFINITIONS
88 ; Function Prototype declaration
89 ----------------------------------------------------------------------------*/
90
91
92 /*----------------------------------------------------------------------------
93 ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
94 ; Variable declaration - defined here and used outside this module
95 ----------------------------------------------------------------------------*/
96 /* 09/29/2000 bring this from mp4def.h */
97 // const static int roundtab4[] = {0,1,1,1};
98 // const static int roundtab8[] = {0,0,1,1,1,1,1,2};
99 /*** 10/30 for TPS */
100 // const static int roundtab12[] = {0,0,0,1,1,1,1,1,1,1,2,2};
101 /* 10/30 for TPS ***/
102 const static int roundtab16[] = {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2};
103
104
105 /*----------------------------------------------------------------------------
106 ; EXTERNAL FUNCTION REFERENCES
107 ; Declare functions defined elsewhere and referenced in this module
108 ----------------------------------------------------------------------------*/
109
110 /*----------------------------------------------------------------------------
111 ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
112 ; Declare variables used in this module but defined elsewhere
113 ----------------------------------------------------------------------------*/
114
115
116 /*----------------------------------------------------------------------------
117 ; FUNCTION CODE
118 ----------------------------------------------------------------------------*/
119
120 /** modified 3 August 2005 to do prediction and put the results in
121 video->mblock->pred_block, no adding with residue */
122
MBMotionComp(VideoDecData * video,int CBP)123 void MBMotionComp(
124 VideoDecData *video,
125 int CBP
126 )
127 {
128
129 /*----------------------------------------------------------------------------
130 ; Define all local variables
131 ----------------------------------------------------------------------------*/
132 /* Previous Video Object Plane */
133 Vop *prev = video->prevVop;
134
135 /* Current Macroblock (MB) in the VOP */
136 int mbnum = video->mbnum;
137
138 /* Number of MB per data row */
139 int MB_in_width = video->nMBPerRow;
140 int ypos, xpos;
141 PIXEL *c_comp, *c_prev;
142 PIXEL *cu_comp, *cu_prev;
143 PIXEL *cv_comp, *cv_prev;
144 int height, width, pred_width;
145 int imv, mvwidth;
146 int32 offset;
147 uint8 mode;
148 uint8 *pred_block, *pred;
149
150 /* Motion vector (dx,dy) in half-pel resolution */
151 int dx, dy;
152
153 MOT px[4], py[4];
154 int xpred, ypred;
155 int xsum;
156 int round1;
157 #ifdef PV_POSTPROC_ON // 2/14/2001
158 /* Total number of pixels in the VOL */
159 int32 size = (int32) video->nTotalMB << 8;
160 uint8 *pp_dec_y, *pp_dec_u;
161 int ll[4];
162 int tmp = 0;
163 uint8 msk_deblock = 0;
164 #endif
165 /*----------------------------------------------------------------------------
166 ; Function body here
167 ----------------------------------------------------------------------------*/
168 /* Set rounding type */
169 /* change from array to single 09/29/2000 */
170 round1 = (int)(1 - video->currVop->roundingType);
171
172 /* width of luminance data in pixels (y axis) */
173 width = video->width;
174
175 /* heigth of luminance data in pixels (x axis) */
176 height = video->height;
177
178 /* number of blocks per row */
179 mvwidth = MB_in_width << 1;
180
181 /* starting y position in current MB; origin of MB */
182 ypos = video->mbnum_row << 4 ;
183 /* starting x position in current MB; origin of MB */
184 xpos = video->mbnum_col << 4 ;
185
186 /* offset to (x,y) position in current luminance MB */
187 /* in pixel resolution */
188 /* ypos*width -> row, +x -> column */
189 offset = (int32)ypos * width + xpos;
190
191 /* get mode for current MB */
192 mode = video->headerInfo.Mode[mbnum];
193
194 /* block index */
195 /* imv = (xpos/8) + ((ypos/8) * mvwidth) */
196 imv = (offset >> 6) - (xpos >> 6) + (xpos >> 3);
197 if (mode & INTER_1VMASK)
198 {
199 dx = px[0] = px[1] = px[2] = px[3] = video->motX[imv];
200 dy = py[0] = py[1] = py[2] = py[3] = video->motY[imv];
201 if ((dx & 3) == 0)
202 {
203 dx = dx >> 1;
204 }
205 else
206 {
207 /* x component of MV is or'ed for rounding (?) */
208 dx = (dx >> 1) | 1;
209 }
210
211 /* y component of motion vector; divide by 2 for to */
212 /* convert to full-pel resolution. */
213 if ((dy & 3) == 0)
214 {
215 dy = dy >> 1;
216 }
217 else
218 {
219 /* y component of MV is or'ed for rounding (?) */
220 dy = (dy >> 1) | 1;
221 }
222 }
223 else
224 {
225 px[0] = video->motX[imv];
226 px[1] = video->motX[imv+1];
227 px[2] = video->motX[imv+mvwidth];
228 px[3] = video->motX[imv+mvwidth+1];
229 xsum = px[0] + px[1] + px[2] + px[3];
230 dx = PV_SIGN(xsum) * (roundtab16[(PV_ABS(xsum)) & 0xF] +
231 (((PV_ABS(xsum)) >> 4) << 1));
232 py[0] = video->motY[imv];
233 py[1] = video->motY[imv+1];
234 py[2] = video->motY[imv+mvwidth];
235 py[3] = video->motY[imv+mvwidth+1];
236 xsum = py[0] + py[1] + py[2] + py[3];
237 dy = PV_SIGN(xsum) * (roundtab16[(PV_ABS(xsum)) & 0xF] +
238 (((PV_ABS(xsum)) >> 4) << 1));
239 }
240
241 /* Pointer to previous luminance frame */
242 c_prev = prev->yChan;
243 if (!c_prev) {
244 ALOGE("b/35269635");
245 android_errorWriteLog(0x534e4554, "35269635");
246 return;
247 }
248
249 pred_block = video->mblock->pred_block;
250
251 /* some blocks have no residue or INTER4V */
252 /*if (mode == MODE_INTER4V) 05/08/15 */
253 /* Motion Compensation for an 8x8 block within a MB */
254 /* (4 MV per MB) */
255
256
257
258 /* Call function that performs luminance prediction */
259 /* luminance_pred_mode_inter4v(xpos, ypos, px, py, c_prev,
260 video->mblock->pred_block, width, height,
261 round1, mvwidth, &xsum, &ysum);*/
262 c_comp = video->currVop->yChan + offset;
263
264
265 xpred = (int)((xpos << 1) + px[0]);
266 ypred = (int)((ypos << 1) + py[0]);
267
268 if ((CBP >> 5)&1)
269 {
270 pred = pred_block;
271 pred_width = 16;
272 }
273 else
274 {
275 pred = c_comp;
276 pred_width = width;
277 }
278
279 /* check whether the MV points outside the frame */
280 if (xpred >= 0 && xpred <= ((width << 1) - (2*B_SIZE)) &&
281 ypred >= 0 && ypred <= ((height << 1) - (2*B_SIZE)))
282 { /*****************************/
283 /* (x,y) is inside the frame */
284 /*****************************/
285 ;
286 GetPredAdvBTable[ypred&1][xpred&1](c_prev + (xpred >> 1) + ((ypred >> 1)*width),
287 pred, width, (pred_width << 1) | round1);
288 }
289 else
290 { /******************************/
291 /* (x,y) is outside the frame */
292 /******************************/
293 GetPredOutside(xpred, ypred, c_prev,
294 pred, width, height, round1, pred_width);
295 }
296
297
298 /* Compute prediction values over current luminance MB */
299 /* (blocks 1); add motion vector prior to input; */
300 /* add 8 to x_pos to advance to next block */
301 xpred = (int)(((xpos + B_SIZE) << 1) + px[1]);
302 ypred = (int)((ypos << 1) + py[1]);
303
304 if ((CBP >> 4)&1)
305 {
306 pred = pred_block + 8;
307 pred_width = 16;
308 }
309 else
310 {
311 pred = c_comp + 8;
312 pred_width = width;
313 }
314
315 /* check whether the MV points outside the frame */
316 if (xpred >= 0 && xpred <= ((width << 1) - (2*B_SIZE)) &&
317 ypred >= 0 && ypred <= ((height << 1) - (2*B_SIZE)))
318 { /*****************************/
319 /* (x,y) is inside the frame */
320 /*****************************/
321 GetPredAdvBTable[ypred&1][xpred&1](c_prev + (xpred >> 1) + ((ypred >> 1)*width),
322 pred, width, (pred_width << 1) | round1);
323 }
324 else
325 { /******************************/
326 /* (x,y) is outside the frame */
327 /******************************/
328 GetPredOutside(xpred, ypred, c_prev,
329 pred, width, height, round1, pred_width);
330 }
331
332
333
334 /* Compute prediction values over current luminance MB */
335 /* (blocks 2); add motion vector prior to input */
336 /* add 8 to y_pos to advance to block on next row */
337 xpred = (int)((xpos << 1) + px[2]);
338 ypred = (int)(((ypos + B_SIZE) << 1) + py[2]);
339
340 if ((CBP >> 3)&1)
341 {
342 pred = pred_block + 128;
343 pred_width = 16;
344 }
345 else
346 {
347 pred = c_comp + (width << 3);
348 pred_width = width;
349 }
350
351 /* check whether the MV points outside the frame */
352 if (xpred >= 0 && xpred <= ((width << 1) - (2*B_SIZE)) &&
353 ypred >= 0 && ypred <= ((height << 1) - (2*B_SIZE)))
354 { /*****************************/
355 /* (x,y) is inside the frame */
356 /*****************************/
357 GetPredAdvBTable[ypred&1][xpred&1](c_prev + (xpred >> 1) + ((ypred >> 1)*width),
358 pred, width, (pred_width << 1) | round1);
359 }
360 else
361 { /******************************/
362 /* (x,y) is outside the frame */
363 /******************************/
364 GetPredOutside(xpred, ypred, c_prev,
365 pred, width, height, round1, pred_width);
366 }
367
368
369
370 /* Compute prediction values over current luminance MB */
371 /* (blocks 3); add motion vector prior to input; */
372 /* add 8 to x_pos and y_pos to advance to next block */
373 /* on next row */
374 xpred = (int)(((xpos + B_SIZE) << 1) + px[3]);
375 ypred = (int)(((ypos + B_SIZE) << 1) + py[3]);
376
377 if ((CBP >> 2)&1)
378 {
379 pred = pred_block + 136;
380 pred_width = 16;
381 }
382 else
383 {
384 pred = c_comp + (width << 3) + 8;
385 pred_width = width;
386 }
387
388 /* check whether the MV points outside the frame */
389 if (xpred >= 0 && xpred <= ((width << 1) - (2*B_SIZE)) &&
390 ypred >= 0 && ypred <= ((height << 1) - (2*B_SIZE)))
391 { /*****************************/
392 /* (x,y) is inside the frame */
393 /*****************************/
394 GetPredAdvBTable[ypred&1][xpred&1](c_prev + (xpred >> 1) + ((ypred >> 1)*width),
395 pred, width, (pred_width << 1) | round1);
396 }
397 else
398 { /******************************/
399 /* (x,y) is outside the frame */
400 /******************************/
401 GetPredOutside(xpred, ypred, c_prev,
402 pred, width, height, round1, pred_width);
403 }
404 /* Call function to set de-blocking and de-ringing */
405 /* semaphores for luminance */
406
407 #ifdef PV_POSTPROC_ON
408 if (video->postFilterType != PV_NO_POST_PROC)
409 {
410 if (mode&INTER_1VMASK)
411 {
412 pp_dec_y = video->pstprcTypCur + imv;
413 ll[0] = 1;
414 ll[1] = mvwidth - 1;
415 ll[2] = 1;
416 ll[3] = -mvwidth - 1;
417 msk_deblock = pp_semaphore_luma(xpred, ypred, pp_dec_y,
418 video->pstprcTypPrv, ll, &tmp, px[0], py[0], mvwidth,
419 width, height);
420
421 pp_dec_u = video->pstprcTypCur + (size >> 6) +
422 ((imv + (xpos >> 3)) >> 2);
423
424 pp_semaphore_chroma_inter(xpred, ypred, pp_dec_u,
425 video->pstprcTypPrv, dx, dy, mvwidth, height, size,
426 tmp, msk_deblock);
427 }
428 else
429 {
430 /* Post-processing mode (MBM_INTER8) */
431 /* deblocking and deringing) */
432 pp_dec_y = video->pstprcTypCur + imv;
433 *pp_dec_y = 4;
434 *(pp_dec_y + 1) = 4;
435 *(pp_dec_y + mvwidth) = 4;
436 *(pp_dec_y + mvwidth + 1) = 4;
437 pp_dec_u = video->pstprcTypCur + (size >> 6) +
438 ((imv + (xpos >> 3)) >> 2);
439 *pp_dec_u = 4;
440 pp_dec_u[size>>8] = 4;
441 }
442 }
443 #endif
444
445
446 /* xpred and ypred calculation for Chrominance is */
447 /* in full-pel resolution. */
448
449 /* Chrominance */
450 /* width of chrominance data in pixels (y axis) */
451 width >>= 1;
452
453 /* heigth of chrominance data in pixels (x axis) */
454 height >>= 1;
455
456 /* Pointer to previous chrominance b frame */
457 cu_prev = prev->uChan;
458
459 /* Pointer to previous chrominance r frame */
460 cv_prev = prev->vChan;
461
462 /* x position in prediction data offset by motion vector */
463 /* xpred calculation for Chrominance is in full-pel */
464 /* resolution. */
465 xpred = xpos + dx;
466
467 /* y position in prediction data offset by motion vector */
468 /* ypred calculation for Chrominance is in full-pel */
469 /* resolution. */
470 ypred = ypos + dy;
471
472 cu_comp = video->currVop->uChan + (offset >> 2) + (xpos >> 2);
473 cv_comp = video->currVop->vChan + (offset >> 2) + (xpos >> 2);
474
475 /* Call function that performs chrominance prediction */
476 /* chrominance_pred(xpred, ypred, cu_prev, cv_prev,
477 pred_block, width_uv, height_uv,
478 round1);*/
479 if (xpred >= 0 && xpred <= ((width << 1) - (2*B_SIZE)) && ypred >= 0 &&
480 ypred <= ((height << 1) - (2*B_SIZE)))
481 {
482 /*****************************/
483 /* (x,y) is inside the frame */
484 /*****************************/
485 if ((CBP >> 1)&1)
486 {
487 pred = pred_block + 256;
488 pred_width = 16;
489 }
490 else
491 {
492 pred = cu_comp;
493 pred_width = width;
494 }
495
496 /* Compute prediction for Chrominance b (block[4]) */
497 GetPredAdvBTable[ypred&1][xpred&1](cu_prev + (xpred >> 1) + ((ypred >> 1)*width),
498 pred, width, (pred_width << 1) | round1);
499
500 if (CBP&1)
501 {
502 pred = pred_block + 264;
503 pred_width = 16;
504 }
505 else
506 {
507 pred = cv_comp;
508 pred_width = width;
509 }
510 /* Compute prediction for Chrominance r (block[5]) */
511 GetPredAdvBTable[ypred&1][xpred&1](cv_prev + (xpred >> 1) + ((ypred >> 1)*width),
512 pred, width, (pred_width << 1) | round1);
513
514 return ;
515 }
516 else
517 {
518 /******************************/
519 /* (x,y) is outside the frame */
520 /******************************/
521 if ((CBP >> 1)&1)
522 {
523 pred = pred_block + 256;
524 pred_width = 16;
525 }
526 else
527 {
528 pred = cu_comp;
529 pred_width = width;
530 }
531
532 /* Compute prediction for Chrominance b (block[4]) */
533 GetPredOutside(xpred, ypred, cu_prev,
534 pred, width, height, round1, pred_width);
535
536 if (CBP&1)
537 {
538 pred = pred_block + 264;
539 pred_width = 16;
540 }
541 else
542 {
543 pred = cv_comp;
544 pred_width = width;
545 }
546
547 /* Compute prediction for Chrominance r (block[5]) */
548 GetPredOutside(xpred, ypred, cv_prev,
549 pred, width, height, round1, pred_width);
550
551 return ;
552 }
553
554 }
555
556 /*** special function for skipped macroblock, Aug 15, 2005 */
SkippedMBMotionComp(VideoDecData * video)557 void SkippedMBMotionComp(
558 VideoDecData *video
559 )
560 {
561 Vop *prev = video->prevVop;
562 Vop *comp;
563 int ypos, xpos;
564 PIXEL *c_comp, *c_prev;
565 PIXEL *cu_comp, *cu_prev;
566 PIXEL *cv_comp, *cv_prev;
567 int width, width_uv;
568 int32 offset;
569 #ifdef PV_POSTPROC_ON // 2/14/2001
570 int imv;
571 int32 size = (int32) video->nTotalMB << 8;
572 uint8 *pp_dec_y, *pp_dec_u;
573 uint8 *pp_prev1;
574 int mvwidth = video->nMBPerRow << 1;
575 #endif
576
577 width = video->width;
578 width_uv = width >> 1;
579 ypos = video->mbnum_row << 4 ;
580 xpos = video->mbnum_col << 4 ;
581 offset = (int32)ypos * width + xpos;
582
583
584 /* zero motion compensation for previous frame */
585 /*mby*width + mbx;*/
586 c_prev = prev->yChan;
587 if (!c_prev) {
588 ALOGE("b/35269635");
589 android_errorWriteLog(0x534e4554, "35269635");
590 return;
591 }
592 c_prev += offset;
593
594 /*by*width_uv + bx;*/
595 cu_prev = prev->uChan + (offset >> 2) + (xpos >> 2);
596 /*by*width_uv + bx;*/
597 cv_prev = prev->vChan + (offset >> 2) + (xpos >> 2);
598
599 comp = video->currVop;
600
601 c_comp = comp->yChan + offset;
602 cu_comp = comp->uChan + (offset >> 2) + (xpos >> 2);
603 cv_comp = comp->vChan + (offset >> 2) + (xpos >> 2);
604
605
606 /* Copy previous reconstructed frame into the current frame */
607 PutSKIPPED_MB(c_comp, c_prev, width);
608 PutSKIPPED_B(cu_comp, cu_prev, width_uv);
609 PutSKIPPED_B(cv_comp, cv_prev, width_uv);
610
611 /* 10/24/2000 post_processing semaphore generation */
612 #ifdef PV_POSTPROC_ON // 2/14/2001
613 if (video->postFilterType != PV_NO_POST_PROC)
614 {
615 imv = (offset >> 6) - (xpos >> 6) + (xpos >> 3);
616 /* Post-processing mode (copy previous MB) */
617 pp_prev1 = video->pstprcTypPrv + imv;
618 pp_dec_y = video->pstprcTypCur + imv;
619 *pp_dec_y = *pp_prev1;
620 *(pp_dec_y + 1) = *(pp_prev1 + 1);
621 *(pp_dec_y + mvwidth) = *(pp_prev1 + mvwidth);
622 *(pp_dec_y + mvwidth + 1) = *(pp_prev1 + mvwidth + 1);
623
624 /* chrominance */
625 /*4*MB_in_width*MB_in_height*/
626 pp_prev1 = video->pstprcTypPrv + (size >> 6) +
627 ((imv + (xpos >> 3)) >> 2);
628 pp_dec_u = video->pstprcTypCur + (size >> 6) +
629 ((imv + (xpos >> 3)) >> 2);
630 *pp_dec_u = *pp_prev1;
631 pp_dec_u[size>>8] = pp_prev1[size>>8];
632 }
633 #endif
634 /*----------------------------------------------------------------------------
635 ; Return nothing or data or data pointer
636 ----------------------------------------------------------------------------*/
637
638 return;
639 }
640