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     /*----------------------------------------------------------------------------
158     ; Function body here
159     ----------------------------------------------------------------------------*/
160     /* Set rounding type */
161     /* change from array to single 09/29/2000 */
162     round1 = (int)(1 - video->currVop->roundingType);
163 
164     /* width of luminance data in pixels (y axis) */
165     width = video->width;
166 
167     /* heigth of luminance data in pixels (x axis) */
168     height = video->height;
169 
170     /* number of blocks per row */
171     mvwidth = MB_in_width << 1;
172 
173     /* starting y position in current MB; origin of MB */
174     ypos = video->mbnum_row << 4 ;
175     /* starting x position in current MB; origin of MB */
176     xpos = video->mbnum_col << 4 ;
177 
178     /* offset to (x,y) position in current luminance MB */
179     /* in pixel resolution                              */
180     /* ypos*width -> row, +x -> column */
181     offset = (int32)ypos * width + xpos;
182 
183     /* get mode for current MB */
184     mode = video->headerInfo.Mode[mbnum];
185 
186     /* block index */
187     /* imv = (xpos/8) + ((ypos/8) * mvwidth) */
188     imv = (offset >> 6) - (xpos >> 6) + (xpos >> 3);
189     if (mode & INTER_1VMASK)
190     {
191         dx = px[0] = px[1] = px[2] = px[3] = video->motX[imv];
192         dy = py[0] = py[1] = py[2] = py[3] = video->motY[imv];
193         if ((dx & 3) == 0)
194         {
195             dx = dx >> 1;
196         }
197         else
198         {
199             /* x component of MV is or'ed for rounding (?) */
200             dx = (dx >> 1) | 1;
201         }
202 
203         /* y component of motion vector; divide by 2 for to */
204         /* convert to full-pel resolution.                  */
205         if ((dy & 3) == 0)
206         {
207             dy = dy >> 1;
208         }
209         else
210         {
211             /* y component of MV is or'ed for rounding (?) */
212             dy = (dy >> 1) | 1;
213         }
214     }
215     else
216     {
217         px[0] = video->motX[imv];
218         px[1] = video->motX[imv+1];
219         px[2] = video->motX[imv+mvwidth];
220         px[3] = video->motX[imv+mvwidth+1];
221         xsum = px[0] + px[1] + px[2] + px[3];
222         dx = PV_SIGN(xsum) * (roundtab16[(PV_ABS(xsum)) & 0xF] +
223                               (((PV_ABS(xsum)) >> 4) << 1));
224         py[0] = video->motY[imv];
225         py[1] = video->motY[imv+1];
226         py[2] = video->motY[imv+mvwidth];
227         py[3] = video->motY[imv+mvwidth+1];
228         xsum = py[0] + py[1] + py[2] + py[3];
229         dy = PV_SIGN(xsum) * (roundtab16[(PV_ABS(xsum)) & 0xF] +
230                               (((PV_ABS(xsum)) >> 4) << 1));
231     }
232 
233     /* Pointer to previous luminance frame */
234     c_prev  = prev->yChan;
235     if (!c_prev) {
236         ALOGE("b/35269635");
237         android_errorWriteLog(0x534e4554, "35269635");
238         return;
239     }
240 
241     pred_block = video->mblock->pred_block;
242 
243     /* some blocks have no residue or INTER4V */
244     /*if (mode == MODE_INTER4V)   05/08/15 */
245     /* Motion Compensation for an 8x8 block within a MB */
246     /* (4 MV per MB) */
247 
248 
249 
250     /* Call function that performs luminance prediction */
251     /*      luminance_pred_mode_inter4v(xpos, ypos, px, py, c_prev,
252                     video->mblock->pred_block, width, height,
253                     round1, mvwidth, &xsum, &ysum);*/
254     c_comp = video->currVop->yChan + offset;
255 
256 
257     xpred = (int)((xpos << 1) + px[0]);
258     ypred = (int)((ypos << 1) + py[0]);
259 
260     if ((CBP >> 5)&1)
261     {
262         pred = pred_block;
263         pred_width = 16;
264     }
265     else
266     {
267         pred = c_comp;
268         pred_width = width;
269     }
270 
271     /* check whether the MV points outside the frame */
272     if (xpred >= 0 && xpred <= ((width << 1) - (2*B_SIZE)) &&
273             ypred >= 0 && ypred <= ((height << 1) - (2*B_SIZE)))
274     {   /*****************************/
275         /* (x,y) is inside the frame */
276         /*****************************/
277         ;
278         GetPredAdvBTable[ypred&1][xpred&1](c_prev + (xpred >> 1) + ((ypred >> 1)*width),
279                                            pred, width, (pred_width << 1) | round1);
280     }
281     else
282     {   /******************************/
283         /* (x,y) is outside the frame */
284         /******************************/
285         GetPredOutside(xpred, ypred, c_prev,
286                        pred, width, height, round1, pred_width);
287     }
288 
289 
290     /* Compute prediction values over current luminance MB */
291     /* (blocks 1); add motion vector prior to input;       */
292     /* add 8 to x_pos to advance to next block         */
293     xpred = (int)(((xpos + B_SIZE) << 1) + px[1]);
294     ypred = (int)((ypos << 1) + py[1]);
295 
296     if ((CBP >> 4)&1)
297     {
298         pred = pred_block + 8;
299         pred_width = 16;
300     }
301     else
302     {
303         pred = c_comp + 8;
304         pred_width = width;
305     }
306 
307     /* check whether the MV points outside the frame */
308     if (xpred >= 0 && xpred <= ((width << 1) - (2*B_SIZE)) &&
309             ypred >= 0 && ypred <= ((height << 1) - (2*B_SIZE)))
310     {   /*****************************/
311         /* (x,y) is inside the frame */
312         /*****************************/
313         GetPredAdvBTable[ypred&1][xpred&1](c_prev + (xpred >> 1) + ((ypred >> 1)*width),
314                                            pred, width, (pred_width << 1) | round1);
315     }
316     else
317     {   /******************************/
318         /* (x,y) is outside the frame */
319         /******************************/
320         GetPredOutside(xpred, ypred, c_prev,
321                        pred, width, height, round1, pred_width);
322     }
323 
324 
325 
326     /* Compute prediction values over current luminance MB */
327     /* (blocks 2); add motion vector prior to input        */
328     /* add 8 to y_pos to advance to block on next row      */
329     xpred = (int)((xpos << 1) + px[2]);
330     ypred = (int)(((ypos + B_SIZE) << 1) + py[2]);
331 
332     if ((CBP >> 3)&1)
333     {
334         pred = pred_block + 128;
335         pred_width = 16;
336     }
337     else
338     {
339         pred = c_comp + (width << 3);
340         pred_width = width;
341     }
342 
343     /* check whether the MV points outside the frame */
344     if (xpred >= 0 && xpred <= ((width << 1) - (2*B_SIZE)) &&
345             ypred >= 0 && ypred <= ((height << 1) - (2*B_SIZE)))
346     {   /*****************************/
347         /* (x,y) is inside the frame */
348         /*****************************/
349         GetPredAdvBTable[ypred&1][xpred&1](c_prev + (xpred >> 1) + ((ypred >> 1)*width),
350                                            pred, width, (pred_width << 1) | round1);
351     }
352     else
353     {   /******************************/
354         /* (x,y) is outside the frame */
355         /******************************/
356         GetPredOutside(xpred, ypred, c_prev,
357                        pred, width, height, round1, pred_width);
358     }
359 
360 
361 
362     /* Compute prediction values over current luminance MB */
363     /* (blocks 3); add motion vector prior to input;       */
364     /* add 8 to x_pos and y_pos to advance to next block   */
365     /* on next row                         */
366     xpred = (int)(((xpos + B_SIZE) << 1) + px[3]);
367     ypred = (int)(((ypos + B_SIZE) << 1) + py[3]);
368 
369     if ((CBP >> 2)&1)
370     {
371         pred = pred_block + 136;
372         pred_width = 16;
373     }
374     else
375     {
376         pred = c_comp + (width << 3) + 8;
377         pred_width = width;
378     }
379 
380     /* check whether the MV points outside the frame */
381     if (xpred >= 0 && xpred <= ((width << 1) - (2*B_SIZE)) &&
382             ypred >= 0 && ypred <= ((height << 1) - (2*B_SIZE)))
383     {   /*****************************/
384         /* (x,y) is inside the frame */
385         /*****************************/
386         GetPredAdvBTable[ypred&1][xpred&1](c_prev + (xpred >> 1) + ((ypred >> 1)*width),
387                                            pred, width, (pred_width << 1) | round1);
388     }
389     else
390     {   /******************************/
391         /* (x,y) is outside the frame */
392         /******************************/
393         GetPredOutside(xpred, ypred, c_prev,
394                        pred, width, height, round1, pred_width);
395     }
396     /* Call function to set de-blocking and de-ringing */
397     /*   semaphores for luminance                      */
398 
399 
400 
401     /* xpred and ypred calculation for Chrominance is */
402     /* in full-pel resolution.                        */
403 
404     /* Chrominance */
405     /* width of chrominance data in pixels (y axis) */
406     width >>= 1;
407 
408     /* heigth of chrominance data in pixels (x axis) */
409     height >>= 1;
410 
411     /* Pointer to previous chrominance b frame */
412     cu_prev = prev->uChan;
413 
414     /* Pointer to previous chrominance r frame */
415     cv_prev = prev->vChan;
416 
417     /* x position in prediction data offset by motion vector */
418     /* xpred calculation for Chrominance is in full-pel      */
419     /* resolution.                                           */
420     xpred = xpos + dx;
421 
422     /* y position in prediction data offset by motion vector */
423     /* ypred calculation for Chrominance is in full-pel      */
424     /* resolution.                                           */
425     ypred = ypos + dy;
426 
427     cu_comp = video->currVop->uChan + (offset >> 2) + (xpos >> 2);
428     cv_comp = video->currVop->vChan + (offset >> 2) + (xpos >> 2);
429 
430     /* Call function that performs chrominance prediction */
431     /*      chrominance_pred(xpred, ypred, cu_prev, cv_prev,
432             pred_block, width_uv, height_uv,
433             round1);*/
434     if (xpred >= 0 && xpred <= ((width << 1) - (2*B_SIZE)) && ypred >= 0 &&
435             ypred <= ((height << 1) - (2*B_SIZE)))
436     {
437         /*****************************/
438         /* (x,y) is inside the frame */
439         /*****************************/
440         if ((CBP >> 1)&1)
441         {
442             pred = pred_block + 256;
443             pred_width = 16;
444         }
445         else
446         {
447             pred = cu_comp;
448             pred_width = width;
449         }
450 
451         /* Compute prediction for Chrominance b (block[4]) */
452         GetPredAdvBTable[ypred&1][xpred&1](cu_prev + (xpred >> 1) + ((ypred >> 1)*width),
453                                            pred, width, (pred_width << 1) | round1);
454 
455         if (CBP&1)
456         {
457             pred = pred_block + 264;
458             pred_width = 16;
459         }
460         else
461         {
462             pred = cv_comp;
463             pred_width = width;
464         }
465         /* Compute prediction for Chrominance r (block[5]) */
466         GetPredAdvBTable[ypred&1][xpred&1](cv_prev + (xpred >> 1) + ((ypred >> 1)*width),
467                                            pred, width, (pred_width << 1) | round1);
468 
469         return ;
470     }
471     else
472     {
473         /******************************/
474         /* (x,y) is outside 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         GetPredOutside(xpred, ypred,    cu_prev,
489                        pred, width, height, round1, pred_width);
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 
502         /* Compute prediction for Chrominance r (block[5]) */
503         GetPredOutside(xpred, ypred,    cv_prev,
504                        pred, width, height, round1, pred_width);
505 
506         return ;
507     }
508 
509 }
510 
511 /*** special function for skipped macroblock,  Aug 15, 2005 */
SkippedMBMotionComp(VideoDecData * video)512 void  SkippedMBMotionComp(
513     VideoDecData *video
514 )
515 {
516     Vop *prev = video->prevVop;
517     Vop *comp;
518     int ypos, xpos;
519     PIXEL *c_comp, *c_prev;
520     PIXEL *cu_comp, *cu_prev;
521     PIXEL *cv_comp, *cv_prev;
522     int width, width_uv;
523     int32 offset;
524 
525     width = video->width;
526     width_uv  = width >> 1;
527     ypos = video->mbnum_row << 4 ;
528     xpos = video->mbnum_col << 4 ;
529     offset = (int32)ypos * width + xpos;
530 
531 
532     /* zero motion compensation for previous frame */
533     /*mby*width + mbx;*/
534     c_prev  = prev->yChan;
535     if (!c_prev) {
536         ALOGE("b/35269635");
537         android_errorWriteLog(0x534e4554, "35269635");
538         return;
539     }
540     c_prev += offset;
541 
542     /*by*width_uv + bx;*/
543     cu_prev = prev->uChan + (offset >> 2) + (xpos >> 2);
544     /*by*width_uv + bx;*/
545     cv_prev = prev->vChan + (offset >> 2) + (xpos >> 2);
546 
547     comp = video->currVop;
548 
549     c_comp  = comp->yChan + offset;
550     cu_comp = comp->uChan + (offset >> 2) + (xpos >> 2);
551     cv_comp = comp->vChan + (offset >> 2) + (xpos >> 2);
552 
553 
554     /* Copy previous reconstructed frame into the current frame */
555     PutSKIPPED_MB(c_comp,  c_prev, width);
556     PutSKIPPED_B(cu_comp, cu_prev, width_uv);
557     PutSKIPPED_B(cv_comp, cv_prev, width_uv);
558 
559     /*  10/24/2000 post_processing semaphore generation */
560     /*----------------------------------------------------------------------------
561     ; Return nothing or data or data pointer
562     ----------------------------------------------------------------------------*/
563 
564     return;
565 }
566