Mercurial > mplayer.hg
annotate libmpcodecs/vf_stereo3d.c @ 33298:f0733d37f56b
Fix bug with gfree() definition in Win32 GUI.
gfree (taking pointer of pointer) was erroneously defined
free (taking pointer). Get rid of gfree() by using suitable
free() statements.
Patch by Stephen Sheldon, sfsheldo gmail com.
author | ib |
---|---|
date | Fri, 06 May 2011 09:35:46 +0000 |
parents | 45b3a91e8fb7 |
children | 16cf555989a9 |
rev | line source |
---|---|
32441 | 1 /* |
2 * Copyright (C) 2010 Gordon Schmidt <gordon.schmidt <at> s2000.tu-chemnitz.de> | |
3 * | |
4 * This file is part of MPlayer. | |
5 * | |
6 * MPlayer is free software; you can redistribute it and/or modify | |
7 * it under the terms of the GNU General Public License as published by | |
8 * the Free Software Foundation; either version 2 of the License, or | |
9 * (at your option) any later version. | |
10 * | |
11 * MPlayer is distributed in the hope that it will be useful, | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 * GNU General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License along | |
17 * with MPlayer; if not, write to the Free Software Foundation, Inc., | |
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
19 */ | |
20 | |
21 //==includes==// | |
22 #include <stdio.h> | |
23 #include <stdlib.h> | |
24 #include <string.h> | |
25 | |
26 #include "config.h" | |
27 #include "mp_msg.h" | |
28 #include "help_mp.h" | |
29 | |
30 #include "img_format.h" | |
31 #include "mp_image.h" | |
32445
7ec524214684
Use proper include instead of extern declarations in the .c file.
reimar
parents:
32441
diff
changeset
|
32 #include "vd.h" |
32441 | 33 #include "vf.h" |
34 #include "m_struct.h" | |
35 | |
36 #include "libavutil/common.h" | |
37 #include "libvo/fastmemcpy.h" | |
38 | |
39 //==types==// | |
40 typedef enum stereo_code { | |
41 ANAGLYPH_RC_GRAY, //anaglyph red/cyan gray | |
42 ANAGLYPH_RC_HALF, //anaglyph red/cyan half colored | |
43 ANAGLYPH_RC_COLOR, //anaglyph red/cyan colored | |
44 ANAGLYPH_RC_DUBOIS, //anaglyph red/cyan dubois | |
45 ANAGLYPH_GM_GRAY, //anaglyph green/magenta gray | |
46 ANAGLYPH_GM_HALF, //anaglyph green/magenta half colored | |
47 ANAGLYPH_GM_COLOR, //anaglyph green/magenta colored | |
48 ANAGLYPH_YB_GRAY, //anaglyph yellow/blue gray | |
49 ANAGLYPH_YB_HALF, //anaglyph yellow/blue half colored | |
50 ANAGLYPH_YB_COLOR, //anaglyph yellow/blue colored | |
51 MONO_L, //mono output for debugging (left eye only) | |
52 MONO_R, //mono output for debugging (right eye only) | |
53 SIDE_BY_SIDE_LR, //side by side parallel (left eye left, right eye right) | |
54 SIDE_BY_SIDE_RL, //side by side crosseye (right eye left, left eye right) | |
55 ABOVE_BELOW_LR, //above-below (left eye above, right eye below) | |
56 ABOVE_BELOW_RL, //above-below (right eye above, left eye below) | |
57 ABOVE_BELOW_2_LR, //above-below with half height resolution | |
58 ABOVE_BELOW_2_RL, //above-below with half height resolution | |
59 STEREO_CODE_COUNT //no value set - TODO: needs autodetection | |
60 } stereo_code; | |
61 | |
62 typedef struct component { | |
63 stereo_code fmt; | |
64 unsigned int width; | |
65 unsigned int height; | |
66 unsigned int off_left; | |
67 unsigned int off_right; | |
32539 | 68 unsigned int row_left; |
69 unsigned int row_right; | |
32441 | 70 } component; |
71 | |
72 //==global variables==// | |
73 static const int ana_coeff[10][3][6] = { | |
74 {{19595, 38470, 7471, 0, 0, 0}, //ANAGLYPH_RC_GRAY | |
75 { 0, 0, 0, 19595, 38470, 7471}, | |
76 { 0, 0, 0, 19595, 38470, 7471}}, | |
77 {{19595, 38470, 7471, 0, 0, 0}, //ANAGLYPH_RC_HALF | |
78 { 0, 0, 0, 0, 65536, 0}, | |
79 { 0, 0, 0, 0, 0, 65536}}, | |
80 {{65536, 0, 0, 0, 0, 0}, //ANAGLYPH_RC_COLOR | |
81 { 0, 0, 0, 0, 65536, 0}, | |
82 { 0, 0, 0, 0, 0, 65536}}, | |
83 {{29891, 32800, 11559, -2849, -5763, -102}, //ANAGLYPH_RC_DUBOIS | |
84 {-2627, -2479, -1033, 24804, 48080, -1209}, | |
85 { -997, -1350, -358, -4729, -7403, 80373}}, | |
86 {{ 0, 0, 0, 19595, 38470, 7471}, //ANAGLYPH_GM_GRAY | |
87 {19595, 38470, 7471, 0, 0, 0}, | |
88 { 0, 0, 0, 19595, 38470, 7471}}, | |
89 {{ 0, 0, 0, 65536, 0, 0}, //ANAGLYPH_GM_HALF | |
90 {19595, 38470, 7471, 0, 0, 0}, | |
91 { 0, 0, 0, 0, 0, 65536}}, | |
92 {{ 0, 0, 0, 65536, 0, 0}, //ANAGLYPH_GM_COLOR | |
93 { 0, 65536, 0, 0, 0, 0}, | |
94 { 0, 0, 0, 0, 0, 65536}}, | |
95 {{ 0, 0, 0, 19595, 38470, 7471}, //ANAGLYPH_YB_GRAY | |
96 { 0, 0, 0, 19595, 38470, 7471}, | |
97 {19595, 38470, 7471, 0, 0, 0}}, | |
98 {{ 0, 0, 0, 65536, 0, 0}, //ANAGLYPH_YB_HALF | |
99 { 0, 0, 0, 0, 65536, 0}, | |
100 {19595, 38470, 7471, 0, 0, 0}}, | |
101 {{ 0, 0, 0, 65536, 0, 0}, //ANAGLYPH_YB_COLOR | |
102 { 0, 0, 0, 0, 65536, 0}, | |
103 { 0, 0, 65536, 0, 0, 0}} | |
104 }; | |
105 | |
106 struct vf_priv_s { | |
107 component in; | |
108 component out; | |
109 int ana_matrix[3][6]; | |
110 unsigned int width; | |
111 unsigned int height; | |
112 } const vf_priv_default = { | |
113 {SIDE_BY_SIDE_LR}, | |
114 {ANAGLYPH_RC_DUBOIS} | |
115 }; | |
116 | |
117 //==functions==// | |
118 static inline uint8_t ana_convert(int coeff[6], uint8_t left[3], uint8_t right[3]) | |
119 { | |
120 int sum; | |
121 | |
122 sum = coeff[0] * left[0] + coeff[3] * right[0]; //red in | |
123 sum += coeff[1] * left[1] + coeff[4] * right[1]; //green in | |
124 sum += coeff[2] * left[2] + coeff[5] * right[2]; //blue in | |
125 return av_clip_uint8(sum >> 16); | |
126 } | |
127 | |
128 static int config(struct vf_instance *vf, int width, int height, int d_width, | |
129 int d_height, unsigned int flags, unsigned int outfmt) | |
130 { | |
131 if ((width & 1) || (height & 1)) { | |
132 mp_msg(MSGT_VFILTER, MSGL_WARN, "[stereo3d] invalid height or width\n"); | |
133 return 0; | |
134 } | |
135 //default input values | |
136 vf->priv->width = width; | |
137 vf->priv->height = height; | |
138 vf->priv->in.width = width; | |
139 vf->priv->in.height = height; | |
140 vf->priv->in.off_left = 0; | |
141 vf->priv->in.off_right = 0; | |
32539 | 142 vf->priv->in.row_left = 0; |
143 vf->priv->in.row_right = 0; | |
32441 | 144 |
145 //check input format | |
146 switch (vf->priv->in.fmt) { | |
147 case SIDE_BY_SIDE_LR: | |
148 vf->priv->width = width / 2; | |
149 vf->priv->in.off_right = vf->priv->width * 3; | |
150 break; | |
151 case SIDE_BY_SIDE_RL: | |
152 vf->priv->width = width / 2; | |
153 vf->priv->in.off_left = vf->priv->width * 3; | |
154 break; | |
32538 | 155 case ABOVE_BELOW_2_LR: |
156 d_height *= 2; | |
32441 | 157 case ABOVE_BELOW_LR: |
158 vf->priv->height = height / 2; | |
32539 | 159 vf->priv->in.row_right = vf->priv->height; |
32441 | 160 break; |
32538 | 161 case ABOVE_BELOW_2_RL: |
162 d_height *= 2; | |
32441 | 163 case ABOVE_BELOW_RL: |
164 vf->priv->height = height / 2; | |
32539 | 165 vf->priv->in.row_left = vf->priv->height; |
32441 | 166 break; |
167 default: | |
168 mp_msg(MSGT_VFILTER, MSGL_WARN, | |
169 "[stereo3d] stereo format of input is not supported\n"); | |
170 return 0; | |
171 break; | |
172 } | |
173 //default output values | |
174 vf->priv->out.width = vf->priv->width; | |
175 vf->priv->out.height = vf->priv->height; | |
176 vf->priv->out.off_left = 0; | |
177 vf->priv->out.off_right = 0; | |
32539 | 178 vf->priv->out.row_left = 0; |
179 vf->priv->out.row_right = 0; | |
32441 | 180 |
181 //check output format | |
182 switch (vf->priv->out.fmt) { | |
183 case ANAGLYPH_RC_GRAY: | |
184 case ANAGLYPH_RC_HALF: | |
185 case ANAGLYPH_RC_COLOR: | |
186 case ANAGLYPH_RC_DUBOIS: | |
187 case ANAGLYPH_GM_GRAY: | |
188 case ANAGLYPH_GM_HALF: | |
189 case ANAGLYPH_GM_COLOR: | |
190 case ANAGLYPH_YB_GRAY: | |
191 case ANAGLYPH_YB_HALF: | |
192 case ANAGLYPH_YB_COLOR: | |
193 memcpy(vf->priv->ana_matrix, ana_coeff[vf->priv->out.fmt], | |
194 sizeof(vf->priv->ana_matrix)); | |
195 break; | |
196 case SIDE_BY_SIDE_LR: | |
197 vf->priv->out.width = vf->priv->width * 2; | |
198 vf->priv->out.off_right = vf->priv->width * 3; | |
199 break; | |
200 case SIDE_BY_SIDE_RL: | |
201 vf->priv->out.width = vf->priv->width * 2; | |
202 vf->priv->out.off_left = vf->priv->width * 3; | |
203 break; | |
32538 | 204 case ABOVE_BELOW_2_LR: |
205 d_height /= 2; | |
32441 | 206 case ABOVE_BELOW_LR: |
207 vf->priv->out.height = vf->priv->height * 2; | |
32539 | 208 vf->priv->out.row_right = vf->priv->height; |
32441 | 209 break; |
32538 | 210 case ABOVE_BELOW_2_RL: |
211 d_height /= 2; | |
32441 | 212 case ABOVE_BELOW_RL: |
213 vf->priv->out.height = vf->priv->height * 2; | |
32539 | 214 vf->priv->out.row_left = vf->priv->height; |
32441 | 215 break; |
216 case MONO_R: | |
217 //same as MONO_L only needs switching of input offsets | |
218 vf->priv->in.off_left = vf->priv->in.off_right; | |
32539 | 219 vf->priv->in.row_left = vf->priv->in.row_right; |
32441 | 220 //nobreak; |
221 case MONO_L: | |
222 //use default settings | |
223 break; | |
224 default: | |
225 mp_msg(MSGT_VFILTER, MSGL_WARN, | |
226 "[stereo3d] stereo format of output is not supported\n"); | |
227 return 0; | |
228 break; | |
229 } | |
230 if (!opt_screen_size_x && !opt_screen_size_y) { | |
231 d_width = d_width * vf->priv->out.width / width; | |
232 d_height = d_height * vf->priv->out.height / height; | |
233 } | |
234 return vf_next_config(vf, vf->priv->out.width, vf->priv->out.height, | |
235 d_width, d_height, flags, outfmt); | |
236 } | |
237 | |
238 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) | |
239 { | |
240 mp_image_t *dmpi; | |
241 if (vf->priv->in.fmt == vf->priv->out.fmt) { //nothing to do | |
242 dmpi = mpi; | |
243 } else { | |
32539 | 244 int out_off_left, out_off_right; |
245 int in_off_left = vf->priv->in.row_left * mpi->stride[0] + | |
246 vf->priv->in.off_left; | |
247 int in_off_right = vf->priv->in.row_right * mpi->stride[0] + | |
248 vf->priv->in.off_right; | |
249 | |
32541
45b3a91e8fb7
Indicate that stereo3d can now handle strides properly.
reimar
parents:
32540
diff
changeset
|
250 dmpi = vf_get_image(vf->next, IMGFMT_RGB24, MP_IMGTYPE_TEMP, |
45b3a91e8fb7
Indicate that stereo3d can now handle strides properly.
reimar
parents:
32540
diff
changeset
|
251 MP_IMGFLAG_ACCEPT_STRIDE, |
32441 | 252 vf->priv->out.width, vf->priv->out.height); |
32539 | 253 out_off_left = vf->priv->out.row_left * dmpi->stride[0] + |
254 vf->priv->out.off_left; | |
255 out_off_right = vf->priv->out.row_right * dmpi->stride[0] + | |
256 vf->priv->out.off_right; | |
257 | |
32441 | 258 switch (vf->priv->out.fmt) { |
259 case SIDE_BY_SIDE_LR: | |
260 case SIDE_BY_SIDE_RL: | |
261 case ABOVE_BELOW_LR: | |
262 case ABOVE_BELOW_RL: | |
263 case ABOVE_BELOW_2_LR: | |
264 case ABOVE_BELOW_2_RL: | |
32539 | 265 memcpy_pic(dmpi->planes[0] + out_off_left, |
266 mpi->planes[0] + in_off_left, | |
32538 | 267 3 * vf->priv->width, |
268 vf->priv->height, | |
32539 | 269 dmpi->stride[0], |
270 mpi->stride[0]); | |
271 memcpy_pic(dmpi->planes[0] + out_off_right, | |
272 mpi->planes[0] + in_off_right, | |
32538 | 273 3 * vf->priv->width, |
274 vf->priv->height, | |
32539 | 275 dmpi->stride[0], |
276 mpi->stride[0]); | |
32441 | 277 break; |
278 case MONO_L: | |
279 case MONO_R: | |
32538 | 280 memcpy_pic(dmpi->planes[0], |
32539 | 281 mpi->planes[0] + in_off_left, |
32538 | 282 3 * vf->priv->width, |
283 vf->priv->height, | |
32539 | 284 dmpi->stride[0], |
285 mpi->stride[0]); | |
32441 | 286 break; |
287 case ANAGLYPH_RC_GRAY: | |
288 case ANAGLYPH_RC_HALF: | |
289 case ANAGLYPH_RC_COLOR: | |
290 case ANAGLYPH_RC_DUBOIS: | |
291 case ANAGLYPH_GM_GRAY: | |
292 case ANAGLYPH_GM_HALF: | |
293 case ANAGLYPH_GM_COLOR: | |
294 case ANAGLYPH_YB_GRAY: | |
295 case ANAGLYPH_YB_HALF: | |
296 case ANAGLYPH_YB_COLOR: { | |
297 int x,y,il,ir,o; | |
298 unsigned char *source = mpi->planes[0]; | |
299 unsigned char *dest = dmpi->planes[0]; | |
300 unsigned int out_width = vf->priv->out.width; | |
301 int *ana_matrix[3]; | |
302 | |
303 for(int i = 0; i < 3; i++) | |
304 ana_matrix[i] = vf->priv->ana_matrix[i]; | |
305 | |
306 for (y = 0; y < vf->priv->out.height; y++) { | |
32539 | 307 o = dmpi->stride[0] * y; |
308 il = in_off_left + y * mpi->stride[0]; | |
309 ir = in_off_right + y * mpi->stride[0]; | |
32441 | 310 for (x = 0; x < out_width; x++) { |
311 dest[o ] = ana_convert( | |
312 ana_matrix[0], source + il, source + ir); //red out | |
313 dest[o + 1] = ana_convert( | |
314 ana_matrix[1], source + il, source + ir); //green out | |
315 dest[o + 2] = ana_convert( | |
316 ana_matrix[2], source + il, source + ir); //blue out | |
317 il += 3; | |
318 ir += 3; | |
319 o += 3; | |
320 } | |
321 } | |
322 break; | |
323 } | |
324 default: | |
325 mp_msg(MSGT_VFILTER, MSGL_WARN, | |
326 "[stereo3d] stereo format of output is not supported\n"); | |
327 return 0; | |
328 break; | |
329 } | |
330 } | |
331 return vf_next_put_image(vf, dmpi, pts); | |
332 } | |
333 | |
334 static int query_format(struct vf_instance *vf, unsigned int fmt) | |
335 { | |
336 switch (fmt) | |
337 case IMGFMT_RGB24: | |
338 return vf_next_query_format(vf, fmt); | |
339 return 0; | |
340 } | |
341 | |
342 static void uninit(vf_instance_t *vf) | |
343 { | |
344 free(vf->priv); | |
345 } | |
346 | |
347 static int vf_open(vf_instance_t *vf, char *args) | |
348 { | |
349 vf->config = config; | |
350 vf->uninit = uninit; | |
351 vf->put_image = put_image; | |
352 vf->query_format = query_format; | |
353 | |
354 return 1; | |
355 } | |
356 | |
357 ///Presets usage | |
358 static const struct format_preset { | |
359 char* name; | |
360 stereo_code scode; | |
361 } vf_format_presets_defs[] = { | |
362 {"arcg", ANAGLYPH_RC_GRAY}, | |
363 {"anaglyph_red_cyan_gray", ANAGLYPH_RC_GRAY}, | |
364 {"arch", ANAGLYPH_RC_HALF}, | |
365 {"anaglyph_red_cyan_half_color", ANAGLYPH_RC_HALF}, | |
366 {"arcc", ANAGLYPH_RC_COLOR}, | |
367 {"anaglyph_red_cyan_color", ANAGLYPH_RC_COLOR}, | |
368 {"arcd", ANAGLYPH_RC_DUBOIS}, | |
369 {"anaglyph_red_cyan_dubios", ANAGLYPH_RC_DUBOIS}, | |
370 {"agmg", ANAGLYPH_GM_GRAY}, | |
371 {"anaglyph_green_magenta_gray", ANAGLYPH_GM_GRAY}, | |
372 {"agmh", ANAGLYPH_GM_HALF}, | |
373 {"anaglyph_green_magenta_half_color",ANAGLYPH_GM_HALF}, | |
374 {"agmc", ANAGLYPH_GM_COLOR}, | |
375 {"anaglyph_green_magenta_color", ANAGLYPH_GM_COLOR}, | |
376 {"aybg", ANAGLYPH_YB_GRAY}, | |
377 {"anaglyph_yellow_blue_gray", ANAGLYPH_YB_GRAY}, | |
378 {"aybh", ANAGLYPH_YB_HALF}, | |
379 {"anaglyph_yellow_blue_half_color", ANAGLYPH_YB_HALF}, | |
380 {"aybc", ANAGLYPH_YB_COLOR}, | |
381 {"anaglyph_yellow_blue_color", ANAGLYPH_YB_COLOR}, | |
382 {"ml", MONO_L}, | |
383 {"mono_left", MONO_L}, | |
384 {"mr", MONO_R}, | |
385 {"mono_right", MONO_R}, | |
386 {"sbsl", SIDE_BY_SIDE_LR}, | |
387 {"side_by_side_left_first", SIDE_BY_SIDE_LR}, | |
388 {"sbsr", SIDE_BY_SIDE_RL}, | |
389 {"side_by_side_right_first", SIDE_BY_SIDE_RL}, | |
390 {"abl", ABOVE_BELOW_LR}, | |
391 {"above_below_left_first", ABOVE_BELOW_LR}, | |
392 {"abr", ABOVE_BELOW_RL}, | |
393 {"above_below_right_first", ABOVE_BELOW_RL}, | |
394 {"ab2l", ABOVE_BELOW_2_LR}, | |
395 {"above_below_half_height_left_first", ABOVE_BELOW_2_LR}, | |
396 {"ab2r", ABOVE_BELOW_2_RL}, | |
397 {"above_below_half_height_right_first",ABOVE_BELOW_2_RL}, | |
398 { NULL, 0} | |
399 }; | |
400 | |
401 #define ST_OFF(f) M_ST_OFF(struct format_preset,f) | |
402 static const m_option_t vf_format_preset_fields_in[] = { | |
403 {"in", ST_OFF(scode), CONF_TYPE_INT, 0,0,0, NULL}, | |
404 { NULL, NULL, 0, 0, 0, 0, NULL } | |
405 }; | |
406 static const m_option_t vf_format_preset_fields_out[] = { | |
407 {"out", ST_OFF(scode), CONF_TYPE_INT, 0,0,0, NULL}, | |
408 { NULL, NULL, 0, 0, 0, 0, NULL } | |
409 }; | |
410 | |
411 static const m_struct_t vf_format_preset_in = { | |
412 "stereo_format_preset_in", | |
413 sizeof(struct format_preset), | |
414 NULL, | |
415 vf_format_preset_fields_in | |
416 }; | |
417 static const m_struct_t vf_format_preset_out = { | |
418 "stereo_format_preset_out", | |
419 sizeof(struct format_preset), | |
420 NULL, | |
421 vf_format_preset_fields_out | |
422 }; | |
423 | |
424 static const m_struct_t vf_opts; | |
425 static const m_obj_presets_t format_preset_in = { | |
426 (struct m_struct_st*)&vf_format_preset_in, | |
427 (struct m_struct_st*)&vf_opts, | |
428 (struct format_preset*)vf_format_presets_defs, | |
429 ST_OFF(name) | |
430 }; | |
431 static const m_obj_presets_t format_preset_out = { | |
432 (struct m_struct_st*)&vf_format_preset_out, | |
433 (struct m_struct_st*)&vf_opts, | |
434 (struct format_preset*)vf_format_presets_defs, | |
435 ST_OFF(name) | |
436 }; | |
437 | |
438 /// Now the options | |
439 #undef ST_OFF | |
440 #define ST_OFF(f) M_ST_OFF(struct vf_priv_s,f) | |
441 static const m_option_t vf_opts_fields[] = { | |
442 {"stereo_in", 0, CONF_TYPE_OBJ_PRESETS, 0, 0, 0, | |
443 (m_obj_presets_t*)&format_preset_in}, | |
444 {"stereo_out", 0, CONF_TYPE_OBJ_PRESETS, 0, 0, 0, | |
445 (m_obj_presets_t*)&format_preset_out}, | |
446 {"in", ST_OFF(in.fmt), CONF_TYPE_INT, 0,0,0, NULL}, | |
447 {"out", ST_OFF(out.fmt), CONF_TYPE_INT, 0,0,0, NULL}, | |
448 { NULL, NULL, 0, 0, 0, 0, NULL } | |
449 }; | |
450 | |
451 static const m_struct_t vf_opts = { | |
452 "stereo3d", | |
453 sizeof(struct vf_priv_s), | |
454 &vf_priv_default, | |
455 vf_opts_fields | |
456 }; | |
457 | |
458 | |
459 //==info struct==// | |
460 const vf_info_t vf_info_stereo3d = { | |
461 "stereoscopic 3d view", | |
462 "stereo3d", | |
463 "Gordon Schmidt", | |
464 "view stereoscopic videos", | |
465 vf_open, | |
466 &vf_opts | |
467 }; |