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 ***/
102const 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
121video->mblock->pred_block, no adding with residue */
122
123void  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 */
557void  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