demux:mkv: do not try to use a seekpoint for a track that doesn't exist
[vlc.git] / modules / video_filter / anaglyph.c
blob4d05ab166247928f1e88099b477379aa348be730
1 /*****************************************************************************
2 * anaglyph.c : Create an image compatible with anaglyph glasses from a 3D video
3 *****************************************************************************
4 * Copyright (C) 2000-2012 VLC authors and VideoLAN
5 * $Id$
7 * Authors: Antoine Cellerier <dionoea .t videolan d@t org>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
28 #include <vlc_common.h>
29 #include <vlc_plugin.h>
30 #include <vlc_filter.h>
31 #include <vlc_picture.h>
32 #include "filter_picture.h"
34 static int Create(vlc_object_t *);
35 static void Destroy(vlc_object_t *);
36 static picture_t *Filter(filter_t *, picture_t *);
37 static void combine_side_by_side_yuv420(picture_t *, picture_t *, int, int);
39 #define SCHEME_TEXT N_("Color scheme")
40 #define SCHEME_LONGTEXT N_("Define the glasses' color scheme")
42 #define FILTER_PREFIX "anaglyph-"
44 /* See http://en.wikipedia.org/wiki/Anaglyph_image for a list of known
45 * color schemes */
46 enum scheme_e
48 red_green = 1,
49 red_blue,
50 red_cyan,
51 trioscopic,
52 magenta_cyan,
55 static const char *const ppsz_scheme_values[] = {
56 "red-green",
57 "red-blue",
58 "red-cyan",
59 "trioscopic",
60 "magenta-cyan",
62 static const char *const ppsz_scheme_descriptions[] = {
63 "pure red (left) pure green (right)",
64 "pure red (left) pure blue (right)",
65 "pure red (left) pure cyan (right)",
66 "pure green (left) pure magenta (right)",
67 "magenta (left) cyan (right)",
70 vlc_module_begin()
71 set_description(N_("Convert 3D picture to anaglyph image video filter"));
72 set_shortname(N_("Anaglyph"))
73 set_category(CAT_VIDEO)
74 set_subcategory(SUBCAT_VIDEO_VFILTER)
75 set_capability("video filter", 0)
76 add_string(FILTER_PREFIX "scheme", "red-cyan", SCHEME_TEXT, SCHEME_LONGTEXT, false)
77 change_string_list(ppsz_scheme_values, ppsz_scheme_descriptions)
78 set_callbacks(Create, Destroy)
79 vlc_module_end()
81 static const char *const ppsz_filter_options[] = {
82 "scheme", NULL
85 struct filter_sys_t
87 int left, right;
91 static int Create(vlc_object_t *p_this)
93 filter_t *p_filter = (filter_t *)p_this;
95 switch (p_filter->fmt_in.video.i_chroma)
97 case VLC_CODEC_I420:
98 case VLC_CODEC_J420:
99 case VLC_CODEC_YV12:
100 break;
102 default:
103 msg_Err(p_filter, "Unsupported input chroma (%4.4s)",
104 (char*)&(p_filter->fmt_in.video.i_chroma));
105 return VLC_EGENERIC;
108 p_filter->p_sys = malloc(sizeof(filter_sys_t));
109 if (!p_filter->p_sys)
110 return VLC_ENOMEM;
111 filter_sys_t *p_sys = p_filter->p_sys;
113 config_ChainParse(p_filter, FILTER_PREFIX, ppsz_filter_options,
114 p_filter->p_cfg);
116 char *psz_scheme = var_CreateGetStringCommand(p_filter,
117 FILTER_PREFIX "scheme");
118 enum scheme_e scheme = red_cyan;
119 if (psz_scheme)
121 if (!strcmp(psz_scheme, "red-green"))
122 scheme = red_green;
123 else if (!strcmp(psz_scheme, "red-blue"))
124 scheme = red_blue;
125 else if (!strcmp(psz_scheme, "red-cyan"))
126 scheme = red_cyan;
127 else if (!strcmp(psz_scheme, "trioscopic"))
128 scheme = trioscopic;
129 else if (!strcmp(psz_scheme, "magenta-cyan"))
130 scheme = magenta_cyan;
131 else
132 msg_Err(p_filter, "Unknown anaglyph color scheme '%s'", psz_scheme);
134 free(psz_scheme);
136 switch (scheme)
138 case red_green:
139 p_sys->left = 0xff0000;
140 p_sys->right = 0x00ff00;
141 break;
142 case red_blue:
143 p_sys->left = 0xff0000;
144 p_sys->right = 0x0000ff;
145 break;
146 case red_cyan:
147 p_sys->left = 0xff0000;
148 p_sys->right = 0x00ffff;
149 break;
150 case trioscopic:
151 p_sys->left = 0x00ff00;
152 p_sys->right = 0xff00ff;
153 break;
154 case magenta_cyan:
155 p_sys->left = 0xff00ff;
156 p_sys->right = 0x00ffff;
157 break;
160 p_filter->pf_video_filter = Filter;
161 return VLC_SUCCESS;
164 static void Destroy(vlc_object_t *p_this)
166 filter_t *p_filter = (filter_t *)p_this;
167 filter_sys_t *p_sys = p_filter->p_sys;
168 free(p_sys);
171 static picture_t *Filter(filter_t *p_filter, picture_t *p_pic)
173 filter_sys_t *p_sys = p_filter->p_sys;
175 if (!p_pic)
176 return NULL;
178 picture_t *p_outpic = filter_NewPicture(p_filter);
179 if (!p_outpic)
181 picture_Release(p_pic);
182 return NULL;
185 switch (p_pic->format.i_chroma)
187 case VLC_CODEC_I420:
188 case VLC_CODEC_J420:
189 case VLC_CODEC_YV12:
190 combine_side_by_side_yuv420(p_pic, p_outpic,
191 p_sys->left, p_sys->right);
192 break;
194 default:
195 msg_Warn(p_filter, "Unsupported input chroma (%4.4s)",
196 (char*)&(p_pic->format.i_chroma));
197 picture_Release(p_pic);
198 return NULL;
201 return CopyInfoAndRelease(p_outpic, p_pic);
205 static void combine_side_by_side_yuv420(picture_t *p_inpic, picture_t *p_outpic,
206 int left, int right)
208 uint8_t *y1inl = p_inpic->p[Y_PLANE].p_pixels;
209 uint8_t *y2inl;
210 uint8_t *uinl = p_inpic->p[U_PLANE].p_pixels;
211 uint8_t *vinl = p_inpic->p[V_PLANE].p_pixels;
213 uint8_t *y1out = p_outpic->p[Y_PLANE].p_pixels;
214 uint8_t *y2out;
215 uint8_t *uout = p_outpic->p[U_PLANE].p_pixels;
216 uint8_t *vout = p_outpic->p[V_PLANE].p_pixels;
218 const int in_pitch = p_inpic->p[Y_PLANE].i_pitch;
219 const int out_pitch = p_outpic->p[Y_PLANE].i_pitch;
221 const int visible_pitch = p_inpic->p[Y_PLANE].i_visible_pitch;
222 const int visible_lines = p_inpic->p[Y_PLANE].i_visible_lines;
223 const int uv_visible_pitch = p_inpic->p[U_PLANE].i_visible_pitch;
225 const uint8_t *yend = y1inl + visible_lines * in_pitch;
227 while (y1inl < yend)
229 uint8_t *y1inr = y1inl + visible_pitch/2;
230 uint8_t *y2inr;
231 uint8_t *uinr = uinl + uv_visible_pitch/2;
232 uint8_t *vinr = vinl + uv_visible_pitch/2;
234 const uint8_t *y1end = y1inr;
235 y2inl = y1inl + in_pitch;
236 y2inr = y1inr + in_pitch;
237 y2out = y1out + out_pitch;
239 while (y1inl < y1end)
241 int rl, gl, bl, rr, gr, br, r, g, b;
243 int rshift = !!((0xff0000&left) && (0xff0000&right));
244 int gshift = !!((0x00ff00&left) && (0x00ff00&right));
245 int bshift = !!((0x0000ff&left) && (0x0000ff&right));
247 yuv_to_rgb(&rl, &gl, &bl, *y1inl, *uinl, *vinl);
248 yuv_to_rgb(&rr, &gr, &br, *y1inr, *uinr, *vinr);
249 r = ((!!(0xff0000&left))*rl + (!!(0xff0000&right))*rr)>>rshift;
250 g = ((!!(0x00ff00&left))*gl + (!!(0x00ff00&right))*gr)>>gshift;
251 b = ((!!(0x0000ff&left))*bl + (!!(0x0000ff&right))*br)>>bshift;
252 rgb_to_yuv(y1out, uout++, vout++, r, g, b);
253 y1out[1] = *y1out;
254 y1out+=2;
255 y1inl++;
256 y1inr++;
258 yuv_to_rgb(&rl, &gl, &bl, *y1inl, *uinl, *vinl);
259 yuv_to_rgb(&rr, &gr, &br, *y1inr, *uinr, *vinr);
260 r = ((!!(0xff0000&left))*rl + (!!(0xff0000&right))*rr)>>rshift;
261 g = ((!!(0x00ff00&left))*gl + (!!(0x00ff00&right))*gr)>>gshift;
262 b = ((!!(0x0000ff&left))*bl + (!!(0x0000ff&right))*br)>>bshift;
263 rgb_to_yuv(y1out, uout++, vout++, r, g, b);
264 y1out[1] = *y1out;
265 y1out+=2;
266 y1inl++;
267 y1inr++;
269 yuv_to_rgb(&rl, &gl, &bl, *y2inl, *uinl, *vinl);
270 yuv_to_rgb(&rr, &gr, &br, *y2inr, *uinr, *vinr);
271 r = ((!!(0xff0000&left))*rl + (!!(0xff0000&right))*rr)>>rshift;
272 g = ((!!(0x00ff00&left))*gl + (!!(0x00ff00&right))*gr)>>gshift;
273 b = ((!!(0x0000ff&left))*bl + (!!(0x0000ff&right))*br)>>bshift;
274 rgb_to_yuv(y2out, uout/*will be overwritten later, as will vout*/, vout, r, g, b);
275 y2out[1] = *y2out;
276 y2out+=2;
277 y2inl++;
278 y2inr++;
280 yuv_to_rgb(&rl, &gl, &bl, *y2inl, *uinl, *vinl);
281 yuv_to_rgb(&rr, &gr, &br, *y2inr, *uinr, *vinr);
282 r = ((!!(0xff0000&left))*rl + (!!(0xff0000&right))*rr)>>rshift;
283 g = ((!!(0x00ff00&left))*gl + (!!(0x00ff00&right))*gr)>>gshift;
284 b = ((!!(0x0000ff&left))*bl + (!!(0x0000ff&right))*br)>>bshift;
285 rgb_to_yuv(y2out, uout/*will be overwritten later, as will vout*/, vout, r, g, b);
286 y2out[1] = *y2out;
287 y2out+=2;
288 y2inl++;
289 y2inr++;
291 uinl++;
292 vinl++;
293 uinr++;
294 vinr++;
297 y1inl = y1inr + 2*in_pitch - visible_pitch;
298 y1out += 2*out_pitch - visible_pitch;
299 uinl = uinr + p_inpic->p[U_PLANE].i_pitch - uv_visible_pitch;
300 vinl = vinr + p_inpic->p[V_PLANE].i_pitch - uv_visible_pitch;
301 uout += p_outpic->p[U_PLANE].i_pitch - uv_visible_pitch;
302 vout += p_outpic->p[V_PLANE].i_pitch - uv_visible_pitch;