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 ***/
98const 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
117video->mblock->pred_block, no adding with residue */
118
119void  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 */
548void  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