1 #include <VLIB/P264/p264_inter_mc.h>
2 #include <VP_Os/vp_os_malloc.h>
3 #include <VP_Os/vp_os_assert.h>
5 typedef struct _part_dim_t {
10 // LUT table to retrieve partition dimension. part_dim[inter_partition_mode_t]
11 static part_dim_t part_dim[NB_PARTITION] =
13 {16,16},{16,8},{8,16},{8,8},{8,4},{4,8},{4,4}
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)
21 // return top left reference pixel
24 else if (x>=(int32_t)picture_width && y>=(int32_t)picture_height)
26 // return bottom right pixel
27 return *(picture + picture_height*linesize - 1);
29 else if (x>=(int32_t)picture_width && y<0)
31 // return top right ref pixel
32 return *(picture + picture_width - 1);
34 else if (x<0 && y>=(int32_t)picture_height)
36 // return bottom left ref pixel
37 return *(picture + (picture_height-1)*linesize );
41 // return first column pixel
42 return *(picture+y*linesize);
46 // return first line pixel
49 else if (x>=(int32_t)picture_width)
51 // return last column pixel
52 return *(picture + y*linesize + picture_width - 1);
54 else if (y>=(int32_t)picture_height)
56 // return last line pixel
57 return *(picture + (picture_height-1)*linesize + x);
62 return *(picture + y*linesize + x);
66 // ________________ ________________
67 // | ref_picture | picture being decoding
70 // | |_________| ===> |
72 // | | (mv) | | refblock| [Motion compensation]
74 // |________________ |________________
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)
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
89 uint8_t *picture_ref_start = picture_ref;
90 uint8_t *picture_start = picture;
92 // compute coordinates of ref_block
94 int32_t block_dim_x,block_dim_y;
96 x_ref = ((int32_t)x)+mv.x;
97 y_ref = ((int32_t)y)+mv.y;
99 // retrieve block dimensions
100 block_dim_x = part_dim[partition].x;
101 block_dim_y = part_dim[partition].y;
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;
109 (x_ref+block_dim_x) <= (int32_t)picture_width &&
111 (y_ref+block_dim_y) <= (int32_t)picture_height)
113 // ref block is not out of boundary
114 // make a simple copy on the luma sample
115 while (block_dim_y--)
118 vp_os_memcpy(picture,picture_ref,block_dim_x);
120 picture_ref += linesize;
126 // ref block is out of boundary
127 // ref picture boundary pixel are extended when necessary
129 for (j=y_ref;j<(block_dim_y+y_ref);j++)
131 for (i=x_ref;i<(block_dim_x+x_ref);i++)
133 *picture++ = get_pixel(i,j,picture_ref_start,linesize,picture_width,picture_height);
135 picture += linesize - block_dim_x;
141 // chroma interpollation
147 // - <-dx-> a <-(8-dx)->
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 ://
159 // a = round[(A+B)>>1]
160 // b = round[(A+C)>>1]
161 // c = round[(A+B+C+D)>>2]
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)
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
173 //uint8_t *picture_start = picture;
175 // compute integer coordinates of ref_block
177 bool_t x_half_pel,y_half_pel;
179 int32_t block_dim_x,block_dim_y;
182 x_ref = ((int32_t)x)+mv.x/2;
184 x_ref = ((int32_t)x)+(mv.x-1)/2;
186 if ((mv.x&0x01) == 0)
195 y_ref = ((int32_t)y)+mv.y/2;
197 y_ref = ((int32_t)y)+(mv.y-1)/2;
199 if ((mv.y&0x01) == 0)
207 // jump to destination position in picture
208 picture += y*linesize + x;
210 // retrieve block dimensions
211 block_dim_x = part_dim[partition].x>>1;
212 block_dim_y = part_dim[partition].y>>1;
214 // interpolate chroma from picture_ref to picture
217 for (j=y_ref;j<(block_dim_y+y_ref);j++)
219 for (i=x_ref;i<(block_dim_x+x_ref);i++)
222 pel = get_pixel(i,j,picture_ref,linesize,picture_width,picture_height);
223 //pel = *picture_ref;
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);
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);
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);
237 // scale pel and set picture pixel
238 *picture++ = pel>>scale;
240 picture += linesize - block_dim_x;