Merge svn changes up to r28641
[mplayer.git] / libmpcodecs / vd.c
blob22bdddc909dbc382f5e69e099ea76957f7e3220a
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
5 #include "config.h"
6 #include "mp_msg.h"
7 #include "help_mp.h"
8 #include "options.h"
10 #include "codec-cfg.h"
12 #include "img_format.h"
14 #include "stream/stream.h"
15 #include "libmpdemux/demuxer.h"
16 #include "libmpdemux/stheader.h"
17 #include "dec_video.h"
19 #include "vd.h"
20 #include "vf.h"
22 extern const vd_functions_t mpcodecs_vd_null;
23 extern const vd_functions_t mpcodecs_vd_ffmpeg;
24 extern const vd_functions_t mpcodecs_vd_theora;
25 extern const vd_functions_t mpcodecs_vd_dshow;
26 extern const vd_functions_t mpcodecs_vd_dmo;
27 extern const vd_functions_t mpcodecs_vd_vfw;
28 extern const vd_functions_t mpcodecs_vd_vfwex;
29 extern const vd_functions_t mpcodecs_vd_raw;
30 extern const vd_functions_t mpcodecs_vd_hmblck;
31 extern const vd_functions_t mpcodecs_vd_xanim;
32 extern const vd_functions_t mpcodecs_vd_nuv;
33 extern const vd_functions_t mpcodecs_vd_mpng;
34 extern const vd_functions_t mpcodecs_vd_ijpg;
35 extern const vd_functions_t mpcodecs_vd_mtga;
36 extern const vd_functions_t mpcodecs_vd_sgi;
37 extern const vd_functions_t mpcodecs_vd_libmpeg2;
38 extern const vd_functions_t mpcodecs_vd_mpegpes;
39 extern const vd_functions_t mpcodecs_vd_zrmjpeg;
40 extern const vd_functions_t mpcodecs_vd_realvid;
41 extern const vd_functions_t mpcodecs_vd_xvid;
42 extern const vd_functions_t mpcodecs_vd_libdv;
43 extern const vd_functions_t mpcodecs_vd_lzo;
44 extern const vd_functions_t mpcodecs_vd_qtvideo;
46 /* Please do not add any new decoders here. If you want to implement a new
47 * decoder, add it to libavcodec, except for wrappers around external
48 * libraries and decoders requiring binary support. */
50 const vd_functions_t * const mpcodecs_vd_drivers[] = {
51 &mpcodecs_vd_null,
52 #ifdef CONFIG_LIBAVCODEC
53 &mpcodecs_vd_ffmpeg,
54 #endif
55 #ifdef CONFIG_OGGTHEORA
56 &mpcodecs_vd_theora,
57 #endif
58 #ifdef CONFIG_WIN32DLL
59 &mpcodecs_vd_dshow,
60 &mpcodecs_vd_dmo,
61 &mpcodecs_vd_vfw,
62 &mpcodecs_vd_vfwex,
63 #endif
64 &mpcodecs_vd_lzo,
65 &mpcodecs_vd_raw,
66 &mpcodecs_vd_hmblck,
67 &mpcodecs_vd_nuv,
68 #ifdef CONFIG_XANIM
69 &mpcodecs_vd_xanim,
70 #endif
71 #ifdef CONFIG_PNG
72 &mpcodecs_vd_mpng,
73 #endif
74 #ifdef CONFIG_JPEG
75 &mpcodecs_vd_ijpg,
76 #endif
77 &mpcodecs_vd_mtga,
78 &mpcodecs_vd_sgi,
79 #ifdef CONFIG_LIBMPEG2
80 &mpcodecs_vd_libmpeg2,
81 #endif
82 &mpcodecs_vd_mpegpes,
83 #ifdef CONFIG_ZR
84 &mpcodecs_vd_zrmjpeg,
85 #endif
86 #ifdef CONFIG_REALCODECS
87 &mpcodecs_vd_realvid,
88 #endif
89 #ifdef CONFIG_XVID4
90 &mpcodecs_vd_xvid,
91 #endif
92 #ifdef CONFIG_LIBDV095
93 &mpcodecs_vd_libdv,
94 #endif
95 #ifdef CONFIG_QTX_CODECS
96 &mpcodecs_vd_qtvideo,
97 #endif
98 /* Please do not add any new decoders here. If you want to implement a new
99 * decoder, add it to libavcodec, except for wrappers around external
100 * libraries and decoders requiring binary support. */
101 NULL
104 #include "libvo/video_out.h"
106 int mpcodecs_config_vo(sh_video_t *sh, int w, int h,
107 unsigned int preferred_outfmt)
109 struct MPOpts *opts = sh->opts;
110 int i, j;
111 unsigned int out_fmt = 0;
112 int screen_size_x = 0;
113 int screen_size_y = 0;
114 vf_instance_t *vf = sh->vfilter, *sc = NULL;
115 int palette = 0;
116 int vocfg_flags = 0;
118 if (w)
119 sh->disp_w = w;
120 if (h)
121 sh->disp_h = h;
123 if (!sh->disp_w || !sh->disp_h)
124 return 0;
126 mp_msg(MSGT_DECVIDEO, MSGL_INFO, MSGTR_VoConfigRequest, w, h,
127 vo_format_name(preferred_outfmt));
129 if (get_video_quality_max(sh) <= 0 && divx_quality) {
130 // user wants postprocess but no pp filter yet:
131 sh->vfilter = vf = vf_open_filter(opts, vf, "pp", NULL);
133 // check if libvo and codec has common outfmt (no conversion):
134 csp_again:
136 if (mp_msg_test(MSGT_DECVIDEO, MSGL_V)) {
137 vf_instance_t *f = vf;
138 mp_msg(MSGT_DECVIDEO, MSGL_V, "Trying filter chain:");
139 for (f = vf; f; f = f->next)
140 mp_msg(MSGT_DECVIDEO, MSGL_V, " %s", f->info->name);
141 mp_msg(MSGT_DECVIDEO, MSGL_V, "\n");
144 j = -1;
145 for (i = 0; i < CODECS_MAX_OUTFMT; i++) {
146 int flags;
147 out_fmt = sh->codec->outfmt[i];
148 if (out_fmt == (unsigned int) 0xFFFFFFFF)
149 continue;
150 flags = vf->query_format(vf, out_fmt);
151 mp_msg(MSGT_CPLAYER, MSGL_DBG2,
152 "vo_debug: query(%s) returned 0x%X (i=%d) \n",
153 vo_format_name(out_fmt), flags, i);
154 if ((flags & VFCAP_CSP_SUPPORTED_BY_HW)
155 || (flags & VFCAP_CSP_SUPPORTED && j < 0)) {
156 // check (query) if codec really support this outfmt...
157 sh->outfmtidx = j; // pass index to the control() function this way
158 if (sh->vd_driver->control(sh, VDCTRL_QUERY_FORMAT, &out_fmt) ==
159 CONTROL_FALSE) {
160 mp_msg(MSGT_CPLAYER, MSGL_DBG2,
161 "vo_debug: codec query_format(%s) returned FALSE\n",
162 vo_format_name(out_fmt));
163 continue;
165 j = i;
166 sh->output_flags = flags;
167 if (flags & VFCAP_CSP_SUPPORTED_BY_HW)
168 break;
169 } else if (!palette
170 && !(flags &
171 (VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_CSP_SUPPORTED))
172 && (out_fmt == IMGFMT_RGB8 || out_fmt == IMGFMT_BGR8)) {
173 sh->outfmtidx = j; // pass index to the control() function this way
174 if (sh->vd_driver->control(sh, VDCTRL_QUERY_FORMAT, &out_fmt) !=
175 CONTROL_FALSE)
176 palette = 1;
179 if (j < 0) {
180 // TODO: no match - we should use conversion...
181 if (strcmp(vf->info->name, "scale") && palette != -1) {
182 mp_msg(MSGT_DECVIDEO, MSGL_INFO, MSGTR_CouldNotFindColorspace);
183 sc = vf = vf_open_filter(opts, vf, "scale", NULL);
184 goto csp_again;
185 } else if (palette == 1) {
186 mp_msg(MSGT_DECVIDEO, MSGL_V, "vd: Trying -vf palette...\n");
187 palette = -1;
188 vf = vf_open_filter(opts, vf, "palette", NULL);
189 goto csp_again;
190 } else {
191 // sws failed, if the last filter (vf_vo) support MPEGPES try
192 // to append vf_lavc
193 vf_instance_t *vo, *vp = NULL, *ve;
194 // Remove the scale filter if we added it ourselves
195 if (vf == sc) {
196 ve = vf;
197 vf = vf->next;
198 vf_uninit_filter(ve);
200 // Find the last filter (vf_vo)
201 for (vo = vf; vo->next; vo = vo->next)
202 vp = vo;
203 if (vo->query_format(vo, IMGFMT_MPEGPES)
204 && (!vp || (vp && strcmp(vp->info->name, "lavc")))) {
205 ve = vf_open_filter(opts, vo, "lavc", NULL);
206 if (vp)
207 vp->next = ve;
208 else
209 vf = ve;
210 goto csp_again;
213 mp_msg(MSGT_CPLAYER, MSGL_WARN, MSGTR_VOincompCodec);
214 sh->vf_initialized = -1;
215 return 0; // failed
217 out_fmt = sh->codec->outfmt[j];
218 mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_UsingXAsOutputCspNoY,
219 vo_format_name(out_fmt), j);
220 sh->outfmtidx = j;
221 sh->vfilter = vf;
223 // autodetect flipping
224 if (opts->flip == -1) {
225 opts->flip = 0;
226 if (sh->codec->outflags[j] & CODECS_FLAG_FLIP)
227 if (!(sh->codec->outflags[j] & CODECS_FLAG_NOFLIP))
228 opts->flip = 1;
230 if (sh->output_flags & VFCAP_FLIPPED)
231 opts->flip ^= 1;
232 if (opts->flip && !(sh->output_flags & VFCAP_FLIP)) {
233 // we need to flip, but no flipping filter avail.
234 vf_add_before_vo(&vf, "flip", NULL);
235 sh->vfilter = vf;
237 // time to do aspect ratio corrections...
239 if (opts->movie_aspect > -1.0)
240 sh->aspect = opts->movie_aspect; // cmdline overrides autodetect
241 else if (sh->stream_aspect != 0.0)
242 sh->aspect = sh->stream_aspect;
244 if (opts->screen_size_x || opts->screen_size_y) {
245 screen_size_x = opts->screen_size_x;
246 screen_size_y = opts->screen_size_y;
247 if (!opts->vidmode) {
248 if (!screen_size_x)
249 screen_size_x = 1;
250 if (!screen_size_y)
251 screen_size_y = 1;
252 if (screen_size_x <= 8)
253 screen_size_x *= sh->disp_w;
254 if (screen_size_y <= 8)
255 screen_size_y *= sh->disp_h;
257 } else {
258 // check source format aspect, calculate prescale ::atmos
259 screen_size_x = sh->disp_w;
260 screen_size_y = sh->disp_h;
261 if (opts->screen_size_xy >= 0.001) {
262 if (opts->screen_size_xy <= 8) {
263 // -xy means x+y scale
264 screen_size_x *= opts->screen_size_xy;
265 screen_size_y *= opts->screen_size_xy;
266 } else {
267 // -xy means forced width while keeping correct aspect
268 screen_size_x = opts->screen_size_xy;
269 screen_size_y = opts->screen_size_xy * sh->disp_h / sh->disp_w;
272 if (sh->aspect > 0.01) {
273 int w;
274 mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_MovieAspectIsSet,
275 sh->aspect);
276 mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_ASPECT=%1.4f\n",
277 sh->aspect);
278 w = (int) ((float) screen_size_y * sh->aspect);
279 w += w % 2; // round
280 // we don't like horizontal downscale || user forced width:
281 if (w < screen_size_x || opts->screen_size_xy > 8) {
282 screen_size_y =
283 (int) ((float) screen_size_x * (1.0 / sh->aspect));
284 screen_size_y += screen_size_y % 2; // round
285 } else
286 screen_size_x = w; // keep new width
287 } else {
288 mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_MovieAspectUndefined);
292 vocfg_flags = (opts->fullscreen ? VOFLAG_FULLSCREEN : 0)
293 | (opts->vidmode ? VOFLAG_MODESWITCHING : 0)
294 | (opts->softzoom ? VOFLAG_SWSCALE : 0)
295 | (opts->flip ? VOFLAG_FLIPPING : 0);
297 // Time to config libvo!
298 mp_msg(MSGT_CPLAYER, MSGL_V,
299 "VO Config (%dx%d->%dx%d,flags=%d,'%s',0x%X)\n", sh->disp_w,
300 sh->disp_h, screen_size_x, screen_size_y, vocfg_flags, "MPlayer",
301 out_fmt);
303 vf->w = sh->disp_w;
304 vf->h = sh->disp_h;
305 if (vf_config_wrapper
306 (vf, sh->disp_w, sh->disp_h, screen_size_x, screen_size_y, vocfg_flags,
307 out_fmt) == 0) {
308 mp_msg(MSGT_CPLAYER, MSGL_WARN, MSGTR_CannotInitVO);
309 sh->vf_initialized = -1;
310 return 0;
313 sh->vf_initialized = 1;
315 if (opts->vo_gamma_gamma != 1000)
316 set_video_colors(sh, "gamma", opts->vo_gamma_gamma);
317 if (opts->vo_gamma_brightness != 1000)
318 set_video_colors(sh, "brightness", opts->vo_gamma_brightness);
319 if (opts->vo_gamma_contrast != 1000)
320 set_video_colors(sh, "contrast", opts->vo_gamma_contrast);
321 if (opts->vo_gamma_saturation != 1000)
322 set_video_colors(sh, "saturation", opts->vo_gamma_saturation);
323 if (opts->vo_gamma_hue != 1000)
324 set_video_colors(sh, "hue", opts->vo_gamma_hue);
326 return 1;
329 // mp_imgtype: buffering type, see mp_image.h
330 // mp_imgflag: buffer requirements (read/write, preserve, stride limits), see mp_image.h
331 // returns NULL or allocated mp_image_t*
332 // Note: buffer allocation may be moved to mpcodecs_config_vo() later...
333 mp_image_t *mpcodecs_get_image(sh_video_t *sh, int mp_imgtype, int mp_imgflag,
334 int w, int h)
336 mp_image_t *mpi =
337 vf_get_image(sh->vfilter, sh->codec->outfmt[sh->outfmtidx], mp_imgtype,
338 mp_imgflag, w, h);
339 if (mpi)
340 mpi->x = mpi->y = 0;
341 return mpi;
344 void mpcodecs_draw_slice(sh_video_t *sh, unsigned char **src, int *stride,
345 int w, int h, int x, int y)
347 struct vf_instance *vf = sh->vfilter;
349 if (vf->draw_slice)
350 vf->draw_slice(vf, src, stride, w, h, x, y);