libandroidplugin added
[mardrone] / mardrone / ARDrone_SDK_Version_1_8_20110726 / ARDroneLib / VLIB / P264 / p264_inter_mc.c
1 #include <VLIB/P264/p264_inter_mc.h>
2 #include <VP_Os/vp_os_malloc.h>
3 #include <VP_Os/vp_os_assert.h>
4 // partition dimension
5 typedef struct _part_dim_t {
6   uint32_t x;
7   uint32_t y;
8 } part_dim_t;
9
10 // LUT table to retrieve partition dimension. part_dim[inter_partition_mode_t]
11 static part_dim_t part_dim[NB_PARTITION] =
12 {
13   {16,16},{16,8},{8,16},{8,8},{8,4},{4,8},{4,4}
14 };
15
16 // return pixel(i,j) from picture. if (i,j) is out of the image, boundary pixel are returned.
17 static uint8_t get_pixel(int32_t x, int32_t y, uint8_t* picture, uint32_t linesize, uint32_t picture_width, uint32_t picture_height)
18 {
19   if (x<0 && y<0)
20   {
21     // return top left reference pixel
22     return  *picture;
23   }
24   else if (x>=(int32_t)picture_width && y>=(int32_t)picture_height)
25   {
26     // return bottom right pixel
27     return  *(picture + picture_height*linesize - 1);
28   }
29   else if (x>=(int32_t)picture_width && y<0)
30   {
31     // return top right ref pixel
32     return  *(picture + picture_width - 1);
33   }
34   else if (x<0 && y>=(int32_t)picture_height)
35   {
36     // return bottom left ref pixel
37     return  *(picture + (picture_height-1)*linesize );
38   }
39   else if (x<0)
40   {
41     // return first column pixel
42     return  *(picture+y*linesize);
43   }
44   else if (y<0)
45   {
46     // return first line pixel
47     return  *(picture+x);
48   }
49   else if (x>=(int32_t)picture_width)
50   {
51     // return last column pixel
52     return  *(picture + y*linesize + picture_width - 1);
53   }
54   else if (y>=(int32_t)picture_height)
55   {
56     // return last line pixel
57     return  *(picture + (picture_height-1)*linesize + x);
58   }
59   else
60   {
61     //return ref pixel
62     return  *(picture + y*linesize + x);
63   }
64 }
65
66 //  ________________           ________________
67 // | ref_picture              | picture being decoding
68 // |  _________               |
69 // | | refblock|              |
70 // | |_________|        ===>  |
71 // |       |                  |  _________
72 // |       | (mv)             | | refblock|     [Motion compensation]
73 // |       V                  | |_________|
74 // |________________          |________________
75
76
77 // move a block from picture_ref to picture at position (x,y).
78 void p264_inter_mc_luma (inter_partition_mode_t partition, MV_XY_t mv,uint8_t *picture_ref , uint8_t *picture, uint32_t x, uint32_t y, uint32_t picture_width, uint32_t picture_height, uint32_t linesize)
79 {
80   // partition : partition mode of the block to be moved (16x16, 16x8, 8x16, ...)
81   // mv : motion vector (in half pixel unit)
82   // picture_ref : picture reference
83   // picture : the dest picture to be motion compensated.
84   // x, y : coordinates of the destination block
85   // picture_width, picture_height : picture dimensions
86   // linesize : pixel line length inside picture. (it is assumed that picture and picture_ref have the same resolution/format)
87   // Note : this function supports only integer MV on luma component
88
89   uint8_t *picture_ref_start = picture_ref;
90   uint8_t *picture_start = picture;
91   //uint8_t temp_pixel;
92   // compute coordinates of ref_block
93   int32_t x_ref,y_ref;
94   int32_t block_dim_x,block_dim_y;
95
96   x_ref = ((int32_t)x)+mv.x;
97   y_ref = ((int32_t)y)+mv.y;
98
99   // retrieve block dimensions
100   block_dim_x = part_dim[partition].x;
101   block_dim_y = part_dim[partition].y;
102
103   // jump to destination position in picture
104   picture = picture_start + y*linesize + x;
105   // jump to source position in picture_ref
106   picture_ref = picture_ref_start + y_ref*linesize + x_ref;
107
108   if ( x_ref > 0 &&
109       (x_ref+block_dim_x) <= (int32_t)picture_width &&
110        y_ref > 0 &&
111       (y_ref+block_dim_y) <= (int32_t)picture_height)
112   {
113     // ref block is not out of boundary
114     // make a simple copy on the luma sample
115     while (block_dim_y--)
116     {
117       // copy line
118       vp_os_memcpy(picture,picture_ref,block_dim_x);
119       // jump to next line
120       picture_ref += linesize;
121       picture += linesize;
122     }
123   }
124   else
125   {
126     // ref block is out of boundary
127     // ref picture boundary pixel are extended when necessary
128     int32_t i,j;
129     for (j=y_ref;j<(block_dim_y+y_ref);j++)
130     {
131       for (i=x_ref;i<(block_dim_x+x_ref);i++)
132       {
133         *picture++ = get_pixel(i,j,picture_ref_start,linesize,picture_width,picture_height);
134       }
135       picture += linesize - block_dim_x;
136     }
137   }
138 }
139
140
141 // chroma interpollation
142 //
143 // A -  -  -  -  -  -  -  B
144 // -        |
145 // -       (dy)
146 // -        |
147 // - <-dx-> a <-(8-dx)->
148 // -        |
149 // -      (8-dy)
150 // -        |
151 // C -  -  -  -  -  -  -  D
152 //
153 // a = round([(8-dx)(8-dy)A + dx(8-dy)B + (8-dx)dyC + dxdyD]/64)
154 // if a is an half pel the formula is ://
155 // A a B
156 // b c
157 // C   D
158 //
159 // a = round[(A+B)>>1]
160 // b = round[(A+C)>>1]
161 // c = round[(A+B+C+D)>>2]
162
163 void p264_inter_mc_chroma (inter_partition_mode_t partition, MV_XY_t mv,uint8_t *picture_ref , uint8_t *picture, uint32_t x, uint32_t y, uint32_t picture_width, uint32_t picture_height, uint32_t linesize)
164 {
165   // partition : partition mode of the block to be moved (16x16, 16x8, 8x16, ...)
166   // mv : motion vector (in 1/2 pixel)
167   // picture_ref : picture reference
168   // picture : the dest picture to be motion compensated.
169   // x,y : coordinates of the destination block
170   // linesize : pixel line length inside picture. (it is assumed that picture and picture_ref have the same resolution/format
171   // Note : this function supports only half pixel MV on chroma
172
173   //uint8_t *picture_start = picture;
174
175   // compute integer coordinates of ref_block
176   int32_t x_ref,y_ref;
177   bool_t x_half_pel,y_half_pel;
178   uint32_t scale=0;
179   int32_t block_dim_x,block_dim_y;
180
181   if (mv.x > 0)
182     x_ref = ((int32_t)x)+mv.x/2;
183   else
184     x_ref = ((int32_t)x)+(mv.x-1)/2;
185
186   if ((mv.x&0x01) == 0)
187     x_half_pel = FALSE;
188   else
189   {
190     scale++;
191     x_half_pel = TRUE;
192   }
193
194   if (mv.y > 0)
195     y_ref = ((int32_t)y)+mv.y/2;
196   else
197     y_ref = ((int32_t)y)+(mv.y-1)/2;
198
199   if ((mv.y&0x01) == 0)
200     y_half_pel = FALSE;
201   else
202   {
203     y_half_pel = TRUE;
204     scale++;
205   }
206
207   // jump to destination position in picture
208   picture += y*linesize + x;
209
210   // retrieve block dimensions
211   block_dim_x = part_dim[partition].x>>1;
212   block_dim_y = part_dim[partition].y>>1;
213
214   // interpolate chroma from picture_ref to picture
215   int32_t i,j;
216   uint32_t pel;
217   for (j=y_ref;j<(block_dim_y+y_ref);j++)
218   {
219     for (i=x_ref;i<(block_dim_x+x_ref);i++)
220     {
221       // add pixel A
222       pel = get_pixel(i,j,picture_ref,linesize,picture_width,picture_height);
223       //pel = *picture_ref;
224       // add pixel B
225       if (x_half_pel == TRUE)
226         //pel += *(picture_ref+1);
227         pel += get_pixel(i+1,j,picture_ref,linesize,picture_width,picture_height);
228       // add pixel C
229       if (y_half_pel == TRUE)
230         //pel += *(picture_ref+linesize);
231         pel += get_pixel(i,j+1,picture_ref,linesize,picture_width,picture_height);
232       // add pixel D
233       if (y_half_pel == TRUE && x_half_pel == TRUE)
234         //pel += *(picture_ref+linesize+1);
235         pel += get_pixel(i+1,j+1,picture_ref,linesize,picture_width,picture_height);
236
237       // scale pel and set picture pixel
238       *picture++ = pel>>scale;
239     }
240     picture += linesize - block_dim_x;
241   }
242 }