2 * libvo common functions, variables used by many/all drivers.
4 * This file is part of MPlayer.
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.
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.
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.
28 //#include <sys/mman.h>
33 #include "video_out.h"
36 #include "old_vo_wrapper.h"
37 #include "input/input.h"
42 #include "osdep/shmem.h"
44 #include "x11_common.h"
47 int xinerama_screen
= -1;
51 int vo_nomouse_input
= 0;
52 int vo_grabpointer
= 1;
53 int vo_doublebuffering
= 1;
57 float vo_panscan
= 0.0f
;
59 int vo_refresh_rate
=0;
65 int vo_pts
=0; // for hw decoding
68 int vo_directrendering
=0;
70 int vo_colorkey
= 0x0000ff00; // default colorkey is green
71 // (0xff000000 means that colorkey has been disabled)
75 // Externally visible list of all vo drivers
77 extern struct vo_driver video_out_x11
;
78 extern struct vo_driver video_out_vdpau
;
79 extern struct vo_driver video_out_xv
;
80 extern struct vo_driver video_out_gl_nosw
;
81 extern struct vo_driver video_out_gl
;
82 extern struct vo_driver video_out_gl3
;
83 extern struct vo_driver video_out_sdl
;
84 extern struct vo_driver video_out_null
;
85 extern struct vo_driver video_out_png
;
86 extern struct vo_driver video_out_caca
;
87 extern struct vo_driver video_out_yuv4mpeg
;
88 extern struct vo_driver video_out_direct3d
;
89 extern struct vo_driver video_out_directx
;
90 extern struct vo_driver video_out_v4l2
;
91 extern struct vo_driver video_out_jpeg
;
92 extern struct vo_driver video_out_gif89a
;
93 extern struct vo_driver video_out_directfb
;
94 extern struct vo_driver video_out_tga
;
95 extern struct vo_driver video_out_corevideo
;
96 extern struct vo_driver video_out_sharedbuffer
;
97 extern struct vo_driver video_out_pnm
;
98 extern struct vo_driver video_out_md5sum
;
100 const struct vo_driver
*video_out_drivers
[] =
102 #ifdef CONFIG_DIRECTX
105 #ifdef CONFIG_DIRECT3D
108 #ifdef CONFIG_GL_COCOA
111 #ifdef CONFIG_COREVIDEO
112 &video_out_corevideo
,
122 #ifndef CONFIG_GL_COCOA
135 #ifdef CONFIG_V4L2_DECODER
139 // should not be auto-selected
140 #ifdef CONFIG_DIRECTFB
141 // vo directfb can call exit() if initialization fails
144 #ifdef CONFIG_YUV4MPEG
163 #ifdef CONFIG_SHAREDBUFFER
164 &video_out_sharedbuffer
,
175 static int vo_preinit(struct vo
*vo
, char *arg
)
177 if (vo
->driver
->privsize
)
178 vo
->priv
= talloc_zero_size(vo
, vo
->driver
->privsize
);
179 if (vo
->driver
->options
) {
180 struct m_config
*cfg
= m_config_simple(vo
->driver
->options
);
181 m_config_initialize(cfg
, vo
->priv
);
183 int l
= snprintf(n
, sizeof(n
), "vo/%s", vo
->driver
->info
->short_name
);
184 assert(l
< sizeof(n
));
185 int r
= m_config_parse_suboptions(cfg
, vo
->priv
, n
, arg
);
190 return vo
->driver
->preinit(vo
, arg
);
193 int vo_control(struct vo
*vo
, uint32_t request
, void *data
)
195 return vo
->driver
->control(vo
, request
, data
);
198 // Return -1 if driver appears not to support a draw_image interface,
199 // 0 otherwise (whether the driver actually drew something or not).
200 int vo_draw_image(struct vo
*vo
, struct mp_image
*mpi
, double pts
)
204 if (vo
->driver
->buffer_frames
) {
205 vo
->driver
->draw_image(vo
, mpi
, pts
);
208 vo
->frame_loaded
= true;
210 // Guaranteed to support at least DRAW_IMAGE later
211 if (vo
->driver
->is_new
) {
212 vo
->waiting_mpi
= mpi
;
215 if (vo_control(vo
, VOCTRL_DRAW_IMAGE
, mpi
) == VO_NOTIMPL
)
220 int vo_redraw_frame(struct vo
*vo
)
222 if (!vo
->config_ok
|| !vo
->hasframe
)
224 if (vo_control(vo
, VOCTRL_REDRAW_FRAME
, NULL
) == true) {
225 vo
->redrawing
= true;
231 int vo_get_buffered_frame(struct vo
*vo
, bool eof
)
235 if (vo
->frame_loaded
)
237 if (!vo
->driver
->buffer_frames
)
239 vo
->driver
->get_buffered_frame(vo
, eof
);
240 return vo
->frame_loaded
? 0 : -1;
243 void vo_skip_frame(struct vo
*vo
)
245 vo_control(vo
, VOCTRL_SKIPFRAME
, NULL
);
246 vo
->frame_loaded
= false;
249 int vo_draw_frame(struct vo
*vo
, uint8_t *src
[])
251 assert(!vo
->driver
->is_new
);
254 return old_vo_draw_frame(vo
, src
);
257 int vo_draw_slice(struct vo
*vo
, uint8_t *src
[], int stride
[], int w
, int h
, int x
, int y
)
259 return vo
->driver
->draw_slice(vo
, src
, stride
, w
, h
, x
, y
);
262 void vo_new_frame_imminent(struct vo
*vo
)
264 if (!vo
->driver
->is_new
)
266 if (vo
->driver
->buffer_frames
)
267 vo_control(vo
, VOCTRL_NEWFRAME
, NULL
);
269 vo_control(vo
, VOCTRL_DRAW_IMAGE
, vo
->waiting_mpi
);
270 vo
->waiting_mpi
= NULL
;
274 void vo_draw_osd(struct vo
*vo
, struct osd_state
*osd
)
278 vo
->driver
->draw_osd(vo
, osd
);
281 void vo_flip_page(struct vo
*vo
, unsigned int pts_us
, int duration
)
285 if (!vo
->redrawing
) {
286 vo
->frame_loaded
= false;
287 vo
->next_pts
= MP_NOPTS_VALUE
;
289 vo
->want_redraw
= false;
290 vo
->redrawing
= false;
291 if (vo
->driver
->flip_page_timed
)
292 vo
->driver
->flip_page_timed(vo
, pts_us
, duration
);
294 vo
->driver
->flip_page(vo
);
298 void vo_check_events(struct vo
*vo
)
300 if (!vo
->config_ok
) {
301 if (vo
->registered_fd
!= -1)
302 mp_input_rm_key_fd(vo
->input_ctx
, vo
->registered_fd
);
303 vo
->registered_fd
= -1;
306 vo
->driver
->check_events(vo
);
309 void vo_seek_reset(struct vo
*vo
)
311 vo_control(vo
, VOCTRL_RESET
, NULL
);
312 vo
->frame_loaded
= false;
313 vo
->hasframe
= false;
316 void vo_destroy(struct vo
*vo
)
318 if (vo
->registered_fd
!= -1)
319 mp_input_rm_key_fd(vo
->input_ctx
, vo
->registered_fd
);
320 vo
->driver
->uninit(vo
);
324 void list_video_out(void)
327 mp_tmsg(MSGT_CPLAYER
, MSGL_INFO
, "Available video output drivers:\n");
328 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VIDEO_OUTPUTS\n");
329 while (video_out_drivers
[i
]) {
330 const vo_info_t
*info
= video_out_drivers
[i
++]->info
;
331 mp_msg(MSGT_GLOBAL
, MSGL_INFO
,"\t%s\t%s\n", info
->short_name
, info
->name
);
333 mp_msg(MSGT_GLOBAL
, MSGL_INFO
,"\n");
336 struct vo
*init_best_video_out(struct MPOpts
*opts
, struct mp_fifo
*key_fifo
,
337 struct input_ctx
*input_ctx
)
339 char **vo_list
= opts
->video_driver_list
;
341 struct vo
*vo
= talloc_ptrtype(NULL
, vo
);
342 struct vo initial_values
= {
344 .key_fifo
= key_fifo
,
345 .input_ctx
= input_ctx
,
349 // first try the preferred drivers, with their optional subdevice param:
350 if (vo_list
&& vo_list
[0])
351 while (vo_list
[0][0]) {
352 char *name
= strdup(vo_list
[0]);
353 char *vo_subdevice
= strchr(name
,':');
354 if (!strcmp(name
, "pgm"))
355 mp_tmsg(MSGT_CPLAYER
, MSGL_ERR
, "The pgm video output driver has been replaced by -vo pnm:pgmyuv.\n");
356 if (!strcmp(name
, "md5"))
357 mp_tmsg(MSGT_CPLAYER
, MSGL_ERR
, "The md5 video output driver has been replaced by -vo md5sum.\n");
362 for (i
= 0; video_out_drivers
[i
]; i
++) {
363 const struct vo_driver
*video_driver
= video_out_drivers
[i
];
364 const vo_info_t
*info
= video_driver
->info
;
365 if (!strcmp(info
->short_name
, name
)) {
366 // name matches, try it
367 *vo
= initial_values
;
368 vo
->driver
= video_driver
;
369 if (!vo_preinit(vo
, vo_subdevice
)) {
371 return vo
; // success!
373 talloc_free_children(vo
);
381 return NULL
; // do NOT fallback to others
384 // now try the rest...
385 for (i
= 0; video_out_drivers
[i
]; i
++) {
386 const struct vo_driver
*video_driver
= video_out_drivers
[i
];
387 *vo
= initial_values
;
388 vo
->driver
= video_driver
;
389 if (!vo_preinit(vo
, NULL
))
390 return vo
; // success!
391 talloc_free_children(vo
);
397 static int event_fd_callback(void *ctx
, int fd
)
401 return MP_INPUT_NOTHING
;
404 int vo_config(struct vo
*vo
, uint32_t width
, uint32_t height
,
405 uint32_t d_width
, uint32_t d_height
, uint32_t flags
,
408 struct MPOpts
*opts
= vo
->opts
;
410 aspect_save_orig(vo
, width
, height
);
411 aspect_save_prescale(vo
, d_width
, d_height
);
413 if (vo_control(vo
, VOCTRL_UPDATE_SCREENINFO
, NULL
) == VO_TRUE
) {
414 aspect(vo
, &d_width
, &d_height
, A_NOZOOM
);
415 vo
->dx
= (int)(opts
->vo_screenwidth
- d_width
) / 2;
416 vo
->dy
= (int)(opts
->vo_screenheight
- d_height
) / 2;
417 geometry(&vo
->dx
, &vo
->dy
, &d_width
, &d_height
,
418 opts
->vo_screenwidth
, opts
->vo_screenheight
);
419 geometry_xy_changed
|= xinerama_screen
>= 0;
420 vo
->dx
+= xinerama_x
;
421 vo
->dy
+= xinerama_y
;
422 vo
->dwidth
= d_width
;
423 vo
->dheight
= d_height
;
426 int ret
= vo
->driver
->config(vo
, width
, height
, d_width
, d_height
, flags
,
428 vo
->config_ok
= (ret
== 0);
429 vo
->config_count
+= vo
->config_ok
;
430 if (vo
->registered_fd
== -1 && vo
->event_fd
!= -1 && vo
->config_ok
) {
431 mp_input_add_key_fd(vo
->input_ctx
, vo
->event_fd
, 1, event_fd_callback
,
433 vo
->registered_fd
= vo
->event_fd
;
435 vo
->frame_loaded
= false;
436 vo
->waiting_mpi
= NULL
;
437 vo
->redrawing
= false;
438 vo
->hasframe
= false;
443 * \brief lookup an integer in a table, table must have 0 as the last key
444 * \param key key to search for
445 * \result translation corresponding to key or "to" value of last mapping
448 int lookup_keymap_table(const struct mp_keymap
*map
, int key
) {
449 while (map
->from
&& map
->from
!= key
) map
++;
454 * \brief helper function for the kind of panscan-scaling that needs a source
455 * and destination rectangle like Direct3D and VDPAU
457 static void src_dst_split_scaling(int src_size
, int dst_size
, int scaled_src_size
,
458 int *src_start
, int *src_end
, int *dst_start
, int *dst_end
) {
459 if (scaled_src_size
> dst_size
) {
460 int border
= src_size
* (scaled_src_size
- dst_size
) / scaled_src_size
;
461 // round to a multiple of 2, this is at least needed for vo_direct3d and ATI cards
462 border
= (border
/ 2 + 1) & ~1;
464 *src_end
= src_size
- border
;
470 *dst_start
= (dst_size
- scaled_src_size
) / 2;
471 *dst_end
= *dst_start
+ scaled_src_size
;
476 * Calculate the appropriate source and destination rectangle to
477 * get a correctly scaled picture, including pan-scan.
478 * Can be extended to take future cropping support into account.
480 * \param crop specifies the cropping border size in the left, right, top and bottom members, may be NULL
481 * \param borders the border values as e.g. EOSD (ASS) and properly placed DVD highlight support requires,
482 * may be NULL and only left and top are currently valid.
484 void calc_src_dst_rects(struct vo
*vo
, int src_width
, int src_height
,
485 struct vo_rect
*src
, struct vo_rect
*dst
,
486 struct vo_rect
*borders
, const struct vo_rect
*crop
)
488 static const struct vo_rect no_crop
= {0, 0, 0, 0, 0, 0};
489 int scaled_width
= 0;
490 int scaled_height
= 0;
491 if (!crop
) crop
= &no_crop
;
492 src_width
-= crop
->left
+ crop
->right
;
493 src_height
-= crop
->top
+ crop
->bottom
;
494 if (src_width
< 2) src_width
= 2;
495 if (src_height
< 2) src_height
= 2;
496 dst
->left
= 0; dst
->right
= vo
->dwidth
;
497 dst
->top
= 0; dst
->bottom
= vo
->dheight
;
498 src
->left
= 0; src
->right
= src_width
;
499 src
->top
= 0; src
->bottom
= src_height
;
501 borders
->left
= 0; borders
->top
= 0;
503 if (aspect_scaling()) {
504 aspect(vo
, &scaled_width
, &scaled_height
, A_WINZOOM
);
505 panscan_calc_windowed(vo
);
506 scaled_width
+= vo
->panscan_x
;
507 scaled_height
+= vo
->panscan_y
;
509 borders
->left
= (vo
->dwidth
- scaled_width
) / 2;
510 borders
->top
= (vo
->dheight
- scaled_height
) / 2;
512 src_dst_split_scaling(src_width
, vo
->dwidth
, scaled_width
,
513 &src
->left
, &src
->right
, &dst
->left
, &dst
->right
);
514 src_dst_split_scaling(src_height
, vo
->dheight
, scaled_height
,
515 &src
->top
, &src
->bottom
, &dst
->top
, &dst
->bottom
);
517 src
->left
+= crop
->left
; src
->right
+= crop
->left
;
518 src
->top
+= crop
->top
; src
->bottom
+= crop
->top
;
519 src
->width
= src
->right
- src
->left
;
520 src
->height
= src
->bottom
- src
->top
;
521 dst
->width
= dst
->right
- dst
->left
;
522 dst
->height
= dst
->bottom
- dst
->top
;
525 // Return the window title the VO should set. Always returns a null terminated
526 // string. The string is valid until frontend code is invoked again. Copy it if
527 // you need to keep the string for an extended period of time.
528 const char *vo_get_window_title(struct vo
*vo
)
530 if (vo
->opts
->vo_wintitle
) {
531 return vo
->opts
->vo_wintitle
;
538 * Generates a mouse movement message if those are enable and sends it
539 * to the "main" MPlayer.
541 * \param posx new x position of mouse
542 * \param posy new y position of mouse
544 void vo_mouse_movement(struct vo
*vo
, int posx
, int posy
)
547 if (!enable_mouse_movements
)
549 snprintf(cmd_str
, sizeof(cmd_str
), "set_mouse_pos %i %i", posx
, posy
);
550 mp_input_queue_cmd(vo
->input_ctx
, mp_input_parse_cmd(cmd_str
));