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