1 /*****************************************************************************
2 * csp.c: h264 encoder library
3 *****************************************************************************
4 * Copyright (C) 2004 Laurent Aimar
5 * $Id: csp.c,v 1.1 2004/06/03 19:27:06 fenrir Exp $
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
29 static inline void plane_copy( uint8_t *dst, int i_dst,
30 uint8_t *src, int i_src, int w, int h)
34 memcpy( dst, src, w );
39 static inline void plane_copy_vflip( uint8_t *dst, int i_dst,
40 uint8_t *src, int i_src, int w, int h)
42 plane_copy( dst, i_dst, src + (h -1)*i_src, -i_src, w, h );
45 static inline void plane_subsamplev2( uint8_t *dst, int i_dst,
46 uint8_t *src, int i_src, int w, int h)
53 for( i = 0; i < w; i++ )
55 *d++ = ( s[0] + s[i_src] + 1 ) >> 1;
63 static inline void plane_subsamplev2_vlip( uint8_t *dst, int i_dst,
64 uint8_t *src, int i_src, int w, int h)
66 plane_subsamplev2( dst, i_dst, src + (2*h-1)*i_src, -i_src, w, h );
69 static inline void plane_subsamplehv2( uint8_t *dst, int i_dst,
70 uint8_t *src, int i_src, int w, int h)
77 for( i = 0; i < w; i++ )
79 *d++ = ( s[0] + s[1] + s[i_src] + s[i_src+1] + 1 ) >> 2;
87 static inline void plane_subsamplehv2_vlip( uint8_t *dst, int i_dst,
88 uint8_t *src, int i_src, int w, int h)
90 plane_subsamplehv2( dst, i_dst, src + (2*h-1)*i_src, -i_src, w, h );
93 static void i420_to_i420( x264_frame_t *frm, x264_image_t *img,
94 int i_width, int i_height )
96 if( img->i_csp & X264_CSP_VFLIP )
98 plane_copy_vflip( frm->plane[0], frm->i_stride[0],
99 img->plane[0], img->i_stride[0],
101 plane_copy_vflip( frm->plane[1], frm->i_stride[1],
102 img->plane[1], img->i_stride[1],
103 i_width / 2, i_height / 2 );
104 plane_copy_vflip( frm->plane[2], frm->i_stride[2],
105 img->plane[2], img->i_stride[2],
106 i_width / 2, i_height / 2 );
110 plane_copy( frm->plane[0], frm->i_stride[0],
111 img->plane[0], img->i_stride[0],
113 plane_copy( frm->plane[1], frm->i_stride[1],
114 img->plane[1], img->i_stride[1],
115 i_width / 2, i_height / 2 );
116 plane_copy( frm->plane[2], frm->i_stride[2],
117 img->plane[2], img->i_stride[2],
118 i_width / 2, i_height / 2 );
122 static void yv12_to_i420( x264_frame_t *frm, x264_image_t *img,
123 int i_width, int i_height )
125 if( img->i_csp & X264_CSP_VFLIP )
127 plane_copy_vflip( frm->plane[0], frm->i_stride[0],
128 img->plane[0], img->i_stride[0],
130 plane_copy_vflip( frm->plane[2], frm->i_stride[2],
131 img->plane[1], img->i_stride[1],
132 i_width / 2, i_height / 2 );
133 plane_copy_vflip( frm->plane[1], frm->i_stride[1],
134 img->plane[2], img->i_stride[2],
135 i_width / 2, i_height / 2 );
139 plane_copy( frm->plane[0], frm->i_stride[0],
140 img->plane[0], img->i_stride[0],
142 plane_copy( frm->plane[2], frm->i_stride[2],
143 img->plane[1], img->i_stride[1],
144 i_width / 2, i_height / 2 );
145 plane_copy( frm->plane[1], frm->i_stride[1],
146 img->plane[2], img->i_stride[2],
147 i_width / 2, i_height / 2 );
151 static void i422_to_i420( x264_frame_t *frm, x264_image_t *img,
152 int i_width, int i_height )
154 if( img->i_csp & X264_CSP_VFLIP )
156 plane_copy_vflip( frm->plane[0], frm->i_stride[0],
157 img->plane[0], img->i_stride[0],
160 plane_subsamplev2_vlip( frm->plane[1], frm->i_stride[1],
161 img->plane[1], img->i_stride[1],
162 i_width / 2, i_height / 2 );
163 plane_subsamplev2_vlip( frm->plane[2], frm->i_stride[2],
164 img->plane[2], img->i_stride[2],
165 i_width / 2, i_height / 2 );
169 plane_copy( frm->plane[0], frm->i_stride[0],
170 img->plane[0], img->i_stride[0],
173 plane_subsamplev2( frm->plane[1], frm->i_stride[1],
174 img->plane[1], img->i_stride[1],
175 i_width / 2, i_height / 2 );
176 plane_subsamplev2( frm->plane[2], frm->i_stride[2],
177 img->plane[2], img->i_stride[2],
178 i_width / 2, i_height / 2 );
182 static void i444_to_i420( x264_frame_t *frm, x264_image_t *img,
183 int i_width, int i_height )
185 if( img->i_csp & X264_CSP_VFLIP )
187 plane_copy_vflip( frm->plane[0], frm->i_stride[0],
188 img->plane[0], img->i_stride[0],
191 plane_subsamplehv2_vlip( frm->plane[1], frm->i_stride[1],
192 img->plane[1], img->i_stride[1],
193 i_width / 2, i_height / 2 );
194 plane_subsamplehv2_vlip( frm->plane[2], frm->i_stride[2],
195 img->plane[2], img->i_stride[2],
196 i_width / 2, i_height / 2 );
200 plane_copy( frm->plane[0], frm->i_stride[0],
201 img->plane[0], img->i_stride[0],
204 plane_subsamplehv2( frm->plane[1], frm->i_stride[1],
205 img->plane[1], img->i_stride[1],
206 i_width / 2, i_height / 2 );
207 plane_subsamplehv2( frm->plane[2], frm->i_stride[2],
208 img->plane[2], img->i_stride[2],
209 i_width / 2, i_height / 2 );
212 static void yuyv_to_i420( x264_frame_t *frm, x264_image_t *img,
213 int i_width, int i_height )
215 uint8_t *src = img->plane[0];
216 int i_src= img->i_stride[0];
218 uint8_t *y = frm->plane[0];
219 uint8_t *u = frm->plane[1];
220 uint8_t *v = frm->plane[2];
222 if( img->i_csp & X264_CSP_VFLIP )
224 src += ( i_height - 1 ) * i_src;
228 for( ; i_height > 0; i_height -= 2 )
236 for( w = i_width; w > 0; w -= 2 )
241 *uu++ = ( ss[1] + ss[1+i_src] + 1 ) >> 1;
242 *vv++ = ( ss[3] + ss[3+i_src] + 1 ) >> 1;
247 y += frm->i_stride[0];
248 u += frm->i_stride[1];
249 v += frm->i_stride[2];
253 for( w = i_width; w > 0; w -= 2 )
260 y += frm->i_stride[0];
264 /* Same value than in XviD */
266 #define FIX(f) ((int)((f) * (1 << BITS) + 0.5))
268 #define Y_R FIX(0.257)
269 #define Y_G FIX(0.504)
270 #define Y_B FIX(0.098)
273 #define U_R FIX(0.148)
274 #define U_G FIX(0.291)
275 #define U_B FIX(0.439)
278 #define V_R FIX(0.439)
279 #define V_G FIX(0.368)
280 #define V_B FIX(0.071)
282 #define RGB_TO_I420( name, POS_R, POS_G, POS_B, S_RGB ) \
283 static void name( x264_frame_t *frm, x264_image_t *img, \
284 int i_width, int i_height ) \
286 uint8_t *src = img->plane[0]; \
287 int i_src= img->i_stride[0]; \
288 int i_y = frm->i_stride[0]; \
289 uint8_t *y = frm->plane[0]; \
290 uint8_t *u = frm->plane[1]; \
291 uint8_t *v = frm->plane[2]; \
293 if( img->i_csp & X264_CSP_VFLIP ) \
295 src += ( i_height - 1 ) * i_src; \
299 for( ; i_height > 0; i_height -= 2 ) \
307 for( w = i_width; w > 0; w -= 2 ) \
309 int cr = 0,cg = 0,cb = 0; \
313 cr = r = ss[POS_R]; \
314 cg = g = ss[POS_G]; \
315 cb = b = ss[POS_B]; \
317 yy[0] = Y_ADD + ((Y_R * r + Y_G * g + Y_B * b) >> BITS); \
319 cr+= r = ss[POS_R+i_src]; \
320 cg+= g = ss[POS_G+i_src]; \
321 cb+= b = ss[POS_B+i_src]; \
322 yy[i_y] = Y_ADD + ((Y_R * r + Y_G * g + Y_B * b) >> BITS); \
326 cr+= r = ss[POS_R]; \
327 cg+= g = ss[POS_G]; \
328 cb+= b = ss[POS_B]; \
330 yy[0] = Y_ADD + ((Y_R * r + Y_G * g + Y_B * b) >> BITS); \
332 cr+= r = ss[POS_R+i_src]; \
333 cg+= g = ss[POS_G+i_src]; \
334 cb+= b = ss[POS_B+i_src]; \
335 yy[i_y] = Y_ADD + ((Y_R * r + Y_G * g + Y_B * b) >> BITS); \
340 *uu++ = (uint8_t)(U_ADD + ((-U_R * cr - U_G * cg + U_B * cb) >> (BITS+2)) ); \
341 *vv++ = (uint8_t)(V_ADD + (( V_R * cr - V_G * cg - V_B * cb) >> (BITS+2)) ); \
345 y += 2*frm->i_stride[0]; \
346 u += frm->i_stride[1]; \
347 v += frm->i_stride[2]; \
351 RGB_TO_I420( rgb_to_i420, 0, 1, 2, 3 );
352 RGB_TO_I420( bgr_to_i420, 2, 1, 0, 3 );
353 RGB_TO_I420( bgra_to_i420, 2, 1, 0, 4 );
355 void x264_csp_init( int cpu, int i_csp, x264_csp_function_t *pf )
360 pf->i420 = i420_to_i420;
361 pf->i422 = i422_to_i420;
362 pf->i444 = i444_to_i420;
363 pf->yv12 = yv12_to_i420;
364 pf->yuyv = yuyv_to_i420;
365 pf->rgb = rgb_to_i420;
366 pf->bgr = bgr_to_i420;
367 pf->bgra = bgra_to_i420;
371 /* For now, can't happen */
372 fprintf( stderr, "arg in x264_csp_init\n" );