2 * VDPAU video output driver
4 * Copyright (C) 2008 NVIDIA
6 * This file is part of MPlayer.
8 * MPlayer is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * MPlayer is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * \defgroup VDPAU_Presentation VDPAU Presentation
27 * Actual decoding and presentation are implemented here.
28 * All necessary frame information is collected through
29 * the "vdpau_render_state" structure after parsing all headers
30 * etc. in libavcodec for different codecs.
40 #include "video_out.h"
41 #include "video_out_internal.h"
42 #include "x11_common.h"
46 #include "libavcodec/vdpau.h"
48 #include "gui/interface.h"
50 #include "libavutil/common.h"
52 static vo_info_t info
= {
55 "Rajib Mahapatra <rmahapatra@nvidia.com> and others",
61 #define CHECK_ST_ERROR(message) \
62 if (vdp_st != VDP_STATUS_OK) { \
63 mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] %s: %s\n", \
64 message, vdp_get_error_string(vdp_st)); \
68 #define CHECK_ST_WARNING(message) \
69 if (vdp_st != VDP_STATUS_OK) \
70 mp_msg(MSGT_VO, MSGL_WARN, "[vdpau] %s: %s\n", \
71 message, vdp_get_error_string(vdp_st));
73 /* number of video and output surfaces */
74 #define NUM_OUTPUT_SURFACES 3
75 #define MAX_VIDEO_SURFACES 50
77 /* number of palette entries */
78 #define PALETTE_SIZE 256
81 * Global variable declaration - VDPAU specific
84 /* Declaration for all variables of win_x11_init_vdpau_procs() and
85 * win_x11_init_vdpau_flip_queue() functions
87 static VdpDevice vdp_device
;
88 static VdpDeviceCreateX11
*vdp_device_create
;
89 static VdpGetProcAddress
*vdp_get_proc_address
;
91 static VdpPresentationQueueTarget vdp_flip_target
;
92 static VdpPresentationQueue vdp_flip_queue
;
94 static VdpDeviceDestroy
*vdp_device_destroy
;
95 static VdpVideoSurfaceCreate
*vdp_video_surface_create
;
96 static VdpVideoSurfaceDestroy
*vdp_video_surface_destroy
;
98 static VdpGetErrorString
*vdp_get_error_string
;
100 /* May be used in software filtering/postprocessing options
101 * in MPlayer (./mplayer -vf ..) if we copy video_surface data to
104 static VdpVideoSurfacePutBitsYCbCr
*vdp_video_surface_put_bits_y_cb_cr
;
105 static VdpOutputSurfacePutBitsNative
*vdp_output_surface_put_bits_native
;
107 static VdpOutputSurfaceCreate
*vdp_output_surface_create
;
108 static VdpOutputSurfaceDestroy
*vdp_output_surface_destroy
;
110 /* VideoMixer puts video_surface data on displayable output_surface. */
111 static VdpVideoMixerCreate
*vdp_video_mixer_create
;
112 static VdpVideoMixerDestroy
*vdp_video_mixer_destroy
;
113 static VdpVideoMixerRender
*vdp_video_mixer_render
;
115 static VdpPresentationQueueTargetDestroy
*vdp_presentation_queue_target_destroy
;
116 static VdpPresentationQueueCreate
*vdp_presentation_queue_create
;
117 static VdpPresentationQueueDestroy
*vdp_presentation_queue_destroy
;
118 static VdpPresentationQueueDisplay
*vdp_presentation_queue_display
;
119 static VdpPresentationQueueBlockUntilSurfaceIdle
*vdp_presentation_queue_block_until_surface_idle
;
120 static VdpPresentationQueueTargetCreateX11
*vdp_presentation_queue_target_create_x11
;
122 /* output_surfaces[2] is used in composite-picture. */
123 static VdpOutputSurfaceRenderOutputSurface
*vdp_output_surface_render_output_surface
;
124 static VdpOutputSurfacePutBitsIndexed
*vdp_output_surface_put_bits_indexed
;
126 static VdpDecoderCreate
*vdp_decoder_create
;
127 static VdpDecoderDestroy
*vdp_decoder_destroy
;
128 static VdpDecoderRender
*vdp_decoder_render
;
130 static void *vdpau_lib_handle
;
131 static VdpOutputSurface output_surfaces
[NUM_OUTPUT_SURFACES
];
132 static int output_surface_width
, output_surface_height
;
134 static VdpVideoMixer video_mixer
;
136 static VdpDecoder decoder
;
137 static int decoder_max_refs
;
139 static VdpRect src_rect_vid
;
140 static VdpRect out_rect_vid
;
141 static int border_x
, border_y
;
143 static struct vdpau_render_state surface_render
[MAX_VIDEO_SURFACES
];
144 static int surface_num
;
145 static int vid_surface_num
;
146 static uint32_t vid_width
, vid_height
;
147 static uint32_t image_format
;
148 static const VdpChromaType vdp_chroma_type
= VDP_CHROMA_TYPE_420
;
151 static unsigned char *index_data
;
152 static int index_data_size
;
153 static uint32_t palette
[PALETTE_SIZE
];
158 static int visible_buf
;
159 static int int_pause
;
161 static void video_to_output_surface(void)
165 VdpOutputSurface output_surface
= output_surfaces
[surface_num
];
166 if (vid_surface_num
< 0)
169 vdp_st
= vdp_presentation_queue_block_until_surface_idle(vdp_flip_queue
,
172 CHECK_ST_WARNING("Error when calling vdp_presentation_queue_block_until_surface_idle")
174 vdp_st
= vdp_video_mixer_render(video_mixer
, VDP_INVALID_HANDLE
, 0,
175 VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME
,
176 0, NULL
, surface_render
[vid_surface_num
].surface
, 0, NULL
, &src_rect_vid
,
178 NULL
, &out_rect_vid
, 0, NULL
);
179 CHECK_ST_WARNING("Error when calling vdp_video_mixer_render")
182 static void resize(void)
186 struct vo_rect src_rect
;
187 struct vo_rect dst_rect
;
188 struct vo_rect borders
;
189 calc_src_dst_rects(vid_width
, vid_height
, &src_rect
, &dst_rect
, &borders
, NULL
);
190 out_rect_vid
.x0
= dst_rect
.left
;
191 out_rect_vid
.x1
= dst_rect
.right
;
192 out_rect_vid
.y0
= dst_rect
.top
;
193 out_rect_vid
.y1
= dst_rect
.bottom
;
194 src_rect_vid
.x0
= src_rect
.left
;
195 src_rect_vid
.x1
= src_rect
.right
;
196 src_rect_vid
.y0
= src_rect
.top
;
197 src_rect_vid
.y1
= src_rect
.bottom
;
198 border_x
= borders
.left
;
199 border_y
= borders
.top
;
200 #ifdef CONFIG_FREETYPE
201 // adjust font size to display size
204 vo_osd_changed(OSDTYPE_OSD
);
206 if (output_surface_width
< vo_dwidth
|| output_surface_height
< vo_dheight
) {
207 if (output_surface_width
< vo_dwidth
) {
208 output_surface_width
+= output_surface_width
>> 1;
209 output_surface_width
= FFMAX(output_surface_width
, vo_dwidth
);
211 if (output_surface_height
< vo_dheight
) {
212 output_surface_height
+= output_surface_height
>> 1;
213 output_surface_height
= FFMAX(output_surface_height
, vo_dheight
);
215 // Creation of output_surfaces
216 for (i
= 0; i
< NUM_OUTPUT_SURFACES
; i
++) {
217 if (output_surfaces
[i
] != VDP_INVALID_HANDLE
)
218 vdp_output_surface_destroy(output_surfaces
[i
]);
219 vdp_st
= vdp_output_surface_create(vdp_device
, VDP_RGBA_FORMAT_B8G8R8A8
,
220 output_surface_width
, output_surface_height
,
221 &output_surfaces
[i
]);
222 CHECK_ST_WARNING("Error when calling vdp_output_surface_create")
223 mp_msg(MSGT_VO
, MSGL_DBG2
, "OUT CREATE: %u\n", output_surfaces
[i
]);
226 video_to_output_surface();
231 /* Initialize vdp_get_proc_address, called from preinit() */
232 static int win_x11_init_vdpau_procs(void)
236 struct vdp_function
{
241 const struct vdp_function
*dsc
;
243 static const struct vdp_function vdp_func
[] = {
244 {VDP_FUNC_ID_GET_ERROR_STRING
, &vdp_get_error_string
},
245 {VDP_FUNC_ID_DEVICE_DESTROY
, &vdp_device_destroy
},
246 {VDP_FUNC_ID_VIDEO_SURFACE_CREATE
, &vdp_video_surface_create
},
247 {VDP_FUNC_ID_VIDEO_SURFACE_DESTROY
, &vdp_video_surface_destroy
},
248 {VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR
,
249 &vdp_video_surface_put_bits_y_cb_cr
},
250 {VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE
,
251 &vdp_output_surface_put_bits_native
},
252 {VDP_FUNC_ID_OUTPUT_SURFACE_CREATE
, &vdp_output_surface_create
},
253 {VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY
, &vdp_output_surface_destroy
},
254 {VDP_FUNC_ID_VIDEO_MIXER_CREATE
, &vdp_video_mixer_create
},
255 {VDP_FUNC_ID_VIDEO_MIXER_DESTROY
, &vdp_video_mixer_destroy
},
256 {VDP_FUNC_ID_VIDEO_MIXER_RENDER
, &vdp_video_mixer_render
},
257 {VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_DESTROY
,
258 &vdp_presentation_queue_target_destroy
},
259 {VDP_FUNC_ID_PRESENTATION_QUEUE_CREATE
, &vdp_presentation_queue_create
},
260 {VDP_FUNC_ID_PRESENTATION_QUEUE_DESTROY
,
261 &vdp_presentation_queue_destroy
},
262 {VDP_FUNC_ID_PRESENTATION_QUEUE_DISPLAY
,
263 &vdp_presentation_queue_display
},
264 {VDP_FUNC_ID_PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE
,
265 &vdp_presentation_queue_block_until_surface_idle
},
266 {VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11
,
267 &vdp_presentation_queue_target_create_x11
},
268 {VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE
,
269 &vdp_output_surface_render_output_surface
},
270 {VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_INDEXED
,
271 &vdp_output_surface_put_bits_indexed
},
272 {VDP_FUNC_ID_DECODER_CREATE
, &vdp_decoder_create
},
273 {VDP_FUNC_ID_DECODER_RENDER
, &vdp_decoder_render
},
274 {VDP_FUNC_ID_DECODER_DESTROY
, &vdp_decoder_destroy
},
278 vdp_st
= vdp_device_create(mDisplay
, mScreen
,
279 &vdp_device
, &vdp_get_proc_address
);
280 if (vdp_st
!= VDP_STATUS_OK
) {
281 mp_msg(MSGT_VO
, MSGL_ERR
, "[vdpau] Error when calling vdp_device_create_x11: %i\n", vdp_st
);
285 for (dsc
= vdp_func
; dsc
->pointer
; dsc
++) {
286 vdp_st
= vdp_get_proc_address(vdp_device
, dsc
->id
, dsc
->pointer
);
287 if (vdp_st
!= VDP_STATUS_OK
) {
288 mp_msg(MSGT_VO
, MSGL_ERR
, "[vdpau] Error when calling vdp_get_proc_address(function id %d): %s\n", dsc
->id
, vdp_get_error_string
? vdp_get_error_string(vdp_st
) : "?");
295 /* Initialize vdpau_flip_queue, called from config() */
296 static int win_x11_init_vdpau_flip_queue(void)
300 vdp_st
= vdp_presentation_queue_target_create_x11(vdp_device
, vo_window
,
302 CHECK_ST_ERROR("Error when calling vdp_presentation_queue_target_create_x11")
304 vdp_st
= vdp_presentation_queue_create(vdp_device
, vdp_flip_target
,
306 CHECK_ST_ERROR("Error when calling vdp_presentation_queue_create")
311 static int create_vdp_mixer(VdpChromaType vdp_chroma_type
) {
312 #define VDP_NUM_MIXER_PARAMETER 3
314 static const VdpVideoMixerParameter parameters
[VDP_NUM_MIXER_PARAMETER
] = {
315 VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH
,
316 VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT
,
317 VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE
319 const void *const parameter_values
[VDP_NUM_MIXER_PARAMETER
] = {
325 vdp_st
= vdp_video_mixer_create(vdp_device
, 0, 0,
326 VDP_NUM_MIXER_PARAMETER
,
327 parameters
, parameter_values
,
329 CHECK_ST_ERROR("Error when calling vdp_video_mixer_create")
334 // Free everything specific to a certain video file
335 static void free_video_specific(void) {
339 if (decoder
!= VDP_INVALID_HANDLE
)
340 vdp_decoder_destroy(decoder
);
341 decoder
= VDP_INVALID_HANDLE
;
342 decoder_max_refs
= -1;
344 for (i
= 0; i
< MAX_VIDEO_SURFACES
; i
++) {
345 if (surface_render
[i
].surface
!= VDP_INVALID_HANDLE
) {
346 vdp_st
= vdp_video_surface_destroy(surface_render
[i
].surface
);
347 CHECK_ST_WARNING("Error when calling vdp_video_surface_destroy")
349 surface_render
[i
].surface
= VDP_INVALID_HANDLE
;
352 if (video_mixer
!= VDP_INVALID_HANDLE
)
353 vdp_st
= vdp_video_mixer_destroy(video_mixer
);
354 CHECK_ST_WARNING("Error when calling vdp_video_mixer_destroy")
355 video_mixer
= VDP_INVALID_HANDLE
;
359 * connect to X server, create and map window, initialize all
360 * VDPAU objects, create different surfaces etc.
362 static int config(uint32_t width
, uint32_t height
, uint32_t d_width
,
363 uint32_t d_height
, uint32_t flags
, char *title
,
367 XSetWindowAttributes xswa
;
368 XWindowAttributes attribs
;
369 unsigned long xswamask
;
373 int vm
= flags
& VOFLAG_MODESWITCHING
;
376 image_format
= format
;
383 guiGetEvent(guiSetShVideo
, 0); // the GUI will set up / resize our window
392 XGetWindowAttributes(mDisplay
, DefaultRootWindow(mDisplay
), &attribs
);
393 depth
= attribs
.depth
;
394 if (depth
!= 15 && depth
!= 16 && depth
!= 24 && depth
!= 32)
396 XMatchVisualInfo(mDisplay
, mScreen
, depth
, TrueColor
, &vinfo
);
398 xswa
.background_pixel
= 0;
399 xswa
.border_pixel
= 0;
400 xswamask
= CWBackPixel
| CWBorderPixel
;
402 vo_x11_create_vo_window(&vinfo
, vo_dx
, vo_dy
, d_width
, d_height
,
403 flags
, CopyFromParent
, "vdpau", title
);
404 XChangeWindowAttributes(mDisplay
, vo_window
, xswamask
, &xswa
);
408 /* Grab the mouse pointer in our window */
410 XGrabPointer(mDisplay
, vo_window
, True
, 0,
411 GrabModeAsync
, GrabModeAsync
,
412 vo_window
, None
, CurrentTime
);
413 XSetInputFocus(mDisplay
, vo_window
, RevertToNone
, CurrentTime
);
418 if ((flags
& VOFLAG_FULLSCREEN
) && WinID
<= 0)
421 /* -----VDPAU related code here -------- */
423 free_video_specific();
425 if (vdp_flip_queue
== VDP_INVALID_HANDLE
&& win_x11_init_vdpau_flip_queue())
428 // video width and height
432 if (create_vdp_mixer(vdp_chroma_type
))
436 vid_surface_num
= -1;
442 static void check_events(void)
444 int e
= vo_x11_check_events(mDisplay
);
446 if (e
& VO_EVENT_RESIZE
)
449 if ((e
& VO_EVENT_EXPOSE
|| e
& VO_EVENT_RESIZE
) && int_pause
) {
450 /* did we already draw a buffer */
452 /* redraw the last visible buffer */
454 vdp_st
= vdp_presentation_queue_display(vdp_flip_queue
,
455 output_surfaces
[surface_num
],
456 vo_dwidth
, vo_dheight
,
458 CHECK_ST_WARNING("Error when calling vdp_presentation_queue_display")
463 static void draw_osd_I8A8(int x0
,int y0
, int w
,int h
, unsigned char *src
,
464 unsigned char *srca
, int stride
)
466 VdpOutputSurface output_surface
= output_surfaces
[surface_num
];
470 int index_data_size_required
;
471 VdpRect output_indexed_rect_vid
;
472 VdpOutputSurfaceRenderBlendState blend_state
;
477 index_data_size_required
= 2*w
*h
;
478 if (index_data_size
< index_data_size_required
) {
479 index_data
= realloc(index_data
, index_data_size_required
);
480 index_data_size
= index_data_size_required
;
483 // index_data creation, component order - I, A, I, A, .....
484 for (i
= 0; i
< h
; i
++)
485 for (j
= 0; j
< w
; j
++) {
486 index_data
[i
*2*w
+ j
*2] = src
[i
*stride
+j
];
487 index_data
[i
*2*w
+ j
*2 + 1] = -srca
[i
*stride
+j
];
490 output_indexed_rect_vid
.x0
= x0
;
491 output_indexed_rect_vid
.y0
= y0
;
492 output_indexed_rect_vid
.x1
= x0
+ w
;
493 output_indexed_rect_vid
.y1
= y0
+ h
;
497 // write source_data to output_surfaces[2].
498 vdp_st
= vdp_output_surface_put_bits_indexed(output_surfaces
[2],
499 VDP_INDEXED_FORMAT_I8A8
,
500 (const void *const*)&index_data
,
502 &output_indexed_rect_vid
,
503 VDP_COLOR_TABLE_FORMAT_B8G8R8X8
,
505 CHECK_ST_WARNING("Error when calling vdp_output_surface_put_bits_indexed")
507 blend_state
.struct_version
= VDP_OUTPUT_SURFACE_RENDER_BLEND_STATE_VERSION
;
508 blend_state
.blend_factor_source_color
= VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE
;
509 blend_state
.blend_factor_source_alpha
= VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE
;
510 blend_state
.blend_factor_destination_color
= VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA
;
511 blend_state
.blend_factor_destination_alpha
= VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA
;
512 blend_state
.blend_equation_color
= VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD
;
513 blend_state
.blend_equation_alpha
= VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD
;
515 vdp_st
= vdp_output_surface_render_output_surface(output_surface
,
516 &output_indexed_rect_vid
,
518 &output_indexed_rect_vid
,
521 VDP_OUTPUT_SURFACE_RENDER_ROTATE_0
);
522 CHECK_ST_WARNING("Error when calling vdp_output_surface_render_output_surface")
525 static void draw_osd(void)
527 mp_msg(MSGT_VO
, MSGL_DBG2
, "DRAW_OSD\n");
529 vo_draw_text_ext(vo_dwidth
, vo_dheight
, border_x
, border_y
, border_x
, border_y
,
530 vid_width
, vid_height
, draw_osd_I8A8
);
533 static void flip_page(void)
536 mp_msg(MSGT_VO
, MSGL_DBG2
, "\nFLIP_PAGE VID:%u -> OUT:%u\n",
537 surface_render
[vid_surface_num
].surface
, output_surfaces
[surface_num
]);
539 vdp_st
= vdp_presentation_queue_display(vdp_flip_queue
, output_surfaces
[surface_num
],
540 vo_dwidth
, vo_dheight
,
542 CHECK_ST_WARNING("Error when calling vdp_presentation_queue_display")
544 surface_num
= !surface_num
;
548 static int draw_slice(uint8_t *image
[], int stride
[], int w
, int h
,
552 struct vdpau_render_state
*rndr
= (struct vdpau_render_state
*)image
[0];
553 int max_refs
= image_format
== IMGFMT_VDPAU_H264
? rndr
->info
.h264
.num_ref_frames
: 2;
554 if (!IMGFMT_IS_VDPAU(image_format
))
556 if (decoder
== VDP_INVALID_HANDLE
|| decoder_max_refs
< max_refs
) {
557 VdpDecoderProfile vdp_decoder_profile
;
558 if (decoder
!= VDP_INVALID_HANDLE
)
559 vdp_decoder_destroy(decoder
);
560 decoder
= VDP_INVALID_HANDLE
;
561 switch (image_format
) {
562 case IMGFMT_VDPAU_MPEG1
:
563 vdp_decoder_profile
= VDP_DECODER_PROFILE_MPEG1
;
565 case IMGFMT_VDPAU_MPEG2
:
566 vdp_decoder_profile
= VDP_DECODER_PROFILE_MPEG2_MAIN
;
568 case IMGFMT_VDPAU_H264
:
569 vdp_decoder_profile
= VDP_DECODER_PROFILE_H264_HIGH
;
571 case IMGFMT_VDPAU_WMV3
:
572 vdp_decoder_profile
= VDP_DECODER_PROFILE_VC1_MAIN
;
574 case IMGFMT_VDPAU_VC1
:
575 vdp_decoder_profile
= VDP_DECODER_PROFILE_VC1_ADVANCED
;
578 vdp_st
= vdp_decoder_create(vdp_device
, vdp_decoder_profile
, vid_width
, vid_height
, max_refs
, &decoder
);
579 CHECK_ST_WARNING("Failed creating VDPAU decoder");
580 decoder_max_refs
= max_refs
;
582 vdp_st
= vdp_decoder_render(decoder
, rndr
->surface
, (void *)&rndr
->info
, rndr
->bitstream_buffers_used
, rndr
->bitstream_buffers
);
583 CHECK_ST_WARNING("Failed VDPAU decoder rendering");
588 static int draw_frame(uint8_t *src
[])
593 static struct vdpau_render_state
*get_surface(int number
)
595 if (number
> MAX_VIDEO_SURFACES
)
597 if (surface_render
[number
].surface
== VDP_INVALID_HANDLE
) {
599 vdp_st
= vdp_video_surface_create(vdp_device
, vdp_chroma_type
,
600 vid_width
, vid_height
,
601 &surface_render
[number
].surface
);
602 CHECK_ST_WARNING("Error when calling vdp_video_surface_create")
603 if (vdp_st
!= VDP_STATUS_OK
)
606 mp_msg(MSGT_VO
, MSGL_DBG2
, "VID CREATE: %u\n", surface_render
[number
].surface
);
607 return &surface_render
[number
];
610 static uint32_t draw_image(mp_image_t
*mpi
)
612 if (IMGFMT_IS_VDPAU(image_format
)) {
613 struct vdpau_render_state
*rndr
= mpi
->priv
;
614 vid_surface_num
= rndr
- surface_render
;
615 } else if (!(mpi
->flags
& MP_IMGFLAG_DRAW_CALLBACK
)) {
617 void *destdata
[3] = {mpi
->planes
[0], mpi
->planes
[2], mpi
->planes
[1]};
618 struct vdpau_render_state
*rndr
= get_surface(0);
619 vid_surface_num
= rndr
- surface_render
;
620 vdp_st
= vdp_video_surface_put_bits_y_cb_cr(rndr
->surface
,
621 VDP_YCBCR_FORMAT_YV12
,
622 (const void *const*)destdata
,
623 mpi
->stride
); // pitch
624 CHECK_ST_ERROR("Error when calling vdp_video_surface_put_bits_y_cb_cr")
627 video_to_output_surface();
631 static uint32_t get_image(mp_image_t
*mpi
)
633 struct vdpau_render_state
*rndr
;
635 // no dr for non-decoding for now
636 if (!IMGFMT_IS_VDPAU(image_format
)) return VO_FALSE
;
637 if (mpi
->type
!= MP_IMGTYPE_NUMBERED
) return VO_FALSE
;
639 rndr
= get_surface(mpi
->number
);
641 mp_msg(MSGT_VO
, MSGL_ERR
, "[vdpau] no surfaces available in get_image\n");
642 // TODO: this probably breaks things forever, provide a dummy buffer?
645 mpi
->flags
|= MP_IMGFLAG_DIRECT
;
646 mpi
->stride
[0] = mpi
->stride
[1] = mpi
->stride
[2] = 0;
647 mpi
->planes
[0] = mpi
->planes
[1] = mpi
->planes
[2] = NULL
;
648 // hack to get around a check and to avoid a special-case in vd_ffmpeg.c
649 mpi
->planes
[0] = (void *)rndr
;
655 static int query_format(uint32_t format
)
659 case IMGFMT_VDPAU_MPEG1
:
660 case IMGFMT_VDPAU_MPEG2
:
661 case IMGFMT_VDPAU_H264
:
662 case IMGFMT_VDPAU_WMV3
:
663 case IMGFMT_VDPAU_VC1
:
664 return VFCAP_CSP_SUPPORTED
| VFCAP_CSP_SUPPORTED_BY_HW
| VFCAP_HWSCALE_UP
| VFCAP_HWSCALE_DOWN
| VFCAP_OSD
;
669 static void DestroyVdpauObjects(void)
674 free_video_specific();
676 vdp_st
= vdp_presentation_queue_destroy(vdp_flip_queue
);
677 CHECK_ST_WARNING("Error when calling vdp_presentation_queue_destroy")
679 vdp_st
= vdp_presentation_queue_target_destroy(vdp_flip_target
);
680 CHECK_ST_WARNING("Error when calling vdp_presentation_queue_target_destroy")
682 for (i
= 0; i
< NUM_OUTPUT_SURFACES
; i
++) {
683 vdp_st
= vdp_output_surface_destroy(output_surfaces
[i
]);
684 output_surfaces
[i
] = VDP_INVALID_HANDLE
;
685 CHECK_ST_WARNING("Error when calling vdp_output_surface_destroy")
688 vdp_st
= vdp_device_destroy(vdp_device
);
689 CHECK_ST_WARNING("Error when calling vdp_device_destroy")
692 static void uninit(void)
694 if (!vo_config_count
)
698 /* Destroy all vdpau objects */
699 DestroyVdpauObjects();
709 dlclose(vdpau_lib_handle
);
712 static int preinit(const char *arg
)
715 static const char *vdpaulibrary
= "libvdpau.so.1";
716 static const char *vdpau_device_create
= "vdp_device_create_x11";
719 mp_msg(MSGT_VO
, MSGL_ERR
, "[vdpau] Unknown subdevice: %s\n", arg
);
723 vdpau_lib_handle
= dlopen(vdpaulibrary
, RTLD_LAZY
);
724 if (!vdpau_lib_handle
) {
725 mp_msg(MSGT_VO
, MSGL_ERR
, "[vdpau] Could not open dynamic library %s\n",
729 vdp_device_create
= dlsym(vdpau_lib_handle
, vdpau_device_create
);
730 if (!vdp_device_create
) {
731 mp_msg(MSGT_VO
, MSGL_ERR
, "[vdpau] Could not find function %s in %s\n",
732 vdpau_device_create
, vdpaulibrary
);
735 if (!vo_init() || win_x11_init_vdpau_procs())
738 decoder
= VDP_INVALID_HANDLE
;
739 for (i
= 0; i
< MAX_VIDEO_SURFACES
; i
++)
740 surface_render
[i
].surface
= VDP_INVALID_HANDLE
;
741 video_mixer
= VDP_INVALID_HANDLE
;
742 for (i
= 0; i
< NUM_OUTPUT_SURFACES
; i
++)
743 output_surfaces
[i
] = VDP_INVALID_HANDLE
;
744 vdp_flip_queue
= VDP_INVALID_HANDLE
;
745 output_surface_width
= output_surface_height
= -1;
747 // full grayscale palette.
748 for (i
= 0; i
< PALETTE_SIZE
; ++i
)
749 palette
[i
] = (i
<< 16) | (i
<< 8) | i
;
756 static int control(uint32_t request
, void *data
)
760 return (int_pause
= 1);
762 return (int_pause
= 0);
763 case VOCTRL_QUERY_FORMAT
:
764 return query_format(*(uint32_t *)data
);
765 case VOCTRL_GET_IMAGE
:
766 return get_image(data
);
767 case VOCTRL_DRAW_IMAGE
:
768 return draw_image(data
);
769 case VOCTRL_GUISUPPORT
:
775 case VOCTRL_FULLSCREEN
:
779 case VOCTRL_GET_PANSCAN
:
781 case VOCTRL_SET_PANSCAN
:
784 case VOCTRL_SET_EQUALIZER
: {
785 struct voctrl_set_equalizer_args
*args
= data
;
786 return vo_x11_set_equalizer(args
->name
, args
->value
);
788 case VOCTRL_GET_EQUALIZER
:
790 struct voctrl_get_equalizer_args
*args
= data
;
791 return vo_x11_get_equalizer(args
->name
, args
->valueptr
);
796 case VOCTRL_UPDATE_SCREENINFO
:
797 update_xinerama_info();