Chroma API change. Chromas are now normal video filters (almost).
[vlc.git] / modules / video_chroma / yuy2_i422.c
1 /*****************************************************************************
2  * yuy2_i422.c : Packed YUV 4:2:2 to Planar YUV conversion module for vlc
3  *****************************************************************************
4  * Copyright (C) 2007 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Antoine Cellerier <dionoea at videolan dot org>
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
34 #include <vlc_filter.h>
35 #include <vlc_vout.h>
36
37 #define SRC_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,cyuv"
38 #define DEST_FOURCC  "I422"
39
40 /*****************************************************************************
41  * Local and extern prototypes.
42  *****************************************************************************/
43 static int  Activate ( vlc_object_t * );
44
45 static void YUY2_I422           ( filter_t *, picture_t *, picture_t * );
46 static void YVYU_I422           ( filter_t *, picture_t *, picture_t * );
47 static void UYVY_I422           ( filter_t *, picture_t *, picture_t * );
48 static void cyuv_I422           ( filter_t *, picture_t *, picture_t * );
49
50 /*****************************************************************************
51  * Module descriptor
52  *****************************************************************************/
53 vlc_module_begin();
54     set_description( N_("Conversions from " SRC_FOURCC " to " DEST_FOURCC) );
55     set_capability( "chroma", 80 );
56     set_callbacks( Activate, NULL );
57 vlc_module_end();
58
59 /*****************************************************************************
60  * Activate: allocate a chroma function
61  *****************************************************************************
62  * This function allocates and initializes a chroma function
63  *****************************************************************************/
64 static int Activate( vlc_object_t *p_this )
65 {
66     filter_t *p_filter = (filter_t *)p_this;
67
68     if( p_filter->fmt_in.video.i_width & 1
69      || p_filter->fmt_in.video.i_height & 1 )
70     {
71         return -1;
72     }
73
74     switch( p_filter->fmt_out.video.i_chroma )
75     {
76         case VLC_FOURCC('I','4','2','2'):
77             switch( p_filter->fmt_in.video.i_chroma )
78             {
79                 case VLC_FOURCC('Y','U','Y','2'):
80                 case VLC_FOURCC('Y','U','N','V'):
81                     p_filter->pf_video_filter_io = YUY2_I422;
82                     break;
83
84                 case VLC_FOURCC('Y','V','Y','U'):
85                     p_filter->pf_video_filter_io = YVYU_I422;
86                     break;
87
88                 case VLC_FOURCC('U','Y','V','Y'):
89                 case VLC_FOURCC('U','Y','N','V'):
90                 case VLC_FOURCC('Y','4','2','2'):
91                     p_filter->pf_video_filter_io = UYVY_I422;
92                     break;
93
94                 case VLC_FOURCC('c','y','u','v'):
95                     p_filter->pf_video_filter_io = cyuv_I422;
96                     break;
97
98                 default:
99                     return -1;
100             }
101             break;
102
103         default:
104             return -1;
105     }
106     return 0;
107 }
108
109 /* Following functions are local */
110
111 /*****************************************************************************
112  * YUY2_I422: packed YUY2 4:2:2 to planar YUV 4:2:2
113  *****************************************************************************/
114 static void YUY2_I422( filter_t *p_filter, picture_t *p_source,
115                                            picture_t *p_dest )
116 {
117     uint8_t *p_line = p_source->p->p_pixels;
118
119     uint8_t *p_y = p_dest->Y_PIXELS;
120     uint8_t *p_u = p_dest->U_PIXELS;
121     uint8_t *p_v = p_dest->V_PIXELS;
122
123     int i_x, i_y;
124
125     const int i_dest_margin = p_dest->p[0].i_pitch
126                                  - p_dest->p[0].i_visible_pitch;
127     const int i_dest_margin_c = p_dest->p[1].i_pitch
128                                  - p_dest->p[1].i_visible_pitch;
129     const int i_source_margin = p_source->p->i_pitch
130                                - p_source->p->i_visible_pitch;
131
132     for( i_y = p_filter->fmt_out.video.i_height ; i_y-- ; )
133     {
134         for( i_x = p_filter->fmt_out.video.i_width / 8 ; i_x-- ; )
135         {
136 #define C_YUYV_YUV422( p_line, p_y, p_u, p_v )      \
137             *p_y++ = *p_line++; *p_u++ = *p_line++; \
138             *p_y++ = *p_line++; *p_v++ = *p_line++
139             C_YUYV_YUV422( p_line, p_y, p_u, p_v );
140             C_YUYV_YUV422( p_line, p_y, p_u, p_v );
141             C_YUYV_YUV422( p_line, p_y, p_u, p_v );
142             C_YUYV_YUV422( p_line, p_y, p_u, p_v );
143         }
144         for( i_x = ( p_filter->fmt_out.video.i_width % 8 ) / 2; i_x-- ; )
145         {
146             C_YUYV_YUV422( p_line, p_y, p_u, p_v );
147         }
148         p_line += i_source_margin;
149         p_y += i_dest_margin;
150         p_u += i_dest_margin_c;
151         p_v += i_dest_margin_c;
152     }
153 }
154
155 /*****************************************************************************
156  * YVYU_I422: packed YVYU 4:2:2 to planar YUV 4:2:2
157  *****************************************************************************/
158 static void YVYU_I422( filter_t *p_filter, picture_t *p_source,
159                                            picture_t *p_dest )
160 {
161     uint8_t *p_line = p_source->p->p_pixels;
162
163     uint8_t *p_y = p_dest->Y_PIXELS;
164     uint8_t *p_u = p_dest->U_PIXELS;
165     uint8_t *p_v = p_dest->V_PIXELS;
166
167     int i_x, i_y;
168
169     const int i_dest_margin = p_dest->p[0].i_pitch
170                                  - p_dest->p[0].i_visible_pitch;
171     const int i_dest_margin_c = p_dest->p[1].i_pitch
172                                  - p_dest->p[1].i_visible_pitch;
173     const int i_source_margin = p_source->p->i_pitch
174                                - p_source->p->i_visible_pitch;
175
176     for( i_y = p_filter->fmt_out.video.i_height ; i_y-- ; )
177     {
178         for( i_x = p_filter->fmt_out.video.i_width / 8 ; i_x-- ; )
179         {
180 #define C_YVYU_YUV422( p_line, p_y, p_u, p_v )      \
181             *p_y++ = *p_line++; *p_v++ = *p_line++; \
182             *p_y++ = *p_line++; *p_u++ = *p_line++
183             C_YVYU_YUV422( p_line, p_y, p_u, p_v );
184             C_YVYU_YUV422( p_line, p_y, p_u, p_v );
185             C_YVYU_YUV422( p_line, p_y, p_u, p_v );
186             C_YVYU_YUV422( p_line, p_y, p_u, p_v );
187         }
188         for( i_x = ( p_filter->fmt_out.video.i_width % 8 ) / 2; i_x-- ; )
189         {
190             C_YVYU_YUV422( p_line, p_y, p_u, p_v );
191         }
192         p_line += i_source_margin;
193         p_y += i_dest_margin;
194         p_u += i_dest_margin_c;
195         p_v += i_dest_margin_c;
196     }
197 }
198
199 /*****************************************************************************
200  * UYVY_I422: packed UYVY 4:2:2 to planar YUV 4:2:2
201  *****************************************************************************/
202 static void UYVY_I422( filter_t *p_filter, picture_t *p_source,
203                                            picture_t *p_dest )
204 {
205     uint8_t *p_line = p_source->p->p_pixels;
206
207     uint8_t *p_y = p_dest->Y_PIXELS;
208     uint8_t *p_u = p_dest->U_PIXELS;
209     uint8_t *p_v = p_dest->V_PIXELS;
210
211     int i_x, i_y;
212
213     const int i_dest_margin = p_dest->p[0].i_pitch
214                                  - p_dest->p[0].i_visible_pitch;
215     const int i_dest_margin_c = p_dest->p[1].i_pitch
216                                  - p_dest->p[1].i_visible_pitch;
217     const int i_source_margin = p_source->p->i_pitch
218                                - p_source->p->i_visible_pitch;
219
220     for( i_y = p_filter->fmt_out.video.i_height ; i_y-- ; )
221     {
222         for( i_x = p_filter->fmt_out.video.i_width / 8 ; i_x-- ; )
223         {
224 #define C_UYVY_YUV422( p_line, p_y, p_u, p_v )      \
225             *p_u++ = *p_line++; *p_y++ = *p_line++; \
226             *p_v++ = *p_line++; *p_y++ = *p_line++
227             C_UYVY_YUV422( p_line, p_y, p_u, p_v );
228             C_UYVY_YUV422( p_line, p_y, p_u, p_v );
229             C_UYVY_YUV422( p_line, p_y, p_u, p_v );
230             C_UYVY_YUV422( p_line, p_y, p_u, p_v );
231         }
232         for( i_x = ( p_filter->fmt_out.video.i_width % 8 ) / 2; i_x-- ; )
233         {
234             C_UYVY_YUV422( p_line, p_y, p_u, p_v );
235         }
236         p_line += i_source_margin;
237         p_y += i_dest_margin;
238         p_u += i_dest_margin_c;
239         p_v += i_dest_margin_c;
240     }
241 }
242
243 /*****************************************************************************
244  * cyuv_I422: upside-down packed UYVY 4:2:2 to planar YUV 4:2:2
245  * FIXME
246  *****************************************************************************/
247 static void cyuv_I422( filter_t *p_filter, picture_t *p_source,
248                                            picture_t *p_dest )
249 {
250     uint8_t *p_line = p_source->p->p_pixels;
251
252     uint8_t *p_y = p_dest->Y_PIXELS;
253     uint8_t *p_u = p_dest->U_PIXELS;
254     uint8_t *p_v = p_dest->V_PIXELS;
255
256     int i_x, i_y;
257
258     const int i_dest_margin = p_dest->p[0].i_pitch
259                                  - p_dest->p[0].i_visible_pitch;
260     const int i_dest_margin_c = p_dest->p[1].i_pitch
261                                  - p_dest->p[1].i_visible_pitch;
262     const int i_source_margin = p_source->p->i_pitch
263                                - p_source->p->i_visible_pitch;
264
265     for( i_y = p_filter->fmt_out.video.i_height ; i_y-- ; )
266     {
267         for( i_x = p_filter->fmt_out.video.i_width / 8 ; i_x-- ; )
268         {
269 #define C_cyuv_YUV422( p_line, p_y, p_u, p_v )      \
270             *p_y++ = *p_line++; *p_v++ = *p_line++; \
271             *p_y++ = *p_line++; *p_u++ = *p_line++
272             C_cyuv_YUV422( p_line, p_y, p_u, p_v );
273             C_cyuv_YUV422( p_line, p_y, p_u, p_v );
274             C_cyuv_YUV422( p_line, p_y, p_u, p_v );
275             C_cyuv_YUV422( p_line, p_y, p_u, p_v );
276         }
277         for( i_x = ( p_filter->fmt_out.video.i_width % 8 ) / 2; i_x-- ; )
278         {
279             C_cyuv_YUV422( p_line, p_y, p_u, p_v );
280         }
281         p_line += i_source_margin;
282         p_y += i_dest_margin;
283         p_u += i_dest_margin_c;
284         p_v += i_dest_margin_c;
285     }
286 }