]> git.sesse.net Git - x264/blob - common/csp.c
cosmetics: simplify #includes
[x264] / common / csp.c
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 $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
23
24 #include <stdio.h>
25 #include <string.h>
26
27 #include "common.h"
28
29 static inline void plane_copy( uint8_t *dst, int i_dst,
30                                uint8_t *src, int i_src, int w, int h)
31 {
32     for( ; h > 0; h-- )
33     {
34         memcpy( dst, src, w );
35         dst += i_dst;
36         src += i_src;
37     }
38 }
39 static inline void plane_copy_vflip( uint8_t *dst, int i_dst,
40                                      uint8_t *src, int i_src, int w, int h)
41 {
42     plane_copy( dst, i_dst, src + (h -1)*i_src, -i_src, w, h );
43 }
44
45 static inline void plane_subsamplev2( uint8_t *dst, int i_dst,
46                                       uint8_t *src, int i_src, int w, int h)
47 {
48     for( ; h > 0; h-- )
49     {
50         uint8_t *d = dst;
51         uint8_t *s = src;
52         int     i;
53         for( i = 0; i < w; i++ )
54         {
55             *d++ = ( s[0] + s[i_src] + 1 ) >> 1;
56             s++;
57         }
58         dst += i_dst;
59         src += 2 * i_src;
60     }
61 }
62
63 static inline void plane_subsamplev2_vlip( uint8_t *dst, int i_dst,
64                                            uint8_t *src, int i_src, int w, int h)
65 {
66     plane_subsamplev2( dst, i_dst, src + (2*h-1)*i_src, -i_src, w, h );
67 }
68
69 static inline void plane_subsamplehv2( uint8_t *dst, int i_dst,
70                                        uint8_t *src, int i_src, int w, int h)
71 {
72     for( ; h > 0; h-- )
73     {
74         uint8_t *d = dst;
75         uint8_t *s = src;
76         int     i;
77         for( i = 0; i < w; i++ )
78         {
79             *d++ = ( s[0] + s[1] + s[i_src] + s[i_src+1] + 1 ) >> 2;
80             s += 2;
81         }
82         dst += i_dst;
83         src += 2 * i_src;
84     }
85 }
86
87 static inline void plane_subsamplehv2_vlip( uint8_t *dst, int i_dst,
88                                             uint8_t *src, int i_src, int w, int h)
89 {
90     plane_subsamplehv2( dst, i_dst, src + (2*h-1)*i_src, -i_src, w, h );
91 }
92
93 static void i420_to_i420( x264_frame_t *frm, x264_image_t *img,
94                           int i_width, int i_height )
95 {
96     if( img->i_csp & X264_CSP_VFLIP )
97     {
98         plane_copy_vflip( frm->plane[0], frm->i_stride[0],
99                           img->plane[0], img->i_stride[0],
100                           i_width, i_height );
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 );
107     }
108     else
109     {
110         plane_copy( frm->plane[0], frm->i_stride[0],
111                     img->plane[0], img->i_stride[0],
112                     i_width, i_height );
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 );
119     }
120 }
121
122 static void yv12_to_i420( x264_frame_t *frm, x264_image_t *img,
123                           int i_width, int i_height )
124 {
125     if( img->i_csp & X264_CSP_VFLIP )
126     {
127         plane_copy_vflip( frm->plane[0], frm->i_stride[0],
128                           img->plane[0], img->i_stride[0],
129                           i_width, i_height );
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 );
136     }
137     else
138     {
139         plane_copy( frm->plane[0], frm->i_stride[0],
140                     img->plane[0], img->i_stride[0],
141                     i_width, i_height );
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 );
148     }
149 }
150
151 static void i422_to_i420( x264_frame_t *frm, x264_image_t *img,
152                           int i_width, int i_height )
153 {
154     if( img->i_csp & X264_CSP_VFLIP )
155     {
156         plane_copy_vflip( frm->plane[0], frm->i_stride[0],
157                           img->plane[0], img->i_stride[0],
158                           i_width, i_height );
159
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 );
166     }
167     else
168     {
169         plane_copy( frm->plane[0], frm->i_stride[0],
170                     img->plane[0], img->i_stride[0],
171                     i_width, i_height );
172
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 );
179     }
180 }
181
182 static void i444_to_i420( x264_frame_t *frm, x264_image_t *img,
183                           int i_width, int i_height )
184 {
185     if( img->i_csp & X264_CSP_VFLIP )
186     {
187         plane_copy_vflip( frm->plane[0], frm->i_stride[0],
188                           img->plane[0], img->i_stride[0],
189                           i_width, i_height );
190
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 );
197     }
198     else
199     {
200         plane_copy( frm->plane[0], frm->i_stride[0],
201                     img->plane[0], img->i_stride[0],
202                     i_width, i_height );
203
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 );
210     }
211 }
212 static void yuyv_to_i420( x264_frame_t *frm, x264_image_t *img,
213                           int i_width, int i_height )
214 {
215     uint8_t *src = img->plane[0];
216     int     i_src= img->i_stride[0];
217
218     uint8_t *y   = frm->plane[0];
219     uint8_t *u   = frm->plane[1];
220     uint8_t *v   = frm->plane[2];
221
222     if( img->i_csp & X264_CSP_VFLIP )
223     {
224         src += ( i_height - 1 ) * i_src;
225         i_src = -i_src;
226     }
227
228     for( ; i_height > 0; i_height -= 2 )
229     {
230         uint8_t *ss = src;
231         uint8_t *yy = y;
232         uint8_t *uu = u;
233         uint8_t *vv = v;
234         int w;
235
236         for( w = i_width; w > 0; w -= 2 )
237         {
238             *yy++ = ss[0];
239             *yy++ = ss[2];
240
241             *uu++ = ( ss[1] + ss[1+i_src] + 1 ) >> 1;
242             *vv++ = ( ss[3] + ss[3+i_src] + 1 ) >> 1;
243
244             ss += 4;
245         }
246         src += i_src;
247         y += frm->i_stride[0];
248         u += frm->i_stride[1];
249         v += frm->i_stride[2];
250
251         ss = src;
252         yy = y;
253         for( w = i_width; w > 0; w -= 2 )
254         {
255             *yy++ = ss[0];
256             *yy++ = ss[2];
257             ss += 4;
258         }
259         src += i_src;
260         y += frm->i_stride[0];
261     }
262 }
263
264 /* Same value than in XviD */
265 #define BITS 8
266 #define FIX(f) ((int)((f) * (1 << BITS) + 0.5))
267
268 #define Y_R   FIX(0.257)
269 #define Y_G   FIX(0.504)
270 #define Y_B   FIX(0.098)
271 #define Y_ADD 16
272
273 #define U_R   FIX(0.148)
274 #define U_G   FIX(0.291)
275 #define U_B   FIX(0.439)
276 #define U_ADD 128
277
278 #define V_R   FIX(0.439)
279 #define V_G   FIX(0.368)
280 #define V_B   FIX(0.071)
281 #define V_ADD 128
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 )           \
285 {                                                       \
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];                       \
292                                                         \
293     if( img->i_csp & X264_CSP_VFLIP )                   \
294     {                                                   \
295         src += ( i_height - 1 ) * i_src;                \
296         i_src = -i_src;                                 \
297     }                                                   \
298                                                         \
299     for(  ; i_height > 0; i_height -= 2 )               \
300     {                                                   \
301         uint8_t *ss = src;                              \
302         uint8_t *yy = y;                                \
303         uint8_t *uu = u;                                \
304         uint8_t *vv = v;                                \
305         int w;                                          \
306                                                         \
307         for( w = i_width; w > 0; w -= 2 )               \
308         {                                               \
309             int cr = 0,cg = 0,cb = 0;                   \
310             int r, g, b;                                \
311                                                         \
312             /* Luma */                                  \
313             cr = r = ss[POS_R];                         \
314             cg = g = ss[POS_G];                         \
315             cb = b = ss[POS_B];                         \
316                                                         \
317             yy[0] = Y_ADD + ((Y_R * r + Y_G * g + Y_B * b) >> BITS);    \
318                                                         \
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);  \
323             yy++;                                       \
324             ss += S_RGB;                                \
325                                                         \
326             cr+= r = ss[POS_R];                         \
327             cg+= g = ss[POS_G];                         \
328             cb+= b = ss[POS_B];                         \
329                                                         \
330             yy[0] = Y_ADD + ((Y_R * r + Y_G * g + Y_B * b) >> BITS);    \
331                                                         \
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);  \
336             yy++;                                       \
337             ss += S_RGB;                                \
338                                                         \
339             /* Chroma */                                \
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)) ); \
342         }                                               \
343                                                         \
344         src += 2*i_src;                                   \
345         y += 2*frm->i_stride[0];                        \
346         u += frm->i_stride[1];                          \
347         v += frm->i_stride[2];                          \
348     }                                                   \
349 }
350
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 );
354
355 void x264_csp_init( int cpu, int i_csp, x264_csp_function_t *pf )
356 {
357     switch( i_csp )
358     {
359         case X264_CSP_I420:
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;
368             break;
369
370         default:
371             /* For now, can't happen */
372             fprintf( stderr, "arg in x264_csp_init\n" );
373             exit( -1 );
374             break;
375     }
376 }
377