[Mplayerxp-cvslog] SF.net SVN: mplayerxp:[43] mplayerxp
Brought to you by:
olov
From: <nic...@us...> - 2009-12-16 15:56:11
|
Revision: 43 http://mplayerxp.svn.sourceforge.net/mplayerxp/?rev=43&view=rev Author: nickols_k Date: 2009-12-16 15:56:00 +0000 (Wed, 16 Dec 2009) Log Message: ----------- import stuff from mphq (may not work) Modified Paths: -------------- mplayerxp/Makefile mplayerxp/configure mplayerxp/libvo/Makefile mplayerxp/libvo/aspect.c mplayerxp/libvo/aspect.h mplayerxp/libvo/video_out.c mplayerxp/libvo/video_out.h mplayerxp/libvo/vo_opengl.c Added Paths: ----------- mplayerxp/libvo/vo_vdpau.c mplayerxp/subopt-helper.c mplayerxp/subopt-helper.h Modified: mplayerxp/Makefile =================================================================== --- mplayerxp/Makefile 2009-12-15 18:08:49 UTC (rev 42) +++ mplayerxp/Makefile 2009-12-16 15:56:00 UTC (rev 43) @@ -24,7 +24,7 @@ LDFLAGS += -Wl,-rpath,${CODECDIR}/codecs -SRCS_COMMON = cpudetect.c mp_msg.c codec-cfg.c cfgparser.c my_profile.c my_malloc.c spudec.c playtree.c playtreeparser.c asxparser.c mp_image.c +SRCS_COMMON = cpudetect.c mp_msg.c codec-cfg.c cfgparser.c my_profile.c my_malloc.c spudec.c playtree.c playtreeparser.c asxparser.c mp_image.c subopt-helper.c SRCS_MPLAYER = mplayer.c $(SRCS_COMMON) find_sub.c subreader.c mixer.c vobsub.c mp-opt-reg.c sig_hand.c dump.c dec_ahead.c m_option.c m_property.c m_struct.c OBJS_MPLAYER = $(SRCS_MPLAYER:.c=.o) Modified: mplayerxp/configure =================================================================== --- mplayerxp/configure 2009-12-15 18:08:49 UTC (rev 42) +++ mplayerxp/configure 2009-12-16 15:56:00 UTC (rev 43) @@ -92,6 +92,7 @@ --enable-xf86vm build with Xf86vm support for X11 [autodetect] --enable-xv build with Xv render support for X 4.x [autodetect] --enable-opengl build with OpenGL render support [autodetect] + --enable-vdpau build with VDPAU render support [autodetect] --enable-fbdev build with FBDev render support [autodetect] --enable-fbdev=nocopy yuv12 converts directly into framebuffer --enable-mlib build with MLIB support (Solaris only) [autodetect] @@ -374,6 +375,7 @@ xinerama xf86vm opengl + vdpau dga vesa vidix @@ -415,6 +417,8 @@ --disable-xv) xv=no ;; --enable-opengl) opengl=yes ;; --disable-opengl) opengl=no ;; + --enable-vdpau) vdpau=yes ;; + --disable-vdpau) vdpau=no ;; --enable-sdl) sdl=yes ;; --disable-sdl) sdl=no ;; --enable-sdl-image) sdl_image=yes ;; @@ -848,6 +852,10 @@ print_config HAVE_ mp_config.h mp_config.mak opengl enabled opengl && _vomodules="opengl $_vomodules" || _novomodules="opengl $_novomodules" +enabled vdpau && require3 vdpau "vdpau/vdpau_x11.h" VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 vdp_device_create_x11 -lvdpau +print_config HAVE_ mp_config.h mp_config.mak vdpau +enabled vdpau && _vomodules="vdpau $_vomodules" || _novomodules="vdpau $_novomodules" + # Note: the -lXxf86vm library is the VideoMode extension and though it's not # needed for DGA, AFAIK every distribution packages together with DGA stuffs # named 'X extensions' or something similar. Modified: mplayerxp/libvo/Makefile =================================================================== --- mplayerxp/libvo/Makefile 2009-12-15 18:08:49 UTC (rev 42) +++ mplayerxp/libvo/Makefile 2009-12-16 15:56:00 UTC (rev 43) @@ -10,6 +10,9 @@ ifeq ($(HAVE_OPENGL),yes) SRCS+=gl_common.c vo_opengl.c endif +ifeq ($(HAVE_VDPAU),yes) +SRCS+=vo_vdpau.c +endif ifeq ($(HAVE_X11),yes) SRCS+=vo_x11.c x11_common.c ifeq ($(CONFIG_VIDIX),yes) Modified: mplayerxp/libvo/aspect.c =================================================================== --- mplayerxp/libvo/aspect.c 2009-12-15 18:08:49 UTC (rev 42) +++ mplayerxp/libvo/aspect.c 2009-12-16 15:56:00 UTC (rev 43) @@ -12,25 +12,25 @@ float monitor_pixel_aspect=1; static struct { - int orgw; // real width - int orgh; // real height - int prew; // prescaled width - int preh; // prescaled height - int scrw; // horizontal resolution - int scrh; // vertical resolution + uint32_t orgw; // real width + uint32_t orgh; // real height + uint32_t prew; // prescaled width + uint32_t preh; // prescaled height + uint32_t scrw; // horizontal resolution + uint32_t scrh; // vertical resolution } aspdat; -void __FASTCALL__ aspect_save_orig(int orgw, int orgh){ +void __FASTCALL__ aspect_save_orig(uint32_t orgw, uint32_t orgh){ aspdat.orgw = orgw; aspdat.orgh = orgh; } -void __FASTCALL__ aspect_save_prescale(int prew, int preh){ +void __FASTCALL__ aspect_save_prescale(uint32_t prew, uint32_t preh){ aspdat.prew = prew; aspdat.preh = preh; } -void __FASTCALL__ aspect_save_screenres(int scrw, int scrh){ +void __FASTCALL__ aspect_save_screenres(uint32_t scrw, uint32_t scrh){ aspdat.scrw = scrw; aspdat.scrh = scrh; monitor_aspect = monitor_pixel_aspect * scrw / scrh; @@ -40,8 +40,8 @@ * resolution, that the scaled image should fit into */ -void __FASTCALL__ aspect(int *srcw, int *srch, int zoom){ - int tmpw; +void __FASTCALL__ aspect(uint32_t *srcw, uint32_t *srch, int zoom){ + uint32_t tmpw; #ifdef ASPECT_DEBUG MSG_DBG2("aspect(0) fitin: %dx%d zoom: %d \n",aspdat.scrw,aspdat.scrh,zoom); @@ -52,19 +52,19 @@ { /* Landscape mode */ *srcw = aspdat.scrw; - *srch = (int)(((float)aspdat.scrw / (float)aspdat.prew * (float)aspdat.preh) + *srch = (uint32_t)(((float)aspdat.scrw / (float)aspdat.prew * (float)aspdat.preh) * ((float)aspdat.scrh / ((float)aspdat.scrw / monitor_aspect))); } else { /* Portrait mode */ *srch = aspdat.scrh; - *srcw = (int)(((float)aspdat.scrh / (float)aspdat.preh * (float)aspdat.prew) + *srcw = (uint32_t)(((float)aspdat.scrh / (float)aspdat.preh * (float)aspdat.prew) * ((float)aspdat.scrw / ((float)aspdat.scrh * monitor_aspect))); } }else{ *srcw = aspdat.prew; - *srch = (int)((float)aspdat.preh + *srch = (uint32_t)((float)aspdat.preh * ((float)aspdat.scrh / ((float)aspdat.scrw / monitor_aspect))); } (*srch)+= (*srch)%2; // round @@ -73,10 +73,10 @@ #endif if(*srch>aspdat.scrh || *srch<aspdat.orgh){ if(zoom) - tmpw = (int)(((float)aspdat.scrh / (float)aspdat.preh * (float)aspdat.prew) + tmpw = (uint32_t)(((float)aspdat.scrh / (float)aspdat.preh * (float)aspdat.prew) * ((float)aspdat.scrw / ((float)aspdat.scrh / (1.0/monitor_aspect)))); else - tmpw = (int)((float)aspdat.prew + tmpw = (uint32_t)((float)aspdat.prew * ((float)aspdat.scrw / ((float)aspdat.scrh / (1.0/monitor_aspect)))); if(tmpw<=aspdat.scrw && tmpw>=aspdat.orgw){ *srch = zoom?aspdat.scrh:aspdat.preh; Modified: mplayerxp/libvo/aspect.h =================================================================== --- mplayerxp/libvo/aspect.h 2009-12-15 18:08:49 UTC (rev 42) +++ mplayerxp/libvo/aspect.h 2009-12-16 15:56:00 UTC (rev 43) @@ -1,16 +1,17 @@ #ifndef __ASPECT_H #define __ASPECT_H /* Stuff for correct aspect scaling. */ +#include <stdint.h> #include "../mp_config.h" -void __FASTCALL__ aspect_save_orig(int orgw, int orgh); -void __FASTCALL__ aspect_save_prescale(int prew, int preh); -void __FASTCALL__ aspect_save_screenres(int scrw, int scrh); +void __FASTCALL__ aspect_save_orig(uint32_t orgw, uint32_t orgh); +void __FASTCALL__ aspect_save_prescale(uint32_t prew, uint32_t preh); +void __FASTCALL__ aspect_save_screenres(uint32_t scrw, uint32_t scrh); #define A_ZOOM 1 #define A_NOZOOM 0 -void __FASTCALL__ aspect(int *srcw, int *srch, int zoom); +void __FASTCALL__ aspect(uint32_t *srcw, uint32_t *srch, int zoom); #endif Modified: mplayerxp/libvo/video_out.c =================================================================== --- mplayerxp/libvo/video_out.c 2009-12-15 18:08:49 UTC (rev 42) +++ mplayerxp/libvo/video_out.c 2009-12-16 15:56:00 UTC (rev 43) @@ -111,6 +111,7 @@ extern vo_functions_t video_out_fbdev; extern vo_functions_t video_out_png; extern vo_functions_t video_out_opengl; +extern vo_functions_t video_out_vdpau; #ifdef HAVE_VESA extern vo_functions_t video_out_vesa; #endif @@ -126,6 +127,9 @@ #ifdef HAVE_OPENGL &video_out_opengl, #endif +#ifdef HAVE_VDPAU + &video_out_vdpau, +#endif #if defined(CONFIG_VIDIX) && defined(HAVE_X11) &video_out_xvidix, #endif Modified: mplayerxp/libvo/video_out.h =================================================================== --- mplayerxp/libvo/video_out.h 2009-12-15 18:08:49 UTC (rev 42) +++ mplayerxp/libvo/video_out.h 2009-12-16 15:56:00 UTC (rev 43) @@ -182,6 +182,10 @@ extern void vo_uninit( void ); extern uint32_t __FASTCALL__ vo_control(uint32_t request, void *data); +struct vo_rect { + int left, right, top, bottom, width, height; +}; + /** Contains geometry of fourcc */ typedef struct s_vo_format_desc { Modified: mplayerxp/libvo/vo_opengl.c =================================================================== --- mplayerxp/libvo/vo_opengl.c 2009-12-15 18:08:49 UTC (rev 42) +++ mplayerxp/libvo/vo_opengl.c 2009-12-16 15:56:00 UTC (rev 43) @@ -28,6 +28,7 @@ #include "video_out_internal.h" #include "font_load.h" #include "sub.h" +#include "subopt-helper.h" #include "gl_common.h" #include "aspect.h" @@ -423,6 +424,7 @@ return -1; #else { +#if 0 XVisualInfo *vinfo=glXChooseVisual( mDisplay,mScreen,wsGLXAttrib ); if (vinfo == NULL) { @@ -430,12 +432,9 @@ return -1; } MSG_V("[gl] GLX chose visual with ID 0x%x\n", (int)vinfo->visualid); - +#endif vo_x11_calcpos(&hint,d_width,d_height,flags); glutInitDisplayMode(GLUT_RGBA); -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) - glutInitDisplayString("MPlayerXP"); -#endif glutInitWindowPosition(hint.x, hint.y); glutInitWindowSize(hint.width, hint.height); gl_win=glutCreateWindow("MPlayerXP"); @@ -853,7 +852,6 @@ glutDestroyWindow(gl_win); } -#if 0 static const opt_t subopts[] = { {"manyfmts", OPT_ARG_BOOL, &many_fmts, NULL}, {"osd", OPT_ARG_BOOL, &use_osd, NULL}, @@ -878,7 +876,6 @@ {"osdcolor", OPT_ARG_INT, &osd_color, NULL}, {NULL} }; -#endif static uint32_t __FASTCALL__ preinit(const char *arg) { @@ -904,7 +901,7 @@ custom_tlin = 1; custom_trect = 0; osd_color = 0xffffff; -#if 0 + if (subopt_parse(arg, subopts) != 0) { MSG_FATAL( "\n-vo gl command line help:\n" @@ -968,7 +965,7 @@ "\n" ); return -1; } -#endif + if (use_rectangle == 1) gl_target = GL_TEXTURE_RECTANGLE; else Added: mplayerxp/libvo/vo_vdpau.c =================================================================== --- mplayerxp/libvo/vo_vdpau.c (rev 0) +++ mplayerxp/libvo/vo_vdpau.c 2009-12-16 15:56:00 UTC (rev 43) @@ -0,0 +1,1288 @@ +/* + * VDPAU video output driver + * + * Copyright (C) 2008 NVIDIA + * + * This file is part of MPlayer. + * + * MPlayer is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * MPlayer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with MPlayer; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/** + * \defgroup VDPAU_Presentation VDPAU Presentation + * \ingroup Decoder + * + * Actual decoding and presentation are implemented here. + * All necessary frame information is collected through + * the "vdpau_render_state" structure after parsing all headers + * etc. in libavcodec for different codecs. + * + * @{ + */ + +#include <stdio.h> +#include <stdlib.h> + +#include "../mp_config.h" +#include "../mplayer.h" +#include "../dec_ahead.h" +#include "video_out.h" +#include "video_out_internal.h" +#include "x11_common.h" +#include "aspect.h" +#include "sub.h" +#include "subopt-helper.h" +#include "../postproc/vfcap.h" +#include "libavcodec/vdpau.h" +#include "libavutil/common.h" +#include "libavutil/mathematics.h" + +#include "vo_msg.h" + +static vo_info_t vo_info = { + "VDPAU with X11", + "vdpau", + "Rajib Mahapatra <rma...@nv...> and others", + "" +}; + +LIBVO_EXTERN(vdpau) + +static const vo_info_t *get_info(void) +{ + return(&vo_info); +} + +#define CHECK_ST_ERROR(message) \ + if (vdp_st != VDP_STATUS_OK) { \ + MSG_ERR("[vdpau] %s: %s\n", \ + message, vdp_get_error_string(vdp_st)); \ + return -1; \ + } + +#define CHECK_ST_WARNING(message) \ + if (vdp_st != VDP_STATUS_OK) \ + MSG_WARN("[vdpau] %s: %s\n", \ + message, vdp_get_error_string(vdp_st)); + +/* number of video and output surfaces */ +#define NUM_OUTPUT_SURFACES 2 +#define MAX_VIDEO_SURFACES 50 + +/* number of palette entries */ +#define PALETTE_SIZE 256 + +/* + * Global variable declaration - VDPAU specific + */ + +/* Declaration for all variables of win_x11_init_vdpau_procs() and + * win_x11_init_vdpau_flip_queue() functions + */ +static VdpDevice vdp_device; +static VdpGetProcAddress *vdp_get_proc_address; + +static VdpPresentationQueueTarget vdp_flip_target; +static VdpPresentationQueue vdp_flip_queue; + +static VdpDeviceDestroy *vdp_device_destroy; +static VdpVideoSurfaceCreate *vdp_video_surface_create; +static VdpVideoSurfaceDestroy *vdp_video_surface_destroy; + +static VdpGetErrorString *vdp_get_error_string; + +/* May be used in software filtering/postprocessing options + * in MPlayer (./mplayer -vf ..) if we copy video_surface data to + * system memory. + */ +static VdpVideoSurfacePutBitsYCbCr *vdp_video_surface_put_bits_y_cb_cr; +static VdpOutputSurfacePutBitsNative *vdp_output_surface_put_bits_native; + +static VdpOutputSurfaceCreate *vdp_output_surface_create; +static VdpOutputSurfaceDestroy *vdp_output_surface_destroy; + +/* VideoMixer puts video_surface data on displayable output_surface. */ +static VdpVideoMixerCreate *vdp_video_mixer_create; +static VdpVideoMixerDestroy *vdp_video_mixer_destroy; +static VdpVideoMixerRender *vdp_video_mixer_render; +static VdpVideoMixerSetFeatureEnables *vdp_video_mixer_set_feature_enables; +static VdpVideoMixerSetAttributeValues *vdp_video_mixer_set_attribute_values; + +static VdpPresentationQueueTargetDestroy *vdp_presentation_queue_target_destroy; +static VdpPresentationQueueCreate *vdp_presentation_queue_create; +static VdpPresentationQueueDestroy *vdp_presentation_queue_destroy; +static VdpPresentationQueueDisplay *vdp_presentation_queue_display; +static VdpPresentationQueueBlockUntilSurfaceIdle *vdp_presentation_queue_block_until_surface_idle; +static VdpPresentationQueueTargetCreateX11 *vdp_presentation_queue_target_create_x11; + +static VdpOutputSurfaceRenderOutputSurface *vdp_output_surface_render_output_surface; +static VdpOutputSurfacePutBitsIndexed *vdp_output_surface_put_bits_indexed; +static VdpOutputSurfaceRenderBitmapSurface *vdp_output_surface_render_bitmap_surface; + +static VdpBitmapSurfaceCreate *vdp_bitmap_surface_create; +static VdpBitmapSurfaceDestroy *vdp_bitmap_surface_destroy; +static VdpBitmapSurfacePutBitsNative *vdp_bitmap_surface_putbits_native; + +static VdpDecoderCreate *vdp_decoder_create; +static VdpDecoderDestroy *vdp_decoder_destroy; +static VdpDecoderRender *vdp_decoder_render; + +static VdpGenerateCSCMatrix *vdp_generate_csc_matrix; +static VdpPreemptionCallbackRegister *vdp_preemption_callback_register; + +/* output_surfaces[NUM_OUTPUT_SURFACES] is misused for OSD. */ +#define osd_surface output_surfaces[NUM_OUTPUT_SURFACES] +static VdpOutputSurface output_surfaces[NUM_OUTPUT_SURFACES + 1]; +static VdpVideoSurface deint_surfaces[3]; +static mp_image_t *deint_mpi[2]; +static uint32_t output_surface_width, output_surface_height; + +static VdpVideoMixer video_mixer; +static int deint; +static int deint_type; +static int deint_counter; +static int deint_buffer_past_frames; +static int pullup; +static float denoise; +static float sharpen; +static int colorspace; +static int chroma_deint; +static int force_mixer; +static int top_field_first; +static int hqscaling; + +static VdpDecoder decoder; +static int decoder_max_refs; + +static VdpRect src_rect_vid; +static VdpRect out_rect_vid; +static int border_x, border_y; +static uint32_t dwidth,dheight; + +static struct vdpau_render_state surface_render[MAX_VIDEO_SURFACES]; +static int surface_num; +static int vid_surface_num; +static uint32_t vid_width, vid_height; +static uint32_t image_format; +static VdpChromaType vdp_chroma_type; +static VdpYCbCrFormat vdp_pixel_format; + +static volatile int is_preempted; + +/* draw_osd */ +static unsigned char *index_data; +static int index_data_size; +static uint32_t palette[PALETTE_SIZE]; +static void draw_osd(void); + +// Video equalizer +static VdpProcamp procamp; + +/* + * X11 specific + */ +static int visible_buf; +static int int_pause; + +static void push_deint_surface(VdpVideoSurface surface) +{ + deint_surfaces[2] = deint_surfaces[1]; + deint_surfaces[1] = deint_surfaces[0]; + deint_surfaces[0] = surface; +} + +static void video_to_output_surface(void) +{ + VdpTime dummy; + VdpStatus vdp_st; + int i; + if (vid_surface_num < 0) + return; + + if (deint < 2 || deint_surfaces[0] == VDP_INVALID_HANDLE) + push_deint_surface(surface_render[vid_surface_num].surface); + + for (i = 0; i <= !!(deint > 1); i++) { + int field = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME; + VdpOutputSurface output_surface; + if (i) { + draw_osd(); + flip_page(0); + } + if (deint) + field = (top_field_first == i) ^ (deint > 1) ? + VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD: + VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD; + output_surface = output_surfaces[surface_num]; + vdp_st = vdp_presentation_queue_block_until_surface_idle(vdp_flip_queue, + output_surface, + &dummy); + CHECK_ST_WARNING("Error when calling vdp_presentation_queue_block_until_surface_idle") + + vdp_st = vdp_video_mixer_render(video_mixer, VDP_INVALID_HANDLE, 0, + field, 2, deint_surfaces + 1, + deint_surfaces[0], + 1, &surface_render[vid_surface_num].surface, + &src_rect_vid, + output_surface, + NULL, &out_rect_vid, 0, NULL); + CHECK_ST_WARNING("Error when calling vdp_video_mixer_render") + push_deint_surface(surface_render[vid_surface_num].surface); + } +} + +static void resize(int x,int y) +{ + VdpStatus vdp_st; + int i; + struct vo_rect src_rect; + struct vo_rect dst_rect; + struct vo_rect borders; + int w = x, h = y; + aspect(&w,&h,A_ZOOM); + dst_rect.left=( vo_screenwidth - (dwidth > vo_screenwidth?vo_screenwidth:dwidth) ) / 2; + dst_rect.top=( vo_screenheight - (dheight > vo_screenheight?vo_screenheight:dheight) ) / 2; + w=(dwidth > vo_screenwidth?vo_screenwidth:dwidth); + h=(dheight > vo_screenheight?vo_screenheight:dheight); + dst_rect.bottom=dst_rect.top+h; + dst_rect.right=dst_rect.left+w; + + out_rect_vid.x0 = dst_rect.left; + out_rect_vid.x1 = dst_rect.right; + out_rect_vid.y0 = dst_rect.top; + out_rect_vid.y1 = dst_rect.bottom; + src_rect_vid.x0 = src_rect.left; + src_rect_vid.x1 = src_rect.right; + src_rect_vid.y0 = flip ? src_rect.bottom : src_rect.top; + src_rect_vid.y1 = flip ? src_rect.top : src_rect.bottom; + border_x = borders.left; + border_y = borders.top; +#ifdef CONFIG_FREETYPE + // adjust font size to display size + force_load_font = 1; +#endif + vo_osd_changed(OSDTYPE_OSD); + + if (output_surface_width < vo_dwidth || output_surface_height < vo_dheight) { + if (output_surface_width < vo_dwidth) { + output_surface_width += output_surface_width >> 1; + output_surface_width = FFMAX(output_surface_width, vo_dwidth); + } + if (output_surface_height < vo_dheight) { + output_surface_height += output_surface_height >> 1; + output_surface_height = FFMAX(output_surface_height, vo_dheight); + } + // Creation of output_surfaces + for (i = 0; i <= NUM_OUTPUT_SURFACES; i++) { + if (output_surfaces[i] != VDP_INVALID_HANDLE) + vdp_output_surface_destroy(output_surfaces[i]); + vdp_st = vdp_output_surface_create(vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, + output_surface_width, output_surface_height, + &output_surfaces[i]); + CHECK_ST_WARNING("Error when calling vdp_output_surface_create") + MSG_DBG2("OUT CREATE: %u\n", output_surfaces[i]); + } + } + if (image_format == IMGFMT_BGRA) { + vdp_st = vdp_output_surface_render_output_surface(output_surfaces[surface_num], + NULL, VDP_INVALID_HANDLE, + NULL, NULL, NULL, + VDP_OUTPUT_SURFACE_RENDER_ROTATE_0); + CHECK_ST_WARNING("Error when calling vdp_output_surface_render_output_surface") + vdp_st = vdp_output_surface_render_output_surface(output_surfaces[1 - surface_num], + NULL, VDP_INVALID_HANDLE, + NULL, NULL, NULL, + VDP_OUTPUT_SURFACE_RENDER_ROTATE_0); + CHECK_ST_WARNING("Error when calling vdp_output_surface_render_output_surface") + } else + video_to_output_surface(); + if (visible_buf) + flip_page(0); +} + +static void preemption_callback(VdpDevice device, void *context) +{ + MSG_ERR("[vdpau] Display preemption detected\n"); + is_preempted = 1; +} + +/* Initialize vdp_get_proc_address, called from preinit() */ +static int win_x11_init_vdpau_procs(void) +{ + VdpStatus vdp_st; + + struct vdp_function { + const int id; + void *pointer; + }; + + const struct vdp_function *dsc; + + static const struct vdp_function vdp_func[] = { + {VDP_FUNC_ID_GET_ERROR_STRING, &vdp_get_error_string}, + {VDP_FUNC_ID_DEVICE_DESTROY, &vdp_device_destroy}, + {VDP_FUNC_ID_VIDEO_SURFACE_CREATE, &vdp_video_surface_create}, + {VDP_FUNC_ID_VIDEO_SURFACE_DESTROY, &vdp_video_surface_destroy}, + {VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR, + &vdp_video_surface_put_bits_y_cb_cr}, + {VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE, + &vdp_output_surface_put_bits_native}, + {VDP_FUNC_ID_OUTPUT_SURFACE_CREATE, &vdp_output_surface_create}, + {VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY, &vdp_output_surface_destroy}, + {VDP_FUNC_ID_VIDEO_MIXER_CREATE, &vdp_video_mixer_create}, + {VDP_FUNC_ID_VIDEO_MIXER_DESTROY, &vdp_video_mixer_destroy}, + {VDP_FUNC_ID_VIDEO_MIXER_RENDER, &vdp_video_mixer_render}, + {VDP_FUNC_ID_VIDEO_MIXER_SET_FEATURE_ENABLES, + &vdp_video_mixer_set_feature_enables}, + {VDP_FUNC_ID_VIDEO_MIXER_SET_ATTRIBUTE_VALUES, + &vdp_video_mixer_set_attribute_values}, + {VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_DESTROY, + &vdp_presentation_queue_target_destroy}, + {VDP_FUNC_ID_PRESENTATION_QUEUE_CREATE, &vdp_presentation_queue_create}, + {VDP_FUNC_ID_PRESENTATION_QUEUE_DESTROY, + &vdp_presentation_queue_destroy}, + {VDP_FUNC_ID_PRESENTATION_QUEUE_DISPLAY, + &vdp_presentation_queue_display}, + {VDP_FUNC_ID_PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE, + &vdp_presentation_queue_block_until_surface_idle}, + {VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11, + &vdp_presentation_queue_target_create_x11}, + {VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE, + &vdp_output_surface_render_output_surface}, + {VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_INDEXED, + &vdp_output_surface_put_bits_indexed}, + {VDP_FUNC_ID_DECODER_CREATE, &vdp_decoder_create}, + {VDP_FUNC_ID_DECODER_RENDER, &vdp_decoder_render}, + {VDP_FUNC_ID_DECODER_DESTROY, &vdp_decoder_destroy}, + {VDP_FUNC_ID_BITMAP_SURFACE_CREATE, &vdp_bitmap_surface_create}, + {VDP_FUNC_ID_BITMAP_SURFACE_DESTROY, &vdp_bitmap_surface_destroy}, + {VDP_FUNC_ID_BITMAP_SURFACE_PUT_BITS_NATIVE, + &vdp_bitmap_surface_putbits_native}, + {VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_BITMAP_SURFACE, + &vdp_output_surface_render_bitmap_surface}, + {VDP_FUNC_ID_GENERATE_CSC_MATRIX, &vdp_generate_csc_matrix}, + {VDP_FUNC_ID_PREEMPTION_CALLBACK_REGISTER, + &vdp_preemption_callback_register}, + {0, NULL} + }; + + vdp_st = vdp_device_create_x11(mDisplay, mScreen, + &vdp_device, &vdp_get_proc_address); + if (vdp_st != VDP_STATUS_OK) { + MSG_ERR("[vdpau] Error when calling vdp_device_create_x11: %i\n", vdp_st); + return -1; + } + + vdp_get_error_string = NULL; + for (dsc = vdp_func; dsc->pointer; dsc++) { + vdp_st = vdp_get_proc_address(vdp_device, dsc->id, dsc->pointer); + if (vdp_st != VDP_STATUS_OK) { + MSG_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) : "?"); + return -1; + } + } + vdp_st = vdp_preemption_callback_register(vdp_device, + preemption_callback, NULL); + CHECK_ST_ERROR("Error when calling vdp_preemption_callback_register") + + return 0; +} + +/* Initialize vdpau_flip_queue, called from config() */ +static int win_x11_init_vdpau_flip_queue(void) +{ + VdpStatus vdp_st; + + vdp_st = vdp_presentation_queue_target_create_x11(vdp_device, vo_window, + &vdp_flip_target); + CHECK_ST_ERROR("Error when calling vdp_presentation_queue_target_create_x11") + + vdp_st = vdp_presentation_queue_create(vdp_device, vdp_flip_target, + &vdp_flip_queue); + CHECK_ST_ERROR("Error when calling vdp_presentation_queue_create") + + return 0; +} + +static int update_csc_matrix(void) +{ + VdpStatus vdp_st; + VdpCSCMatrix matrix; + static const VdpVideoMixerAttribute attributes[] = {VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX}; + const void *attribute_values[] = {&matrix}; + static const VdpColorStandard vdp_colors[] = {0, VDP_COLOR_STANDARD_ITUR_BT_601, VDP_COLOR_STANDARD_ITUR_BT_709, VDP_COLOR_STANDARD_SMPTE_240M}; + static const char * const vdp_names[] = {NULL, "BT.601", "BT.709", "SMPTE-240M"}; + int csp = colorspace; + + if (!csp) + csp = vid_width >= 1280 || vid_height > 576 ? 2 : 1; + + MSG_V("[vdpau] Updating CSC matrix for %s\n", + vdp_names[csp]); + + vdp_st = vdp_generate_csc_matrix(&procamp, vdp_colors[csp], &matrix); + CHECK_ST_WARNING("Error when generating CSC matrix") + + vdp_st = vdp_video_mixer_set_attribute_values(video_mixer, 1, attributes, + attribute_values); + CHECK_ST_WARNING("Error when setting CSC matrix") + return VO_TRUE; +} + +static int create_vdp_mixer(VdpChromaType vdp_chroma_type) +{ +#define VDP_NUM_MIXER_PARAMETER 3 +#define MAX_NUM_FEATURES 6 + int i; + VdpStatus vdp_st; + int feature_count = 0; + VdpVideoMixerFeature features[MAX_NUM_FEATURES]; + VdpBool feature_enables[MAX_NUM_FEATURES]; + static const VdpVideoMixerAttribute denoise_attrib[] = {VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL}; + const void * const denoise_value[] = {&denoise}; + static const VdpVideoMixerAttribute sharpen_attrib[] = {VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL}; + const void * const sharpen_value[] = {&sharpen}; + static const VdpVideoMixerAttribute skip_chroma_attrib[] = {VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE}; + const uint8_t skip_chroma_value = 1; + const void * const skip_chroma_value_ptr[] = {&skip_chroma_value}; + static const VdpVideoMixerParameter parameters[VDP_NUM_MIXER_PARAMETER] = { + VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, + VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, + VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE + }; + const void *const parameter_values[VDP_NUM_MIXER_PARAMETER] = { + &vid_width, + &vid_height, + &vdp_chroma_type + }; + features[feature_count++] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL; + if (deint == 4) + features[feature_count++] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL; + if (pullup) + features[feature_count++] = VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE; + if (denoise) + features[feature_count++] = VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION; + if (sharpen) + features[feature_count++] = VDP_VIDEO_MIXER_FEATURE_SHARPNESS; + if (hqscaling) + features[feature_count++] = VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 + (hqscaling - 1); + + vdp_st = vdp_video_mixer_create(vdp_device, feature_count, features, + VDP_NUM_MIXER_PARAMETER, + parameters, parameter_values, + &video_mixer); + CHECK_ST_ERROR("Error when calling vdp_video_mixer_create") + + for (i = 0; i < feature_count; i++) + feature_enables[i] = VDP_TRUE; + if (deint < 3) + feature_enables[0] = VDP_FALSE; + if (feature_count) + vdp_video_mixer_set_feature_enables(video_mixer, feature_count, features, feature_enables); + if (denoise) + vdp_video_mixer_set_attribute_values(video_mixer, 1, denoise_attrib, denoise_value); + if (sharpen) + vdp_video_mixer_set_attribute_values(video_mixer, 1, sharpen_attrib, sharpen_value); + if (!chroma_deint) + vdp_video_mixer_set_attribute_values(video_mixer, 1, skip_chroma_attrib, skip_chroma_value_ptr); + + update_csc_matrix(); + return 0; +} + +// Free everything specific to a certain video file +static void free_video_specific(void) +{ + int i; + VdpStatus vdp_st; + + if (decoder != VDP_INVALID_HANDLE) + vdp_decoder_destroy(decoder); + decoder = VDP_INVALID_HANDLE; + decoder_max_refs = -1; + + for (i = 0; i < 3; i++) + deint_surfaces[i] = VDP_INVALID_HANDLE; + + for (i = 0; i < 2; i++) + if (deint_mpi[i]) { + deint_mpi[i] = NULL; + } + + for (i = 0; i < MAX_VIDEO_SURFACES; i++) { + if (surface_render[i].surface != VDP_INVALID_HANDLE) { + vdp_st = vdp_video_surface_destroy(surface_render[i].surface); + CHECK_ST_WARNING("Error when calling vdp_video_surface_destroy") + } + surface_render[i].surface = VDP_INVALID_HANDLE; + } + + if (video_mixer != VDP_INVALID_HANDLE) { + vdp_st = vdp_video_mixer_destroy(video_mixer); + CHECK_ST_WARNING("Error when calling vdp_video_mixer_destroy") + } + video_mixer = VDP_INVALID_HANDLE; +} + +static int create_vdp_decoder(uint32_t format, uint32_t width, uint32_t height, + int max_refs) +{ + VdpStatus vdp_st; + VdpDecoderProfile vdp_decoder_profile; + if (decoder != VDP_INVALID_HANDLE) + vdp_decoder_destroy(decoder); + switch (format) { + case IMGFMT_VDPAU_MPEG1: + vdp_decoder_profile = VDP_DECODER_PROFILE_MPEG1; + break; + case IMGFMT_VDPAU_MPEG2: + vdp_decoder_profile = VDP_DECODER_PROFILE_MPEG2_MAIN; + break; + case IMGFMT_VDPAU_H264: + vdp_decoder_profile = VDP_DECODER_PROFILE_H264_HIGH; + MSG_V("[vdpau] Creating H264 hardware decoder for %d reference frames.\n", max_refs); + break; + case IMGFMT_VDPAU_WMV3: + vdp_decoder_profile = VDP_DECODER_PROFILE_VC1_MAIN; + break; + case IMGFMT_VDPAU_VC1: + vdp_decoder_profile = VDP_DECODER_PROFILE_VC1_ADVANCED; + break; + case IMGFMT_VDPAU_MPEG4: + vdp_decoder_profile = VDP_DECODER_PROFILE_MPEG4_PART2_ASP; + break; + default: + goto err_out; + } + vdp_st = vdp_decoder_create(vdp_device, vdp_decoder_profile, + width, height, max_refs, &decoder); + CHECK_ST_WARNING("Failed creating VDPAU decoder"); + if (vdp_st != VDP_STATUS_OK) { +err_out: + decoder = VDP_INVALID_HANDLE; + decoder_max_refs = 0; + return 0; + } + decoder_max_refs = max_refs; + return 1; +} + +static void mark_vdpau_objects_uninitialized(void) +{ + int i; + + decoder = VDP_INVALID_HANDLE; + for (i = 0; i < MAX_VIDEO_SURFACES; i++) + surface_render[i].surface = VDP_INVALID_HANDLE; + for (i = 0; i < 3; i++) { + deint_surfaces[i] = VDP_INVALID_HANDLE; + deint_mpi[i] = NULL; + } + video_mixer = VDP_INVALID_HANDLE; + vdp_flip_queue = VDP_INVALID_HANDLE; + vdp_flip_target = VDP_INVALID_HANDLE; + for (i = 0; i <= NUM_OUTPUT_SURFACES; i++) + output_surfaces[i] = VDP_INVALID_HANDLE; + vdp_device = VDP_INVALID_HANDLE; + output_surface_width = output_surface_height = -1; + visible_buf = 0; +} + +static int handle_preemption(void) +{ + if (!is_preempted) + return 0; + is_preempted = 0; + MSG_INFO("[vdpau] Attempting to recover from preemption.\n"); + mark_vdpau_objects_uninitialized(); + if (win_x11_init_vdpau_procs() < 0 || + win_x11_init_vdpau_flip_queue() < 0 || + create_vdp_mixer(vdp_chroma_type) < 0) { + MSG_ERR("[vdpau] Recovering from preemption failed\n"); + is_preempted = 1; + return -1; + } +// resize(); + MSG_INFO("[vdpau] Recovered from display preemption.\n"); + return 1; +} + +/* + * connect to X server, create and map window, initialize all + * VDPAU objects, create different surfaces etc. + */ +static uint32_t __FASTCALL__ config(uint32_t width, uint32_t height, uint32_t d_width, + uint32_t d_height, uint32_t flags, char *title, + uint32_t format,const vo_tune_info_t *tune) +{ + XSizeHints hint; + XVisualInfo vinfo; + XSetWindowAttributes xswa; + XWindowAttributes attribs; + unsigned long xswamask; + int depth; + +#ifdef CONFIG_XF86VM + int vm = flags & VOFLAG_MODESWITCHING; +#endif + flip = flags & VOFLAG_FLIPPING; + + image_format = format; + vid_width = width; + vid_height = height; + dwidth = d_width; + dheight = d_height; + free_video_specific(); + if (IMGFMT_IS_VDPAU(image_format) + && !create_vdp_decoder(image_format, vid_width, vid_height, 2)) + return -1; + + int_pause = 0; + visible_buf = 0; + +#ifdef CONFIG_GUI + if (use_gui) + guiGetEvent(guiSetShVideo, 0); // the GUI will set up / resize our window + else +#endif + { +#ifdef CONFIG_XF86VM + if (vm) + vo_vm_switch(); + else +#endif + XGetWindowAttributes(mDisplay, DefaultRootWindow(mDisplay), &attribs); + depth = attribs.depth; + if (depth != 15 && depth != 16 && depth != 24 && depth != 32) + depth = 24; + XMatchVisualInfo(mDisplay, mScreen, depth, TrueColor, &vinfo); + + xswa.background_pixel = 0; + xswa.border_pixel = 0; + /* Do not use CWBackPixel: It leads to VDPAU errors after + aspect ratio changes. */ + xswamask = CWBorderPixel; + + aspect_save_screenres(vo_screenwidth,vo_screenheight); + + aspect(&d_width,&d_height,softzoom?A_ZOOM:A_NOZOOM); +#ifdef X11_FULLSCREEN + if( vo_fs ) aspect(&d_width,&d_height,A_ZOOM); +#endif + vo_x11_calcpos(&hint,d_width,d_height,flags); + hint.flags = PPosition | PSize; + vo_window = XCreateWindow(mDisplay, RootWindow(mDisplay,mScreen), + hint.x, hint.y, hint.width, hint.height, + 0, depth,CopyFromParent,vinfo.visual,xswamask,&xswa); +// vo_x11_create_vo_window(&vinfo, vo_dx, vo_dy, d_width, d_height, +// flags, CopyFromParent, "vdpau", title); + XChangeWindowAttributes(mDisplay, vo_window, xswamask, &xswa); + +#ifdef CONFIG_XF86VM + if (vm) { + /* Grab the mouse pointer in our window */ + if (vo_grabpointer) + XGrabPointer(mDisplay, vo_window, True, 0, + GrabModeAsync, GrabModeAsync, + vo_window, None, CurrentTime); + XSetInputFocus(mDisplay, vo_window, RevertToNone, CurrentTime); + } +#endif + } + + if ((flags & VOFLAG_FULLSCREEN) && WinID <= 0) + vo_fs = 1; + + /* -----VDPAU related code here -------- */ + if (vdp_flip_queue == VDP_INVALID_HANDLE && win_x11_init_vdpau_flip_queue()) + return -1; + + vdp_chroma_type = VDP_CHROMA_TYPE_420; + switch (image_format) { + case IMGFMT_YV12: + case IMGFMT_I420: + case IMGFMT_IYUV: + vdp_pixel_format = VDP_YCBCR_FORMAT_YV12; + break; + case IMGFMT_NV12: + vdp_pixel_format = VDP_YCBCR_FORMAT_NV12; + break; + case IMGFMT_YUY2: + vdp_pixel_format = VDP_YCBCR_FORMAT_YUYV; + vdp_chroma_type = VDP_CHROMA_TYPE_422; + break; + case IMGFMT_UYVY: + vdp_pixel_format = VDP_YCBCR_FORMAT_UYVY; + vdp_chroma_type = VDP_CHROMA_TYPE_422; + } + if (create_vdp_mixer(vdp_chroma_type)) + return -1; + + surface_num = 0; + vid_surface_num = -1; +// resize(); + + return 0; +} + +static uint32_t __FASTCALL__ check_events(int (* __FASTCALL__ adjust_size)(unsigned cw,unsigned ch,unsigned *w,unsigned *h)) +{ + int e = vo_x11_check_events(mDisplay,adjust_size); + + if (handle_preemption() < 0) + return 0; + + if (e & VO_EVENT_RESIZE) + resize(vo_dwidth,vo_dheight); + + if ((e & VO_EVENT_EXPOSE || e & VO_EVENT_RESIZE) && int_pause) { + /* did we already draw a buffer */ + if (visible_buf) { + /* redraw the last visible buffer */ + VdpStatus vdp_st; + vdp_st = vdp_presentation_queue_display(vdp_flip_queue, + output_surfaces[surface_num], + vo_dwidth, vo_dheight, + 0); + CHECK_ST_WARNING("Error when calling vdp_presentation_queue_display") + } + } + return e; +} + +static void draw_osd_I8A8(int x0,int y0, int w,int h, const unsigned char *src, + const unsigned char *srca, int stride, unsigned char* dstbase,int dststride) +{ + VdpOutputSurface output_surface = output_surfaces[surface_num]; + VdpStatus vdp_st; + int i, j; + int pitch; + int index_data_size_required; + VdpRect output_indexed_rect_vid; + VdpOutputSurfaceRenderBlendState blend_state; + + if (!w || !h) + return; + + index_data_size_required = 2*w*h; + if (index_data_size < index_data_size_required) { + index_data = realloc(index_data, index_data_size_required); + index_data_size = index_data_size_required; + } + + // index_data creation, component order - I, A, I, A, ..... + for (i = 0; i < h; i++) + for (j = 0; j < w; j++) { + index_data[i*2*w + j*2] = src [i*stride + j]; + index_data[i*2*w + j*2 + 1] = -srca[i*stride + j]; + } + + output_indexed_rect_vid.x0 = x0; + output_indexed_rect_vid.y0 = y0; + output_indexed_rect_vid.x1 = x0 + w; + output_indexed_rect_vid.y1 = y0 + h; + + pitch = w*2; + + // write source_data to osd_surface. + vdp_st = vdp_output_surface_put_bits_indexed(osd_surface, + VDP_INDEXED_FORMAT_I8A8, + (const void *const*)&index_data, + &pitch, + &output_indexed_rect_vid, + VDP_COLOR_TABLE_FORMAT_B8G8R8X8, + (void *)palette); + CHECK_ST_WARNING("Error when calling vdp_output_surface_put_bits_indexed") + + blend_state.struct_version = VDP_OUTPUT_SURFACE_RENDER_BLEND_STATE_VERSION; + blend_state.blend_factor_source_color = VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE; + blend_state.blend_factor_source_alpha = VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE; + blend_state.blend_factor_destination_color = VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + blend_state.blend_factor_destination_alpha = VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + blend_state.blend_equation_color = VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD; + blend_state.blend_equation_alpha = VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD; + + vdp_st = vdp_output_surface_render_output_surface(output_surface, + &output_indexed_rect_vid, + osd_surface, + &output_indexed_rect_vid, + NULL, + &blend_state, + VDP_OUTPUT_SURFACE_RENDER_ROTATE_0); + CHECK_ST_WARNING("Error when calling vdp_output_surface_render_output_surface") +} + +static void draw_osd(void) +{ + MSG_DBG2("DRAW_OSD\n"); + + if (handle_preemption() < 0) + return; + + vo_draw_text(vo_dwidth, vo_dheight, draw_osd_I8A8); +} + +static void flip_page(unsigned idx) +{ + VdpStatus vdp_st; + MSG_DBG2("\nFLIP_PAGE VID:%u -> OUT:%u\n", + surface_render[vid_surface_num].surface, output_surfaces[surface_num]); + + if (handle_preemption() < 0) + return; + + vdp_st = vdp_presentation_queue_display(vdp_flip_queue, output_surfaces[surface_num], + vo_dwidth, vo_dheight, + 0); + CHECK_ST_WARNING("Error when calling vdp_presentation_queue_display") + + surface_num = (surface_num + 1) % NUM_OUTPUT_SURFACES; + visible_buf = 1; +} + +static int draw_slice(uint8_t *image[], int stride[], int w, int h, + int x, int y) +{ + VdpStatus vdp_st; + struct vdpau_render_state *rndr = (struct vdpau_render_state *)image[0]; + int max_refs = image_format == IMGFMT_VDPAU_H264 ? rndr->info.h264.num_ref_frames : 2; + + if (handle_preemption() < 0) + return VO_TRUE; + + if (!IMGFMT_IS_VDPAU(image_format)) + return VO_FALSE; + if ((decoder == VDP_INVALID_HANDLE || decoder_max_refs < max_refs) + && !create_vdp_decoder(image_format, vid_width, vid_height, max_refs)) + return VO_FALSE; + + vdp_st = vdp_decoder_render(decoder, rndr->surface, (void *)&rndr->info, rndr->bitstream_buffers_used, rndr->bitstream_buffers); + CHECK_ST_WARNING("Failed VDPAU decoder rendering"); + return VO_TRUE; +} + + +static int draw_frame(uint8_t *src[]) +{ + return VO_ERROR; +} + +static struct vdpau_render_state *get_surface(int number) +{ + if (number > MAX_VIDEO_SURFACES) + return NULL; + if (surface_render[number].surface == VDP_INVALID_HANDLE) { + VdpStatus vdp_st; + vdp_st = vdp_video_surface_create(vdp_device, vdp_chroma_type, + vid_width, vid_height, + &surface_render[number].surface); + CHECK_ST_WARNING("Error when calling vdp_video_surface_create") + if (vdp_st != VDP_STATUS_OK) + return NULL; + } + MSG_DBG2("VID CREATE: %u\n", surface_render[number].surface); + return &surface_render[number]; +} + +static uint32_t draw_image(mp_image_t *mpi) +{ + if (IMGFMT_IS_VDPAU(image_format)) { + struct vdpau_render_state *rndr = mpi->priv; + vid_surface_num = rndr - surface_render; + if (deint_buffer_past_frames) { + deint_mpi[1] = deint_mpi[0]; + deint_mpi[0] = mpi; + } + } else if (image_format == IMGFMT_BGRA) { + VdpStatus vdp_st; + VdpRect r = {0, 0, vid_width, vid_height}; + vdp_st = vdp_output_surface_put_bits_native(output_surfaces[2], + (void const*const*)mpi->planes, + mpi->stride, &r); + CHECK_ST_ERROR("Error when calling vdp_output_surface_put_bits_native") + vdp_st = vdp_output_surface_render_output_surface(output_surfaces[surface_num], + &out_rect_vid, + output_surfaces[2], + &src_rect_vid, NULL, NULL, + VDP_OUTPUT_SURFACE_RENDER_ROTATE_0); + CHECK_ST_ERROR("Error when calling vdp_output_surface_render_output_surface") + } else if (!(mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)) { + VdpStatus vdp_st; + void *destdata[3] = {mpi->planes[0], mpi->planes[2], mpi->planes[1]}; + struct vdpau_render_state *rndr = get_surface(deint_counter); + deint_counter = (deint_counter + 1) % 3; + vid_surface_num = rndr - surface_render; + if (image_format == IMGFMT_NV12) + destdata[1] = destdata[2]; + vdp_st = vdp_video_surface_put_bits_y_cb_cr(rndr->surface, + vdp_pixel_format, + (const void *const*)destdata, + mpi->stride); // pitch + CHECK_ST_ERROR("Error when calling vdp_video_surface_put_bits_y_cb_cr") + } + if (mpi->fields & MP_IMGFIELD_ORDERED) + top_field_first = !!(mpi->fields & MP_IMGFIELD_TOP_FIRST); + else + top_field_first = 1; + + video_to_output_surface(); + return VO_TRUE; +} + +static uint32_t get_image(mp_image_t *mpi) +{ + struct vdpau_render_state *rndr; + + // no dr for non-decoding for now + if (!IMGFMT_IS_VDPAU(image_format)) + return VO_FALSE; +// if (mpi->type != MP_IMGTYPE_NUMBERED) +// return VO_FALSE; + + rndr = get_surface(0/*mpi->number*/); + if (!rndr) { + MSG_ERR("[vdpau] no surfaces available in get_image\n"); + // TODO: this probably breaks things forever, provide a dummy buffer? + return VO_FALSE; + } + mpi->flags |= MP_IMGFLAG_DIRECT; + mpi->stride[0] = mpi->stride[1] = mpi->stride[2] = 0; + mpi->planes[0] = mpi->planes[1] = mpi->planes[2] = NULL; + // hack to get around a check and to avoid a special-case in vd_ffmpeg.c + mpi->planes[0] = (void *)rndr; + mpi->num_planes = 1; + mpi->priv = rndr; + return VO_TRUE; +} + +static int query_format(uint32_t format) +{ + int default_flags = VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_OSD | VFCAP_FLIP; + switch (format) { + case IMGFMT_BGRA: + if (force_mixer) + return 0; + case IMGFMT_YV12: + case IMGFMT_I420: + case IMGFMT_IYUV: + case IMGFMT_NV12: + case IMGFMT_YUY2: + case IMGFMT_UYVY: + return default_flags/* | VOCAP_NOSLICES*/; + case IMGFMT_VDPAU_MPEG1: + case IMGFMT_VDPAU_MPEG2: + case IMGFMT_VDPAU_H264: + case IMGFMT_VDPAU_WMV3: + case IMGFMT_VDPAU_VC1: + case IMGFMT_VDPAU_MPEG4: + if (create_vdp_decoder(format, 48, 48, 2)) + return default_flags; + } + return 0; +} + +static void DestroyVdpauObjects(void) +{ + int i; + VdpStatus vdp_st; + + free_video_specific(); + + vdp_st = vdp_presentation_queue_destroy(vdp_flip_queue); + CHECK_ST_WARNING("Error when calling vdp_presentation_queue_destroy") + + vdp_st = vdp_presentation_queue_target_destroy(vdp_flip_target); + CHECK_ST_WARNING("Error when calling vdp_presentation_queue_target_destroy") + + for (i = 0; i <= NUM_OUTPUT_SURFACES; i++) { + vdp_st = vdp_output_surface_destroy(output_surfaces[i]); + output_surfaces[i] = VDP_INVALID_HANDLE; + CHECK_ST_WARNING("Error when calling vdp_output_surface_destroy") + } + + vdp_st = vdp_device_destroy(vdp_device); + CHECK_ST_WARNING("Error when calling vdp_device_destroy") +} + +static void uninit(void) +{ + int i; + +// if (!vo_config_count) +// return; + visible_buf = 0; + + for (i = 0; i < MAX_VIDEO_SURFACES; i++) { + // Allocated in ff_vdpau_add_data_chunk() + free(surface_render[i].bitstream_buffers); + surface_render[i].bitstream_buffers_allocated = 0; + } + + /* Destroy all vdpau objects */ + DestroyVdpauObjects(); + + free(index_data); + index_data = NULL; + +#ifdef CONFIG_XF86VM + vo_vm_close(); +#endif + vo_x11_uninit(mDisplay,vo_window); +} + +static const opt_t subopts[] = { + {"deint", OPT_ARG_INT, &deint, (opt_test_f)int_non_neg}, + {"chroma-deint", OPT_ARG_BOOL, &chroma_deint, NULL}, + {"pullup", OPT_ARG_BOOL, &pullup, NULL}, + {"denoise", OPT_ARG_FLOAT, &denoise, NULL}, + {"sharpen", OPT_ARG_FLOAT, &sharpen, NULL}, + {"colorspace", OPT_ARG_INT, &colorspace, NULL}, + {"force-mixer", OPT_ARG_BOOL, &force_mixer, NULL}, + {"hqscaling", OPT_ARG_INT, &hqscaling, (opt_test_f)int_non_neg}, + {NULL} +}; + +static const char help_msg[] = + "\n-vo vdpau command line help:\n" + "Example: mplayer -vo vdpau:deint=2\n" + "\nOptions:\n" + " deint (all modes > 0 respect -field-dominance)\n" + " 0: no deinterlacing\n" + " 1: only show first field\n" + " 2: bob deinterlacing\n" + " 3: temporal deinterlacing (resource-hungry)\n" + " 4: temporal-spatial deinterlacing (very resource-hungry)\n" + " chroma-deint\n" + " Operate on luma and chroma when using temporal deinterlacing (default)\n" + " Use nochroma-deint to speed up temporal deinterlacing\n" + " pullup\n" + " Try to apply inverse-telecine (needs temporal deinterlacing)\n" + " denoise\n" + " Apply denoising, argument is strength from 0.0 to 1.0\n" + " sharpen\n" + " Apply sharpening or softening, argument is strength from -1.0 to 1.0\n" + " colorspace\n" + " 0: guess based on video resolution\n" + " 1: ITU-R BT.601 (default)\n" + " 2: ITU-R BT.709\n" + " 3: SMPTE-240M\n" + " hqscaling\n" + " 0: default VDPAU scaler\n" + " 1-9: high quality VDPAU scaler (needs capable hardware)\n" + " force-mixer\n" + " Use the VDPAU mixer (default)\n" + " Use noforce-mixer to allow BGRA output (disables all above options)\n" + ; + +static uint32_t __FASTCALL__ preinit(const char *arg) +{ + int i; + + deint = 0; + deint_type = 3; + deint_counter = 0; + deint_buffer_past_frames = 0; + deint_mpi[0] = deint_mpi[1] = NULL; + chroma_deint = 1; + pullup = 0; + denoise = 0; + sharpen = 0; + colorspace = 1; + force_mixer = 1; + hqscaling = 0; + if (subopt_parse(arg, subopts) != 0) { + MSG_FATAL(help_msg); + return -1; + } + if (deint) + deint_type = deint; + if (deint > 1) + deint_buffer_past_frames = 1; + if (colorspace < 0 || colorspace > 3) { + MSG_WARN("[vdpau] Invalid color space specified, " + "using BT.601\n"); + colorspace = 1; + } + + if (!vo_init(arg) || win_x11_init_vdpau_procs()) + return -1; + + decoder = VDP_INVALID_HANDLE; + for (i = 0; i < MAX_VIDEO_SURFACES; i++) + surface_render[i].surface = VDP_INVALID_HANDLE; + video_mixer = VDP_INVALID_HANDLE; + for (i = 0; i <= NUM_OUTPUT_SURFACES; i++) + output_surfaces[i] = VDP_INVALID_HANDLE; + vdp_flip_queue = VDP_INVALID_HANDLE; + output_surface_width = output_surface_height = -1; + + // full grayscale palette. + for (i = 0; i < PALETTE_SIZE; ++i) + palette[i] = (i << 16) | (i << 8) | i; + index_data = NULL; + index_data_size = 0; + + procamp.struct_version = VDP_PROCAMP_VERSION; + procamp.brightness = 0.0; + procamp.contrast = 1.0; + procamp.saturation = 1.0; + procamp.hue = 0.0; + + return 0; +} + +static int get_equalizer(char *name, int *value) +{ + if (!strcasecmp(name, "brightness")) + *value = procamp.brightness * 100; + else if (!strcasecmp(name, "contrast")) + *value = (procamp.contrast-1.0) * 100; + else if (!strcasecmp(name, "saturation")) + *value = (procamp.saturation-1.0) * 100; + else if (!strcasecmp(name, "hue")) + *value = procamp.hue * 100 / M_PI; + else + return VO_NOTIMPL; + return VO_TRUE; +} + +static int set_equalizer(char *name, int value) +{ + if (!strcasecmp(name, "brightness")) + procamp.brightness = value / 100.0; + else if (!strcasecmp(name, "contrast")) + procamp.contrast = value / 100.0 + 1.0; + else if (!strcasecmp(name, "saturation")) + procamp.saturation = value / 100.0 + 1.0; + else if (!strcasecmp(name, "hue")) + procamp.hue = value / 100.0 * M_PI; + else + return VO_NOTIMPL; + + return update_csc_matrix(); +} + +static uint32_t control(uint32_t request, void *data) +{ + if (handle_preemption() < 0) + return VO_FALSE; + + switch (request) { + case VOCTRL_CHECK_EVENTS: + { + vo_resize_t * vrest = (vo_resize_t *)data; + vrest->event_type = check_events(vrest->adjust_size); + if(enable_xp && (vrest->event_type & VO_EVENT_RESIZE)==VO_EVENT_RESIZE) + LOCK_VDECODING(); /* just for compatibility with other vo */ + return VO_TRUE; + } +#if 0 + case VOCTRL_GET_DEINTERLACE: + *(int*)data = deint; + return VO_TRUE; + case VOCTRL_SET_DEINTERLACE: + if (image_format == IMGFMT_BGRA) + return VO_NOTIMPL; + deint = *(int*)data; + if (deint) + deint = deint_type; + if (deint_type > 2) { + VdpStatus vdp_st; + VdpVideoMixerFeature features[1] = + {deint_type == 3 ? + VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL : + VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL}; + VdpBool feature_enables[1] = {deint ? VDP_TRUE : VDP_FALSE}; + vdp_st = vdp_video_mixer_set_feature_enables(video_mixer, 1, + features, + feature_enables); + CHECK_ST_WARNING("Error changing deinterlacing settings") + deint_buffer_past_frames = 1; + } + return VO_TRUE; +#endif + case VOCTRL_PAUSE: + return int_pause = 1; + case VOCTRL_RESUME: + return int_pause = 0; + case VOCTRL_QUERY_FORMAT: + return query_format(*(uint32_t *)data); +#if 0 + case VOCTRL_GET_IMAGE: + return get_image(data); + case VOCTRL_DRAW_IMAGE: + return draw_image(data); + case VOCTRL_GUISUPPORT: + return VO_TRUE; + case VOCTRL_BORDER: + vo_x11_border(); + resize(); + return VO_TRUE; +#endif + case VOCTRL_FULLSCREEN: + vo_x11_fullscreen(); + resize(vo_dwidth, vo_dheight); + return VO_TRUE; +#if 0 + case VOCTRL_GET_PANSCAN: + return VO_TRUE; + case VOCTRL_SET_PANSCAN: + resize(); + return VO_TRUE; +#endif + case VOCTRL_SET_EQUALIZER: { + int value=*(int *)data; + if (image_format == IMGFMT_BGRA) + return VO_NOTIMPL; + return set_equalizer(data, value); + } + case VOCTRL_GET_EQUALIZER: { + int *value = (int *)data; + return get_equalizer(data, value); + } +#if 0 + case VOCTRL_ONTOP: + vo_x11_ontop(); + return VO_TRUE; + case VOCTRL_UPDATE_SCREENINFO: + update_xinerama_info(); + return VO_TRUE; + case VOCTRL_DRAW_EOSD: + if (!data) + return VO_FALSE; + generate_eosd(data); + draw_eosd(); + return VO_TRUE; + case VOCTRL_GET_EOSD_RES: { + mp_eosd_res_t *r = data; + r->mt = r->mb = r->ml = r->mr = 0; + if (vo_fs) { + r->w = vo_screenwidth; + r->h = vo_screenheight; + r->ml = r->mr = border_x; + r->mt = r->mb = border_y; + } else { + r->w = vo_dwidth; + r->h = vo_dheight; + } + return VO_TRUE; + } +#endif + } + return VO_NOTIMPL; +} + +/* @} */ Property changes on: mplayerxp/libvo/vo_vdpau.c ___________________________________________________________________ Added: svn:eol-style + native Added: mplayerxp/subopt-helper.c =================================================================== --- mplayerxp/subopt-helper.c (rev 0) +++ mplayerxp/subopt-helper.c 2009-12-16 15:56:00 UTC (rev 43) @@ -0,0 +1,335 @@ +/** + * \file subopt-helper.c + * + * \brief Compensates the suboption parsing code duplication a bit. + * + * The routines defined below are there to help you with the + * suboption parsing. Meaning extracting the options and their + * values for you and also outputting generic help message if + * a parse error is encountered. + * + * Most stuff happens in the subopt_parse function: if you call it + * it parses for the passed opts in the passed string. It calls some + * extra functions for explicit argument parsing ( where the option + * itself isn't the argument but a value given after the argument + * delimiter ('='). It also calls your test function if you supplied + * one. + * + */ +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include <assert.h> + +#include "subopt-helper.h" +#define MSGT_CLASS MSGT_GLOBAL +#include "__mp_msg.h" + + +#ifndef MPDEBUG + #defin... [truncated message content] |