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