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     xpos = x half-pixel of (x,y) coordinates within a VOP; motion
24            compensated coordinates; native data type
25     ypos = y half-pixel of (x,y) coordinates within a VOP; motion
26            compensated coordinates; native data type
27     comp = pointer to 8-bit compensated prediction values within a VOP;
28            computed by this module (i/o); full-pel resolution; 8-bit data
29     c_prev = pointer to previous 8-bit prediction values within a VOP;
30          values range from (0-255); full-pel resolution; 8-bit data
31     sh_d = pointer to residual values used to compensate the predicted
32            value; values range from (-512 to 511); full-pel resolution;
33            native data type
34     width = width of the VOP in pixels (x axis); full-pel resolution;
35         native data type
36     height = height of the VOP in pixels (y axis); full-pel resolution;
37          native data type
38     rnd1 = rounding value for case when one dimension uses half-pel
39            resolution; native data type
40     rnd2 = rounding value for case when two dimensions uses half-pel
41            resolution; native data type
42 
43  Outputs:
44     returns 1
45 
46  Local Stores/Buffers/Pointers Needed:
47     None
48 
49  Global Stores/Buffers/Pointers Needed:
50     None
51 
52  Pointers and Buffers Modified:
53     comp = buffer contains newly computed compensated prediction values
54 
55  Local Stores Modified:
56     None
57 
58  Global Stores Modified:
59     None
60 
61 ------------------------------------------------------------------------------
62  FUNCTION DESCRIPTION
63 
64  Summary:
65 
66  This function performs motion compensated prediction for the case where
67  the motion vector points to a block outside the VOP. The function interpolates
68  the pixels that are outside the VOP using the boundary pixels for the block.
69  Once the values are interpolated, the pixel values are computed for a block
70  in the current VOP. The prediction values are generated by averaging pixel
71  values in the previous VOP; the block position in the previous frame is
72  computed from the current block's motion vector. The computed pixel values
73  are calculated by adding the prediction values to the block residual values.
74 
75  Details:
76 
77  First, this functions determines which VOP boundary(ies) the motion vector
78  is outside, i.e., left, right, top, bottom. xpos is compared to the left and
79  right boundaries; ypos is compared to the top and bottom boundaries. The number
80  of block pixels inside the the boundary in the x and y directions are stored
81  in endx and endy, respectively. If the entire block is inside the x or y
82  boundary, the respectively end is set to 0.
83 
84  After the boundaries are tested, any pixels lying outside a boundary are
85  interpolated from the boundary pixels. For example, if the block is outside the
86  bottom boundary, boundary pixels alone the bottom of the VOP as used to
87  interpolated those pixels lying outside the bottom boundary. The interpolation
88  used is a simple column-wise or row-wise copy of the boundary pixels (inside the
89  block) depending on which boundary the block is outside. In our example, each
90  boundary pixel would be copied column-wise to the pixel beneath it. If the
91  block was outside right boundary, the boundary pixels would be copied row-wise
92  to the pixel to the right of it. If the block was outside both an x and y
93  boundary, the boundary pixels would be copied row-wise for the portion of the
94  block outside the x boundary, and column-wise for the portion of the block
95  outside the y boundary. And so on.
96 
97  Once the pixel interpolation is complete, the motion compensated output values
98  (comp[]) are calculed from the motion compensated prediction (pred[])values and
99  the residual values (sh_d[]) of the current frame. The prediction values are
100  generated by averaging pixel values in the previous VOP; the block position in
101  the previous frame is computed from the current block's motion vector. The
102  computed pixel values are calculated by adding the prediction values to the
103  block residual values.
104 
105 */
106 
107 /*----------------------------------------------------------------------------
108 ; INCLUDES
109 ----------------------------------------------------------------------------*/
110 #include "mp4dec_lib.h"
111 #include "motion_comp.h"
112 
113 #define PAD_CORNER {    temp = *prev; \
114             temp |= (temp<<8);  \
115             temp |= (temp<<16); \
116             *((uint32*)ptr) = temp; \
117             *((uint32*)(ptr+4)) = temp;  \
118             *((uint32*)(ptr+=16)) = temp;  \
119             *((uint32*)(ptr+4)) = temp;  \
120             *((uint32*)(ptr+=16)) = temp;  \
121             *((uint32*)(ptr+4)) = temp;  \
122             *((uint32*)(ptr+=16)) = temp;  \
123             *((uint32*)(ptr+4)) = temp;  \
124             *((uint32*)(ptr+=16)) = temp;  \
125             *((uint32*)(ptr+4)) = temp;  \
126             *((uint32*)(ptr+=16)) = temp;  \
127             *((uint32*)(ptr+4)) = temp;  \
128             *((uint32*)(ptr+=16)) = temp;  \
129             *((uint32*)(ptr+4)) = temp;  \
130             *((uint32*)(ptr+=16)) = temp;  \
131             *((uint32*)(ptr+4)) = temp;  }
132 
133 #define PAD_ROW  {  temp = *((uint32*)prev); \
134                     temp2 = *((uint32*)(prev+4)); \
135             *((uint32*)ptr) =  temp;\
136             *((uint32*)(ptr+4)) =  temp2; \
137             *((uint32*)(ptr+=16)) = temp; \
138             *((uint32*)(ptr+4)) = temp2;\
139             *((uint32*)(ptr+=16)) = temp; \
140             *((uint32*)(ptr+4)) = temp2;\
141             *((uint32*)(ptr+=16)) = temp; \
142             *((uint32*)(ptr+4)) = temp2;\
143             *((uint32*)(ptr+=16)) = temp; \
144             *((uint32*)(ptr+4)) = temp2;\
145             *((uint32*)(ptr+=16)) = temp; \
146             *((uint32*)(ptr+4)) = temp2;\
147             *((uint32*)(ptr+=16)) = temp; \
148             *((uint32*)(ptr+4)) = temp2;\
149             *((uint32*)(ptr+=16)) = temp; \
150             *((uint32*)(ptr+4)) = temp2;}
151 
152 #define PAD_EXTRA_4x8           {   temp = *((uint32*)(prev+8)); \
153                 *((uint32*)ptr) =  temp; \
154                 *((uint32*)(ptr+=16)) = temp; \
155                 *((uint32*)(ptr+=16)) = temp; \
156                 *((uint32*)(ptr+=16)) = temp; \
157                 *((uint32*)(ptr+=16)) = temp; \
158                 *((uint32*)(ptr+=16)) = temp; \
159                 *((uint32*)(ptr+=16)) = temp; \
160                 *((uint32*)(ptr+=16)) = temp; }
161 
162 #define PAD_COL { temp = *prev; \
163             temp|=(temp<<8);  temp|=(temp<<16); \
164             *((uint32*)ptr) = temp; \
165             *((uint32*)(ptr+4)) = temp; \
166             temp = *(prev+=16); \
167             temp|=(temp<<8);  temp|=(temp<<16); \
168             *((uint32*)(ptr+=16)) = temp; \
169             *((uint32*)(ptr+4)) = temp; \
170             temp = *(prev+=16); \
171             temp|=(temp<<8);  temp|=(temp<<16); \
172             *((uint32*)(ptr+=16)) = temp; \
173             *((uint32*)(ptr+4)) = temp; \
174             temp = *(prev+=16); \
175             temp|=(temp<<8);  temp|=(temp<<16); \
176             *((uint32*)(ptr+=16)) = temp; \
177             *((uint32*)(ptr+4)) = temp; \
178             temp = *(prev+=16); \
179             temp|=(temp<<8);  temp|=(temp<<16); \
180             *((uint32*)(ptr+=16)) = temp; \
181             *((uint32*)(ptr+4)) = temp; \
182             temp = *(prev+=16); \
183             temp|=(temp<<8);  temp|=(temp<<16); \
184             *((uint32*)(ptr+=16)) = temp; \
185             *((uint32*)(ptr+4)) = temp; \
186             temp = *(prev+=16); \
187             temp|=(temp<<8);  temp|=(temp<<16); \
188             *((uint32*)(ptr+=16)) = temp; \
189             *((uint32*)(ptr+4)) = temp; \
190             temp = *(prev+=16); \
191             temp|=(temp<<8);  temp|=(temp<<16); \
192             *((uint32*)(ptr+=16)) = temp; \
193             *((uint32*)(ptr+4)) = temp;}
194 
195 /* copy 8x8 block */
196 #define COPY_BLOCK  {           *((uint32*)ptr) = *((uint32*)prev); \
197             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
198             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
199             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
200             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
201             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
202             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
203             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
204             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
205             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
206             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
207             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
208             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
209             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
210             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
211             *((uint32*)(ptr+4)) = *((uint32*)(prev+4));  }
212 
213 #define COPY_12x8       {       *((uint32*)ptr) = *((uint32*)prev); \
214             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
215             *((uint32*)(ptr+8)) = *((uint32*)(prev+8)); \
216             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
217             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
218             *((uint32*)(ptr+8)) = *((uint32*)(prev+8)); \
219             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
220             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
221             *((uint32*)(ptr+8)) = *((uint32*)(prev+8)); \
222             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
223             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
224             *((uint32*)(ptr+8)) = *((uint32*)(prev+8)); \
225             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
226             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
227             *((uint32*)(ptr+8)) = *((uint32*)(prev+8)); \
228             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
229             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
230             *((uint32*)(ptr+8)) = *((uint32*)(prev+8)); \
231             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
232             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
233             *((uint32*)(ptr+8)) = *((uint32*)(prev+8)); \
234             *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
235             *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
236             *((uint32*)(ptr+8)) = *((uint32*)(prev+8)); }
237 
238 /*----------------------------------------------------------------------------
239 ; FUNCTION CODE
240 ----------------------------------------------------------------------------*/
GetPredOutside(int xpos,int ypos,uint8 * c_prev,uint8 * pred_block,int width,int height,int rnd1,int pred_width)241 int GetPredOutside(
242     int xpos,       /* i */
243     int ypos,       /* i */
244     uint8 *c_prev,      /* i */
245     uint8 *pred_block,      /* i */
246     int width,      /* i */
247     int height,     /* i */
248     int rnd1,       /* i */
249     int pred_width
250 )
251 {
252     /*----------------------------------------------------------------------------
253     ; Define all local variables
254     ----------------------------------------------------------------------------*/
255     uint8   *prev;      /* pointers to adjacent pixels in the    */
256     uint8   pred[256];  /* storage for padded pixel values, 16x16 */
257     uint8   *ptr;
258     int xoffset;
259     uint32 temp, temp2;
260 
261     /*----------------------------------------------------------------------------
262     ; Function body here
263     ----------------------------------------------------------------------------*/
264     /* saturate xpos and ypos */
265     if (xpos < -16) xpos = -16;
266     if (xpos > ((width - 1) << 1)) xpos = (width - 1) << 1;
267     if (ypos < -16) ypos = -16;
268     if (ypos > ((height - 1) << 1)) ypos = (height - 1) << 1;
269 
270     if (xpos < 0)
271     {
272         if (ypos < 0) /* pad top left of frame */
273         {
274             /* copy the block */
275             ptr = pred + (8 << 4) + 8;
276             prev = c_prev;
277             COPY_BLOCK
278 
279             /* pad the corner */
280             ptr = pred;
281             prev = pred + (8 << 4) + 8;
282             PAD_CORNER
283 
284             /* pad top */
285             ptr = pred + 8;
286             prev = pred + (8 << 4) + 8;
287             PAD_ROW
288 
289             /* pad left */
290             ptr = pred + (8 << 4);
291             prev = pred + (8 << 4) + 8;
292             PAD_COL
293 
294 
295             ptr = pred + (((ypos >> 1) + 8) << 4) + (xpos >> 1) + 8;
296 
297             GetPredAdvBTable[ypos&1][xpos&1](ptr, pred_block, 16, (pred_width << 1) | rnd1);
298 
299             return 1;
300         }
301         else if ((ypos >> 1) < (height - B_SIZE)) /* pad left of frame */
302         {
303             /* copy block */
304             ptr = pred + 8;
305             prev = c_prev + (ypos >> 1) * width;
306             COPY_BLOCK
307             /* copy extra line */
308             *((uint32*)(ptr += 16)) = *((uint32*)(prev += width));
309             *((uint32*)(ptr + 4)) = *((uint32*)(prev + 4));
310 
311             /* pad left */
312             ptr = pred;
313             prev = pred + 8;
314             PAD_COL
315             /* pad extra line */
316             temp = *(prev += 16);
317             temp |= (temp << 8);
318             temp |= (temp << 16);
319             *((uint32*)(ptr += 16)) = temp;
320             *((uint32*)(ptr + 4)) = temp;
321 
322             ptr = pred + 8 + (xpos >> 1);
323 
324             GetPredAdvBTable[ypos&1][xpos&1](ptr, pred_block, 16, (pred_width << 1) | rnd1);
325 
326             return 1;
327         }
328         else /* pad bottom left of frame */
329         {
330             /* copy the block */
331             ptr = pred + 8; /* point to the center */
332             prev = c_prev + width * (height - 8);
333             COPY_BLOCK
334 
335             /* pad the corner */
336             ptr = pred + (8 << 4);
337             prev = ptr - 8;
338             PAD_CORNER
339 
340             /* pad bottom */
341             ptr = pred + (8 << 4) + 8;
342             prev = ptr - 16;
343             PAD_ROW
344 
345             /* pad left */
346             ptr = pred ;
347             prev = ptr + 8;
348             PAD_COL
349 
350             ptr = pred + 8 + (((ypos >> 1) - (height - 8)) << 4) + (xpos >> 1);
351 
352             GetPredAdvBTable[ypos&1][xpos&1](ptr, pred_block, 16, (pred_width << 1) | rnd1);
353 
354             return 1;
355         }
356     }
357     else if ((xpos >> 1) < (width - B_SIZE))
358     {
359         if (ypos < 0) /* pad top of frame */
360         {
361             xoffset = xpos >> 1;
362             xoffset = xoffset & 0x3; /* word align ptr */
363 
364             /* copy block */
365             ptr = pred + (8 << 4);
366             prev = c_prev + (xpos >> 1) - xoffset;
367 
368             if (xoffset || (xpos&1)) /* copy extra 4x8 */
369             {
370                 COPY_12x8
371             }
372             else
373             {
374                 COPY_BLOCK
375             }
376 
377             /* pad top */
378             ptr = pred;
379             prev = pred + (8 << 4);
380             PAD_ROW
381             if (xoffset || (xpos&1)) /* pad extra 4x8 */
382             {
383                 ptr = pred + 8;
384                 PAD_EXTRA_4x8
385             }
386 
387             ptr = pred + (((ypos >> 1) + 8) << 4) + xoffset;
388 
389             GetPredAdvBTable[ypos&1][xpos&1](ptr, pred_block, 16, (pred_width << 1) | rnd1);
390 
391             return 1;
392         }
393         else /* pad bottom of frame */
394         {
395             xoffset = xpos >> 1;
396             xoffset = xoffset & 0x3; /* word align ptr */
397             /* copy block */
398             ptr = pred ;
399             prev = c_prev + width * (height - 8) + (xpos >> 1) - xoffset;
400             if (xoffset  || (xpos&1))
401             {
402                 COPY_12x8
403             }
404             else
405             {
406                 COPY_BLOCK
407             }
408 
409             /* pad bottom */
410             ptr = pred + (8 << 4);
411             prev = ptr - 16;
412             PAD_ROW
413             if (xoffset || (xpos&1))
414             {
415                 ptr = pred + (8 << 4) + 8;
416                 PAD_EXTRA_4x8
417             }
418 
419             ptr = pred + (((ypos >> 1) - (height - 8)) << 4) + xoffset;
420 
421             GetPredAdvBTable[ypos&1][xpos&1](ptr, pred_block, 16, (pred_width << 1) | rnd1);
422 
423             return 1;
424         }
425     }
426     else
427     {
428         if (ypos < 0) /* pad top right of frame */
429         {
430             /* copy block */
431             ptr = pred + (8 << 4);
432             prev = c_prev + width - 8;
433             COPY_BLOCK
434 
435             /* pad top-right */
436             ptr = pred + 8;
437             prev = pred + (8 << 4) + 7;
438             PAD_CORNER
439 
440             /* pad top */
441             ptr = pred ;
442             prev = pred + (8 << 4);
443             PAD_ROW;
444 
445             /* pad right */
446             ptr = pred + (8 << 4) + 8;
447             prev = ptr - 1;
448             PAD_COL;
449 
450             ptr = pred + ((8 + (ypos >> 1)) << 4) + (8 - (width - (xpos >> 1)));
451 
452             GetPredAdvBTable[ypos&1][xpos&1](ptr, pred_block, 16, (pred_width << 1) | rnd1);
453 
454             return 1;
455         }
456         else if ((ypos >> 1) < (height - B_SIZE)) /* pad right of frame */
457         {
458             /* copy block */
459             ptr = pred;
460             prev = c_prev + (ypos >> 1) * width + width - 8;
461             COPY_BLOCK
462             /* copy extra line */
463             *((uint32*)(ptr += 16)) = *((uint32*)(prev += width));
464             *((uint32*)(ptr + 4)) = *((uint32*)(prev + 4));
465 
466             /* pad right */
467             ptr = pred + 8;
468             prev = ptr - 1;
469             PAD_COL;
470             /* pad extra line */
471             temp = *(prev += 16);
472             temp |= (temp << 8);
473             temp |= (temp << 16);
474             *((uint32*)(ptr += 16)) = temp;
475             *((uint32*)(ptr + 4)) = temp;
476 
477 
478             ptr = pred + 8 - (width - (xpos >> 1));
479 
480             GetPredAdvBTable[ypos&1][xpos&1](ptr, pred_block, 16, (pred_width << 1) | rnd1);
481 
482             return 1;
483 
484         }
485         else /* pad bottom right of frame */
486         {
487             /* copy block */
488             ptr = pred;
489             prev = c_prev + width * (height - 8) + width - 8;
490             COPY_BLOCK
491 
492             /* pad bottom-right */
493             ptr = pred + (8 << 4) + 8;
494             prev = ptr - 17;
495             PAD_CORNER
496 
497             /* pad right */
498             ptr = pred + 8;
499             prev = ptr - 1;
500             PAD_COL
501 
502             /* pad bottom */
503             ptr = pred + (8 << 4);
504             prev = ptr - 16;
505             PAD_ROW
506 
507             ptr = pred + 8 - (width - (xpos >> 1)) + ((8 - (height - (ypos >> 1))) << 4);
508 
509             GetPredAdvBTable[ypos&1][xpos&1](ptr, pred_block, 16, (pred_width << 1) | rnd1);
510 
511             return 1;
512         }
513     }
514 }
515