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