comparison libvo/vo_xvmc.c @ 10698:7ab88b24cb81

OSD support, optinal queue, optional use of sleep(), and benchmark mode
author iive
date Mon, 25 Aug 2003 21:41:10 +0000
parents 2cae82f2ab02
children 240e212130d3
comparison
equal deleted inserted replaced
10697:f0cddd635519 10698:7ab88b24cb81
1 #include <stdlib.h> 1 #include <stdlib.h>
2 #include <stdio.h> 2 #include <stdio.h>
3 #include <string.h> 3 #include <string.h>
4 4 #include <unistd.h>
5 #include <X11/Xlib.h>
6 #include <X11/Xutil.h>
7 #include <X11/Xatom.h>
8 #include <X11/extensions/Xv.h>
9 #include <X11/extensions/Xvlib.h>
10 #include <X11/extensions/XvMClib.h>
11 5
12 #include "config.h" 6 #include "config.h"
13 #include "mp_msg.h" 7 #include "mp_msg.h"
14 #include "video_out.h" 8 #include "video_out.h"
15 #include "video_out_internal.h" 9 #include "video_out_internal.h"
16 #include "fastmemcpy.h" 10 #include "fastmemcpy.h"
11 #include "osdep/timer.h"
12
13 #include <X11/Xlib.h>
14 #include <X11/Xutil.h>
15 #include <X11/Xatom.h>
16
17 #ifdef HAVE_SHM
18 #include <sys/ipc.h>
19 #include <sys/shm.h>
20 #include <X11/extensions/XShm.h>
21 #endif
22
23 #include <X11/extensions/Xv.h>
24 #include <X11/extensions/Xvlib.h>
25 #include <X11/extensions/XvMClib.h>
17 26
18 #include "x11_common.h" 27 #include "x11_common.h"
19 #include "xvmc_render.h" 28 #include "xvmc_render.h"
20 29
21 #include "sub.h" 30 #include "sub.h"
23 32
24 #ifdef HAVE_NEW_GUI 33 #ifdef HAVE_NEW_GUI
25 #include "../Gui/interface.h" 34 #include "../Gui/interface.h"
26 #endif 35 #endif
27 36
37 //no chanse xinerama to be suported in near future
28 #undef HAVE_XINERAMA 38 #undef HAVE_XINERAMA
29 39
30 #undef NDEBUG 40 #undef NDEBUG
31 #include <assert.h> 41 #include <assert.h>
32 42
33 //no chanse xinerama to be suported in near future
34 43
35 #define UNUSED(x) ((void)(x)) 44 #define UNUSED(x) ((void)(x))
36 45
37 46
38 extern int vo_directrendering; 47 extern int vo_directrendering;
39 extern int vo_verbose; 48 extern int vo_verbose;
40 49
41 static void xvmc_free(void); 50 static int benchmark;
51 static int busy_wait;
52 static int use_queue;
42 53
43 static int image_width,image_height; 54 static int image_width,image_height;
44 static uint32_t drwX,drwY; 55 static uint32_t drwX,drwY;
45 56
46 static XvPortID xv_port; 57 static XvPortID xv_port;
47 58
48 //0-auto;1-backgound always keycolor;2-autopaint(by X);3-manual fill 59 #define AUTO_COLORKEY 0
60 #define BACKGROUND_COLORKEY 1
61 #define AUTOPAINT_COLORKEY 2
62 #define MANUALFILL_COLORKEY 3
49 static int keycolor_handling; 63 static int keycolor_handling;
50 static unsigned long keycolor; 64 static unsigned long keycolor;
65
66 #define NO_SUBPICTURE 0
67 #define OVERLAY_SUBPICTURE 1
68 #define BLEND_SUBPICTURE 2
69 #define BACKEND_SUBPICTURE 3
70
71 static int subpicture_mode;
72 static int subpicture_alloc;
73 static XvMCSubpicture subpicture;
74 static XvImageFormatValues subpicture_info;
75 static int subpicture_clear_color;//transparent color for the subpicture or color key for overlay
51 76
52 static XvMCSurfaceInfo surface_info; 77 static XvMCSurfaceInfo surface_info;
53 static XvMCContext ctx; 78 static XvMCContext ctx;
54 static XvMCBlockArray data_blocks; 79 static XvMCBlockArray data_blocks;
55 static XvMCMacroBlockArray mv_blocks; 80 static XvMCMacroBlockArray mv_blocks;
59 static XvMCSurface surface_array[MAX_SURFACES]; 84 static XvMCSurface surface_array[MAX_SURFACES];
60 static xvmc_render_state_t * surface_render; 85 static xvmc_render_state_t * surface_render;
61 86
62 static xvmc_render_state_t * p_render_surface_to_show=NULL; 87 static xvmc_render_state_t * p_render_surface_to_show=NULL;
63 static xvmc_render_state_t * p_render_surface_visible=NULL; 88 static xvmc_render_state_t * p_render_surface_visible=NULL;
89
90 //display queue, kinda render ahead
91 static xvmc_render_state_t * show_queue[MAX_SURFACES];
92 static int free_element;
93
94
95 static void (*draw_osd_fnc)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride);
96 static void (*clear_osd_fnc)(int x0,int y0, int w,int h);
97 static void (*init_osd_fnc)(void);
98
99 static void draw_osd_AI44(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride);
100 static void draw_osd_IA44(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride);
101 static void clear_osd_subpic(int x0,int y0, int w,int h);
102 static void init_osd_yuv_pal(void);
103
104
105 static const struct{
106 int id;//id as xvimages or as mplayer RGB|{8,15,16,24,32}
107 void (* init_func_ptr)();
108 void (* draw_func_ptr)();
109 void (* clear_func_ptr)();
110 } osd_render[]={
111 {0x34344149,init_osd_yuv_pal,draw_osd_AI44,clear_osd_subpic},
112 {0x34344941,init_osd_yuv_pal,draw_osd_IA44,clear_osd_subpic},
113 {0,NULL,NULL,NULL}
114 };
115
116 static void xvmc_free(void);
117 static int count_free_surfaces();
118 static xvmc_render_state_t * find_free_surface();
64 119
65 static vo_info_t info = { 120 static vo_info_t info = {
66 "XVideo Motion Compensation", 121 "XVideo Motion Compensation",
67 "xvmc", 122 "xvmc",
68 "Ivan Kalvachev <iive@users.sf.net>", 123 "Ivan Kalvachev <iive@users.sf.net>",
69 "" 124 ""
70 }; 125 };
71 126
72 LIBVO_EXTERN(xvmc); 127 LIBVO_EXTERN(xvmc);
73 128
129 //shm stuff from vo_xv
130 #ifdef HAVE_SHM
131 /* since it doesn't seem to be defined on some platforms */
132 int XShmGetEventBase(Display*);
133 static XShmSegmentInfo Shminfo;
134 static int Shmem_Flag;
135 #endif
136 XvImage * xvimage;
137
138
139 static void allocate_xvimage(int xvimage_width,int xvimage_height,int xv_format)
140 {
141 /*
142 * allocate XvImages. FIXME: no error checking, without
143 * mit-shm this will bomb... trzing to fix ::atmos
144 */
145 #ifdef HAVE_SHM
146 if ( mLocalDisplay && XShmQueryExtension( mDisplay ) ) Shmem_Flag = 1;
147 else
148 {
149 Shmem_Flag = 0;
150 mp_msg(MSGT_VO,MSGL_INFO, "Shared memory not supported\nReverting to normal Xv\n" );
151 }
152 if ( Shmem_Flag )
153 {
154 xvimage = (XvImage *) XvShmCreateImage(mDisplay, xv_port, xv_format,
155 NULL, xvimage_width, xvimage_height, &Shminfo);
156
157 Shminfo.shmid = shmget(IPC_PRIVATE, xvimage->data_size, IPC_CREAT | 0777);
158 Shminfo.shmaddr = (char *) shmat(Shminfo.shmid, 0, 0);
159 Shminfo.readOnly = False;
160
161 xvimage->data = Shminfo.shmaddr;
162 XShmAttach(mDisplay, &Shminfo);
163 XSync(mDisplay, False);
164 shmctl(Shminfo.shmid, IPC_RMID, 0);
165 }
166 else
167 #endif
168 {
169 xvimage = (XvImage *) XvCreateImage(mDisplay, xv_port, xv_format, NULL, xvimage_width, xvimage_height);
170 xvimage->data = malloc(xvimage->data_size);
171 XSync(mDisplay,False);
172 }
173 // memset(xvimage->data,128,xvimage->data_size);
174 return;
175 }
176
177 static void deallocate_xvimage()
178 {
179 #ifdef HAVE_SHM
180 if ( Shmem_Flag )
181 {
182 XShmDetach( mDisplay,&Shminfo );
183 shmdt( Shminfo.shmaddr );
184 }
185 else
186 #endif
187 {
188 free(xvimage->data);
189 }
190 XFree(xvimage);
191
192 XFlush( mDisplay );
193 XSync(mDisplay, False);
194 return;
195 }
196 //end of vo_xv shm/xvimage code
197
198
74 static void init_keycolor(){ 199 static void init_keycolor(){
75 Atom xv_atom; 200 Atom xv_atom;
76 XvAttribute * attributes; 201 XvAttribute * attributes;
77 int colorkey; 202 int colorkey;
78 int rez; 203 int rez;
79 int attrib_count,i; 204 int attrib_count,i;
80 205
81 keycolor=2110; 206 keycolor=2110;
82 207
83 if(keycolor_handling == 0){ 208 if(keycolor_handling == AUTO_COLORKEY){
84 //XV_AUTOPING_COLORKEY doesn't work for XvMC yet(NVidia 43.63) 209 //XV_AUTOPING_COLORKEY doesn't work for XvMC yet(NVidia 43.63)
85 attributes = XvQueryPortAttributes(mDisplay, xv_port, &attrib_count); 210 attributes = XvQueryPortAttributes(mDisplay, xv_port, &attrib_count);
86 if(attributes!=NULL) 211 if(attributes!=NULL)
87 for (i = 0; i < attrib_count; i++) 212 for (i = 0; i < attrib_count; i++)
88 if (!strcmp(attributes[i].name, "XV_AUTOPAINT_COLORKEY")) 213 if (!strcmp(attributes[i].name, "XV_AUTOPAINT_COLORKEY"))
89 { 214 {
90 xv_atom = XInternAtom(mDisplay, "XV_AUTOPAINT_COLORKEY", False); 215 xv_atom = XInternAtom(mDisplay, "XV_AUTOPAINT_COLORKEY", False);
91 if(xv_atom!=None) 216 if(xv_atom!=None)
92 { 217 {
93 rez=XvSetPortAttribute(mDisplay, xv_port, xv_atom, 1); 218 rez=XvSetPortAttribute(mDisplay, xv_port, xv_atom, 1);
94 if(rez == Success) 219 if(rez == Success)
95 keycolor_handling = 2;//this is the way vo_xv works 220 keycolor_handling = AUTOPAINT_COLORKEY;
96 } 221 }
97 break; 222 break;
98 } 223 }
99 XFree(attributes); 224 XFree(attributes);
100 } 225 }
101 226
102 xv_atom = XInternAtom(mDisplay, "XV_COLORKEY",False); 227 xv_atom = XInternAtom(mDisplay, "XV_COLORKEY",False);
103 if(xv_atom == None) return; 228 if(xv_atom == None) return;
104 rez=XvGetPortAttribute(mDisplay,xv_port, xv_atom, &colorkey); 229 rez=XvGetPortAttribute(mDisplay,xv_port, xv_atom, &colorkey);
105 if(rez == Success){ 230 if(rez == Success){
106 keycolor=colorkey; 231 keycolor = colorkey;
107 if(keycolor_handling == 0){ 232 if(keycolor_handling == AUTO_COLORKEY){
108 keycolor_handling = 3; 233 keycolor_handling = MANUALFILL_COLORKEY;
109 } 234 }
110 } 235 }
111 } 236 }
112 237
113 //from vo_xmga 238 //from vo_xmga
114 static void mDrawColorKey(uint32_t x,uint32_t y, uint32_t w, uint32_t h) 239 static void mDrawColorKey(uint32_t x,uint32_t y, uint32_t w, uint32_t h)
115 { 240 {
116 if( (keycolor_handling != 2) && (keycolor_handling != 3) ) 241 if( (keycolor_handling != AUTOPAINT_COLORKEY) &&
117 return ;//unknown method 242 (keycolor_handling != MANUALFILL_COLORKEY) )
243 return;
118 244
119 XSetBackground( mDisplay,vo_gc,0 ); 245 XSetBackground( mDisplay,vo_gc,0 );
120 XClearWindow( mDisplay,vo_window ); 246 XClearWindow( mDisplay,vo_window );
121 247
122 if(keycolor_handling == 3){ 248 if(keycolor_handling == MANUALFILL_COLORKEY){
123 XSetForeground( mDisplay,vo_gc,keycolor ); 249 XSetForeground( mDisplay,vo_gc,keycolor );
124 XFillRectangle( mDisplay,vo_window,vo_gc,x,y,w,h); 250 XFillRectangle( mDisplay,vo_window,vo_gc,x,y,w,h);
125 } 251 }
126 XFlush( mDisplay ); 252 XFlush( mDisplay );
127 } 253 }
128 254
129 // now it is ugly, but i need it working 255
130 static int xvmc_check_surface_format(uint32_t format, XvMCSurfaceInfo * surf_info){ 256 static int xvmc_check_surface_format(uint32_t format, XvMCSurfaceInfo * surf_info){
131 if ( format == IMGFMT_XVMC_IDCT_MPEG2 ){ 257 if ( format == IMGFMT_XVMC_IDCT_MPEG2 ){
132 if( surf_info->mc_type != (XVMC_IDCT|XVMC_MPEG_2) ) return -1; 258 if( surf_info->mc_type != (XVMC_IDCT|XVMC_MPEG_2) ) return -1;
133 if( surf_info->chroma_format != XVMC_CHROMA_FORMAT_420 ) return -1; 259 if( surf_info->chroma_format != XVMC_CHROMA_FORMAT_420 ) return -1;
134 return 0; 260 return 0;
139 return 0; 265 return 0;
140 } 266 }
141 return -1;//fail 267 return -1;//fail
142 } 268 }
143 269
270 //print all info needed to add new format
271 static void print_xvimage_format_values(XvImageFormatValues *xifv){
272 int i;
273 printf("Format_ID = 0x%X\n",xifv->id);
274
275 printf(" type = ");
276 if(xifv->type == XvRGB) printf("RGB\n");
277 else if(xifv->type == XvYUV) printf("YUV\n");
278 else printf("Unknown\n");
279
280 printf(" byte_order = ");
281 if(xifv->byte_order == LSBFirst) printf("LSB First\n");
282 else if(xifv->type == MSBFirst) printf("MSB First\n");
283 else printf("Unknown\n");//yes Linux support other types too
284
285 printf(" guid = ");
286 for(i=0;i<16;i++)
287 printf("%02X ",(unsigned char)xifv->guid[i]);
288 printf("\n");
289
290 printf(" bits_per_pixel = %d\n",xifv->bits_per_pixel);
291
292 printf(" format = ");
293 if(xifv->format == XvPacked) printf("XvPacked\n");
294 else if(xifv->format == XvPlanar) printf("XvPlanar\n");
295 else printf("Unknown\n");
296
297 printf(" num_planes = %d\n",xifv->num_planes);
298
299 if(xifv->type == XvRGB){
300 printf(" red_mask = %0X\n", xifv->red_mask);
301 printf(" green_mask = %0X\n",xifv->green_mask);
302 printf(" blue_mask = %0X\n", xifv->blue_mask);
303 }
304 if(xifv->type == XvYUV){
305 printf(" y_sample_bits = %d\n u_sample_bits = %d\n v_sample_bits = %d\n",
306 xifv->y_sample_bits,xifv->u_sample_bits,xifv->v_sample_bits);
307 printf(" horz_y_period = %d\n horz_u_period = %d\n horz_v_period = %d\n",
308 xifv->horz_y_period,xifv->horz_u_period,xifv->horz_v_period);
309 printf(" vert_y_period = %d\n vert_u_period = %d\n vert_v_period = %d\n",
310 xifv->vert_y_period,xifv->vert_u_period,xifv->vert_v_period);
311
312 printf(" component_order = ");
313 for(i=0;i<32;i++)
314 if(xifv->component_order[i]>=32)
315 printf("%c",xifv->component_order[i]);
316 printf("\n");
317
318 printf(" scanline = ");
319 if(xifv->scanline_order == XvTopToBottom) printf("XvTopToBottom\n");
320 else if(xifv->scanline_order == XvBottomToTop) printf("XvBottomToTop\n");
321 else printf("Unknown\n");
322 }
323 printf("\n");
324 }
325
144 // WARNING This function may changes xv_port and surface_info! 326 // WARNING This function may changes xv_port and surface_info!
145 static int xvmc_find_surface_by_format(int format,int width,int height, 327 static int xvmc_find_surface_by_format(int format,int width,int height,
146 XvMCSurfaceInfo * surf_info,int query){ 328 XvMCSurfaceInfo * surf_info,int query){
147 int rez; 329 int rez;
148 XvAdaptorInfo * ai; 330 XvAdaptorInfo * ai;
149 int num_adaptors,i; 331 int num_adaptors,i;
150 unsigned long p; 332 unsigned long p;
151 int s,mc_surf_num; 333 int s,mc_surf_num;
152 XvMCSurfaceInfo * mc_surf_list; 334 XvMCSurfaceInfo * mc_surf_list;
153 335
154 rez = XvQueryAdaptors(mDisplay,DefaultRootWindow(mDisplay),&num_adaptors,&ai); 336 rez = XvQueryAdaptors(mDisplay,DefaultRootWindow(mDisplay),&num_adaptors,&ai);
155 if( rez != Success ) return -1; 337 if( rez != Success ) return -1;
156 if( verbose > 2 ) printf("vo_xvmc: Querying %d adaptors\n",num_adaptors); 338 if( verbose > 2 ) printf("vo_xvmc: Querying %d adaptors\n",num_adaptors);
157 for(i=0; i<num_adaptors; i++) 339 for(i=0; i<num_adaptors; i++)
158 { 340 {
169 } 351 }
170 if( verbose > 2) printf("vo_xvmc: XvMC list have %d surfaces\n",mc_surf_num); 352 if( verbose > 2) printf("vo_xvmc: XvMC list have %d surfaces\n",mc_surf_num);
171 //we have XvMC list! 353 //we have XvMC list!
172 for(s=0; s<mc_surf_num; s++) 354 for(s=0; s<mc_surf_num; s++)
173 { 355 {
174 if( width > mc_surf_list[s].max_width ) continue; 356 if( width > mc_surf_list[s].max_width ) continue;
175 if( height > mc_surf_list[s].max_height ) continue; 357 if( height > mc_surf_list[s].max_height ) continue;
176 if( xvmc_check_surface_format(format,&mc_surf_list[s])<0 ) continue; 358 if( xvmc_check_surface_format(format,&mc_surf_list[s])<0 ) continue;
177 //we have match! 359 //we have match!
178 360
179 if(!query){ 361 if(!query){
180 rez = XvGrabPort(mDisplay,p,CurrentTime); 362 rez = XvGrabPort(mDisplay,p,CurrentTime);
181 if(rez != Success){ 363 if(rez != Success){
182 if (verbose > 2) printf("vo_xvmc: Fail to grab port %ld\n",p); 364 if (verbose > 2) printf("vo_xvmc: Fail to grab port %ld\n",p);
183 continue; 365 continue;
184 } 366 }
185 printf("vo_xvmc: Port %ld grabed\n",p); 367 printf("vo_xvmc: Port %ld grabed\n",p);
188 goto surface_found; 370 goto surface_found;
189 }//for mc surf 371 }//for mc surf
190 XFree(mc_surf_list);//if mc_surf_num==0 is list==NULL ? 372 XFree(mc_surf_list);//if mc_surf_num==0 is list==NULL ?
191 }//for ports 373 }//for ports
192 }//for adaptors 374 }//for adaptors
193 375
194 if(!query) printf("vo_xvmc: Could not find free matching surface. Sorry.\n"); 376 if(!query) printf("vo_xvmc: Could not find free matching surface. Sorry.\n");
195 return 0; 377 return 0;
196 378
197 // somebody know cleaner way to escape from 3 internal loops? 379 // somebody know cleaner way to escape from 3 internal loops?
198 surface_found: 380 surface_found:
208 xvmc_render_state_t * rndr; 390 xvmc_render_state_t * rndr;
209 391
210 assert(mpi!=NULL); 392 assert(mpi!=NULL);
211 assert(mpi->flags &MP_IMGFLAG_DIRECT); 393 assert(mpi->flags &MP_IMGFLAG_DIRECT);
212 // assert(mpi->flags &MP_IMGFLAGS_DRAWBACK); 394 // assert(mpi->flags &MP_IMGFLAGS_DRAWBACK);
213 395
214 rndr = (xvmc_render_state_t*)mpi->priv;//there is copy in plane[2] 396 rndr = (xvmc_render_state_t*)mpi->priv;//there is copy in plane[2]
215 assert( rndr != NULL ); 397 assert( rndr != NULL );
216 assert( rndr->magic == MP_XVMC_RENDER_MAGIC ); 398 assert( rndr->magic == MP_XVMC_RENDER_MAGIC );
217 if( verbose > 3 ) 399 if( verbose > 3 )
218 printf("vo_xvmc: draw_image(show rndr=%p)\n",rndr); 400 printf("vo_xvmc: draw_image(show rndr=%p)\n",rndr);
225 static uint32_t preinit(const char *arg){ 407 static uint32_t preinit(const char *arg){
226 int xv_version,xv_release,xv_request_base,xv_event_base,xv_error_base; 408 int xv_version,xv_release,xv_request_base,xv_event_base,xv_error_base;
227 int mc_eventBase,mc_errorBase; 409 int mc_eventBase,mc_errorBase;
228 int mc_ver,mc_rev; 410 int mc_ver,mc_rev;
229 411
230 //Obtain display handler 412 //Obtain display handler
231 if (!vo_init()) return -1;//vo_xv 413 if (!vo_init()) return -1;//vo_xv
232 414
233 //XvMC is subdivision of XVideo 415 //XvMC is subdivision of XVideo
234 if (Success != XvQueryExtension(mDisplay,&xv_version,&xv_release,&xv_request_base, 416 if (Success != XvQueryExtension(mDisplay,&xv_version,&xv_release,&xv_request_base,
235 &xv_event_base,&xv_error_base) ){ 417 &xv_event_base,&xv_error_base) ){
236 mp_msg(MSGT_VO,MSGL_ERR,"Sorry, Xv(MC) not supported by this X11 version/driver\n"); 418 mp_msg(MSGT_VO,MSGL_ERR,"Sorry, Xv(MC) not supported by this X11 version/driver\n");
237 mp_msg(MSGT_VO,MSGL_ERR,"********** Try with -vo x11 or -vo sdl ***********\n"); 419 mp_msg(MSGT_VO,MSGL_ERR,"********** Try with -vo x11 or -vo sdl ***********\n");
238 return -1; 420 return -1;
239 } 421 }
240 printf("vo_xvmc: X-Video extension %d.%d\n",xv_version,xv_release); 422 printf("vo_xvmc: X-Video extension %d.%d\n",xv_version,xv_release);
241 423
242 if( True != XvMCQueryExtension(mDisplay,&mc_eventBase,&mc_errorBase) ){ 424 if( True != XvMCQueryExtension(mDisplay,&mc_eventBase,&mc_errorBase) ){
243 printf("vo_xvmc: No X-Video MotionCompensation Extension on %s\n", 425 printf("vo_xvmc: No X-Video MotionCompensation Extension on %s\n",
244 XDisplayName(NULL)); 426 XDisplayName(NULL));
245 return -1; 427 return -1;
246 } 428 }
247 429
248 if(Success == XvMCQueryVersion(mDisplay, &mc_ver, &mc_rev) ){ 430 if(Success == XvMCQueryVersion(mDisplay, &mc_ver, &mc_rev) ){
249 printf("vo_xvmc: X-Video MotionCompensation Extension version %i.%i\n", 431 printf("vo_xvmc: X-Video MotionCompensation Extension version %i.%i\n",
250 mc_ver,mc_rev); 432 mc_ver,mc_rev);
251 } 433 }
252 else{ 434 else{
253 printf("vo_xvmc: Error querying version info!\n"); 435 printf("vo_xvmc: Error querying version info!\n");
254 return -1; 436 return -1;
255 } 437 }
438 surface_render = NULL;
256 xv_port = 0; 439 xv_port = 0;
257 number_of_surfaces = 0; 440 number_of_surfaces = 0;
258 keycolor_handling = 3;//!!fixme 441 keycolor_handling = MANUALFILL_COLORKEY;//fixme
259 surface_render=NULL; 442 subpicture_alloc = 0;
260 443
444 benchmark = 0; //disable PutImageto allow faster display than screen refresh
445 busy_wait = 1;
446 use_queue = 0;
447 if(arg)
448 while(*arg){
449 if(strncmp(arg,"benchmark",9) == 0){
450 arg+=9;
451 if(*arg == ':') arg++;
452 benchmark = 1;//disable PutImageto allow faster display than screen refresh
453 continue;
454 }
455 if(strncmp(arg,"wait",4) == 0){
456 arg+=4;
457 if(*arg == ':') arg++;
458 busy_wait = 1;
459 continue;
460 }
461 if(strncmp(arg,"sleep",5) == 0){
462 arg+=5;
463 if(*arg == ':') arg++;
464 busy_wait = 0;
465 continue;
466 }
467 if(strncmp(arg,"queue",5) == 0){
468 arg+=5;
469 if(*arg == ':') arg++;
470 use_queue = 1;
471 continue;
472 }
473 break;
474 }
475
261 return 0; 476 return 0;
262 } 477 }
263 478
264 static uint32_t config(uint32_t width, uint32_t height, 479 static uint32_t config(uint32_t width, uint32_t height,
265 uint32_t d_width, uint32_t d_height, 480 uint32_t d_width, uint32_t d_height,
295 xvmc_free(); 510 xvmc_free();
296 }; 511 };
297 numblocks=((width+15)/16)*((height+15)/16); 512 numblocks=((width+15)/16)*((height+15)/16);
298 // Find Supported Surface Type 513 // Find Supported Surface Type
299 mode_id = xvmc_find_surface_by_format(format,width,height,&surface_info,0);//false=1 to grab port, not query 514 mode_id = xvmc_find_surface_by_format(format,width,height,&surface_info,0);//false=1 to grab port, not query
300 515
301 rez = XvMCCreateContext(mDisplay, xv_port,mode_id,width,height,XVMC_DIRECT,&ctx); 516 rez = XvMCCreateContext(mDisplay, xv_port,mode_id,width,height,XVMC_DIRECT,&ctx);
302 if( rez != Success ) return -1; 517 if( rez != Success ) return -1;
303 if( ctx.flags & XVMC_DIRECT ){ 518 if( ctx.flags & XVMC_DIRECT ){
304 printf("vo_xvmc: Allocated Direct Context\n"); 519 printf("vo_xvmc: Allocated Direct Context\n");
305 }else{ 520 }else{
306 printf("vo_xvmc: Allocated Indirect Context!\n"); 521 printf("vo_xvmc: Allocated Indirect Context!\n");
307 } 522 }
308 523
524
309 blocks_per_macroblock = 6; 525 blocks_per_macroblock = 6;
310 if(surface_info.chroma_format == XVMC_CHROMA_FORMAT_422) 526 if(surface_info.chroma_format == XVMC_CHROMA_FORMAT_422)
311 blocks_per_macroblock = 8; 527 blocks_per_macroblock = 8;
312 if(surface_info.chroma_format == XVMC_CHROMA_FORMAT_444) 528 if(surface_info.chroma_format == XVMC_CHROMA_FORMAT_444)
313 blocks_per_macroblock = 12; 529 blocks_per_macroblock = 12;
314 530
315 rez = XvMCCreateBlocks(mDisplay,&ctx,numblocks*blocks_per_macroblock,&data_blocks); 531 rez = XvMCCreateBlocks(mDisplay,&ctx,numblocks*blocks_per_macroblock,&data_blocks);
316 if( rez != Success ){ 532 if( rez != Success ){
317 XvMCDestroyContext(mDisplay,&ctx); 533 XvMCDestroyContext(mDisplay,&ctx);
327 } 543 }
328 printf("vo_xvmc: mv_blocks allocated\n"); 544 printf("vo_xvmc: mv_blocks allocated\n");
329 545
330 if(surface_render==NULL) 546 if(surface_render==NULL)
331 surface_render=malloc(MAX_SURFACES*sizeof(xvmc_render_state_t));//easy mem debug 547 surface_render=malloc(MAX_SURFACES*sizeof(xvmc_render_state_t));//easy mem debug
332 548
333 for(i=0; i<MAX_SURFACES; i++){ 549 for(i=0; i<MAX_SURFACES; i++){
334 rez=XvMCCreateSurface(mDisplay,&ctx,&surface_array[i]); 550 rez=XvMCCreateSurface(mDisplay,&ctx,&surface_array[i]);
335 if( rez != Success ) 551 if( rez != Success )
336 break; 552 break;
337 memset(&surface_render[i],0,sizeof(xvmc_render_state_t)); 553 memset(&surface_render[i],0,sizeof(xvmc_render_state_t));
360 //debug 576 //debug
361 printf("vo_xvmc: idct=%d unsigned_intra=%d\n", 577 printf("vo_xvmc: idct=%d unsigned_intra=%d\n",
362 (surface_info.mc_type & XVMC_IDCT) == XVMC_IDCT, 578 (surface_info.mc_type & XVMC_IDCT) == XVMC_IDCT,
363 (surface_info.flags & XVMC_INTRA_UNSIGNED) == XVMC_INTRA_UNSIGNED); 579 (surface_info.flags & XVMC_INTRA_UNSIGNED) == XVMC_INTRA_UNSIGNED);
364 580
581 // Find way to display OSD & subtitle
582 printf("vo_xvmc: looking for OSD support\n");
583 subpicture_mode = NO_SUBPICTURE;
584 if(surface_info.flags & XVMC_OVERLAID_SURFACE)
585 subpicture_mode = OVERLAY_SUBPICTURE;
586
587 if(surface_info.subpicture_max_width != 0 &&
588 surface_info.subpicture_max_height != 0 ){
589 int s,k,num_subpic;
590
591 XvImageFormatValues * xvfmv;
592 xvfmv = XvMCListSubpictureTypes(mDisplay, xv_port,
593 surface_info.surface_type_id, &num_subpic);
594
595 if(num_subpic != 0 && xvfmv != NULL){
596 if(verbose > 3){//Print All subpicture types for debug
597 for(s=0;s<num_subpic;s++)
598 printf(" Subpicture id 0x%08X\n",xvfmv[s].id);
599 }
600
601 if(verbose > 0)
602 for(s=0;s<num_subpic;s++){
603 for(k=0;osd_render[k].draw_func_ptr!=NULL;k++)
604
605 if(xvfmv[s].id == osd_render[k].id)
606 {
607 init_osd_fnc = osd_render[k].init_func_ptr;
608 draw_osd_fnc = osd_render[k].draw_func_ptr;
609 clear_osd_fnc = osd_render[k].clear_func_ptr;
610
611 subpicture_mode = BLEND_SUBPICTURE;
612 subpicture_info = xvfmv[s];
613 print_xvimage_format_values(&subpicture_info);
614 goto found_subpic;
615 }
616 }
617 found_subpic:
618 XFree(xvfmv);
619 }
620 //Blend2 supicture is always possible, blend1 only at backend
621 if( (subpicture_mode == BLEND_SUBPICTURE) &&
622 (surface_info.flags & XVMC_BACKEND_SUBPICTURE) )
623 {
624 subpicture_mode = BACKEND_SUBPICTURE;
625 }
626
627 }
628
629 switch(subpicture_mode){
630 case NO_SUBPICTURE:
631 printf("vo_xvmc: No OSD support for this mode\n");
632 break;
633 case OVERLAY_SUBPICTURE:
634 printf("vo_xvmc: OSD support via color key tricks\n");
635 printf("vo_xvmc: not yet implemented:(\n");
636 break;
637 case BLEND_SUBPICTURE:
638 printf("vo_xvmc: OSD support by additional frontend rendering\n");
639 break;
640 case BACKEND_SUBPICTURE:
641 printf("vo_xvmc: OSD support by beckend rendering (fast)\n");
642 printf("vo_xvmc: Pleace send feedback to configrm that it work,otherwise send bugreport!\n");
643 break;
644 }
645
365 init_keycolor();// take keycolor value and choose method for handling it 646 init_keycolor();// take keycolor value and choose method for handling it
366 647
367 //taken from vo_xv 648 //taken from vo_xv
368 panscan_init(); 649 panscan_init();
369 650
370 aspect_save_orig(width,height); 651 aspect_save_orig(width,height);
371 aspect_save_prescale(d_width,d_height); 652 aspect_save_prescale(d_width,d_height);
372 653
373 image_height = height; 654 image_height = height;
374 image_width = width; 655 image_width = width;
375 656
376 vo_mouse_autohide = 1; 657 vo_mouse_autohide = 1;
377 658
378 vo_dx=( vo_screenwidth - d_width ) / 2; vo_dy=( vo_screenheight - d_height ) / 2; 659 vo_dx=( vo_screenwidth - d_width ) / 2; vo_dy=( vo_screenheight - d_height ) / 2;
379 geometry(&vo_dx, &vo_dy, &d_width, &d_height, vo_screenwidth, vo_screenheight); 660 geometry(&vo_dx, &vo_dy, &d_width, &d_height, vo_screenwidth, vo_screenheight);
380 vo_dwidth=d_width; vo_dheight=d_height; 661 vo_dwidth=d_width; vo_dheight=d_height;
381 662
382 #ifdef HAVE_XF86VM 663 #ifdef HAVE_XF86VM
383 if( flags&0x02 ) vm = 1; 664 if( flags&0x02 ) vm = 1;
384 #endif 665 #endif
385 666
386 aspect_save_screenres(vo_screenwidth,vo_screenheight); 667 aspect_save_screenres(vo_screenwidth,vo_screenheight);
433 depth=attribs.depth; 714 depth=attribs.depth;
434 if (depth != 15 && depth != 16 && depth != 24 && depth != 32) depth = 24; 715 if (depth != 15 && depth != 16 && depth != 24 && depth != 32) depth = 24;
435 XMatchVisualInfo(mDisplay, mScreen, depth, TrueColor, &vinfo); 716 XMatchVisualInfo(mDisplay, mScreen, depth, TrueColor, &vinfo);
436 717
437 xswa.background_pixel = 0; 718 xswa.background_pixel = 0;
438 if (keycolor_handling == 1) 719 if (keycolor_handling == BACKGROUND_COLORKEY)
439 xswa.background_pixel = keycolor;// 2110; 720 xswa.background_pixel = keycolor;// 2110;
440 xswa.border_pixel = 0; 721 xswa.border_pixel = 0;
441 xswamask = CWBackPixel | CWBorderPixel; 722 xswamask = CWBackPixel | CWBorderPixel;
442 723
443 if ( WinID>=0 ){ 724 if ( WinID>=0 ){
475 // vo_fs set means we were already at fullscreen 756 // vo_fs set means we were already at fullscreen
476 vo_x11_sizehint( hint.x, hint.y, hint.width, hint.height,0 ); 757 vo_x11_sizehint( hint.x, hint.y, hint.width, hint.height,0 );
477 if ( !vo_fs ) XMoveResizeWindow( mDisplay,vo_window,hint.x,hint.y,hint.width,hint.height ); 758 if ( !vo_fs ) XMoveResizeWindow( mDisplay,vo_window,hint.x,hint.y,hint.width,hint.height );
478 if ( flags&1 && !vo_fs ) vo_x11_fullscreen(); // handle -fs on non-first file 759 if ( flags&1 && !vo_fs ) vo_x11_fullscreen(); // handle -fs on non-first file
479 } 760 }
480 761
481 // vo_x11_sizehint( hint.x, hint.y, hint.width, hint.height,0 ); 762 // vo_x11_sizehint( hint.x, hint.y, hint.width, hint.height,0 );
482 763
483 if ( vo_gc != None ) XFreeGC( mDisplay,vo_gc ); 764 if ( vo_gc != None ) XFreeGC( mDisplay,vo_gc );
484 vo_gc = XCreateGC(mDisplay, vo_window, GCForeground, &xgcv); 765 vo_gc = XCreateGC(mDisplay, vo_window, GCForeground, &xgcv);
485 XFlush(mDisplay); 766 XFlush(mDisplay);
486 XSync(mDisplay, False); 767 XSync(mDisplay, False);
487 #ifdef HAVE_XF86VM 768 #ifdef HAVE_XF86VM
512 793
513 mp_msg(MSGT_VO,MSGL_V, "[xvmc] dx: %d dy: %d dw: %d dh: %d\n",drwX,drwY,vo_dwidth,vo_dheight ); 794 mp_msg(MSGT_VO,MSGL_V, "[xvmc] dx: %d dy: %d dw: %d dh: %d\n",drwX,drwY,vo_dwidth,vo_dheight );
514 795
515 saver_off(mDisplay); // turning off screen saver 796 saver_off(mDisplay); // turning off screen saver
516 //end vo_xv 797 //end vo_xv
517 798
518 /* store image dimesions for displaying */ 799 /* store image dimesions for displaying */
519 p_render_surface_visible = NULL; 800 p_render_surface_visible = NULL;
520 p_render_surface_to_show = NULL; 801 p_render_surface_to_show = NULL;
521 802
803 free_element = 0;
804
522 vo_directrendering = 1;//ugly hack, coz xvmc works only with direct rendering 805 vo_directrendering = 1;//ugly hack, coz xvmc works only with direct rendering
523 return 0; 806 return 0;
524 } 807 }
525 808
526 static uint32_t draw_frame(uint8_t *srcp[]){ 809 static uint32_t draw_frame(uint8_t *srcp[]){
527 assert(0 && srcp==NULL);//silense unused srcp warning 810 UNUSED(srcp);
811 assert(0);
812 }
813
814 static void init_osd_yuv_pal(){
815 char * palette;
816 int rez;
817 int i,j;
818 int snum,seb;
819 int Y,U,V;
820
821 subpicture_clear_color = 0;
822
823 if(subpicture.num_palette_entries > 0){
824
825 snum = subpicture.num_palette_entries;
826 seb = subpicture.entry_bytes;
827 palette = (char*)malloc(snum*seb);//check fail
828 if(palette == NULL) return;
829 for(i=0; i<snum; i++){
830 // 0-black max-white the other are gradients
831 Y = i*(1 << subpicture_info.y_sample_bits)/snum;//snum=2;->(0),(1*(1<<1)/2)
832 U = 1 << (subpicture_info.u_sample_bits - 1);
833 V = 1 << (subpicture_info.v_sample_bits - 1);
834 for(j=0; j<seb; j++)
835 switch(subpicture.component_order[j]){
836 case 'U': palette[i*seb+j] = U; break;
837 case 'V': palette[i*seb+j] = V; break;
838 case 'Y':
839 default:
840 palette[i*seb+j] = Y; break;
841 }
842 }
843 rez = XvMCSetSubpicturePalette(mDisplay, &subpicture, palette);
844 if(rez!=Success){
845 printf("vo_xvmc: set pallete fail\n");
846 }
847 }
848 }
849
850 static void clear_osd_subpic(int x0, int y0, int w, int h){
851 int rez;
852 rez=XvMCClearSubpicture(mDisplay, &subpicture,
853 x0, y0, w,h,
854 subpicture_clear_color);
855 if(rez != Success)
856 printf("vo_xvmc: XvMCClearSubpicture failed!\n");
857 }
858
859 static void OSD_init(){
860 unsigned short osd_height, osd_width;
861 int rez;
862
863 if(subpicture_alloc){
864 if(verbose>3)
865 printf("vo_xvmc: destroying subpicture\n");
866 XvMCDestroySubpicture(mDisplay,&subpicture);
867 deallocate_xvimage();
868 subpicture_alloc = 0;
869 }
870
871 /* if(surface_info.flags & XVMC_SUBPICTURE_INDEPENDENT_SCALING){
872 osd_width = vo_dwidth;
873 osd_height = vo_dheight;
874 }else*/
875 {
876 osd_width = image_width;
877 osd_height = image_height;
878 }
879
880 if(osd_width > surface_info.subpicture_max_width)
881 osd_width = surface_info.subpicture_max_width;
882 if(osd_height > surface_info.subpicture_max_height)
883 osd_height = surface_info.subpicture_max_height;
884 if(osd_width == 0 || osd_height == 0)
885 return;//if called before window size is known
886
887 if(verbose > 3)
888 printf("vo_xvmc: creating subpicture (%d,%d) format %X\n",
889 osd_width,osd_height,subpicture_info.id);
890
891 rez = XvMCCreateSubpicture(mDisplay,&ctx,&subpicture,
892 osd_width,osd_height,subpicture_info.id);
893 if(rez != Success){
894 subpicture_mode = NO_SUBPICTURE;
895 printf("vo_xvmc: Create Subpicture failed, OSD disabled\n");
896 return;
897 }
898 if(verbose > 3){
899 int i;
900 printf("vo_xvmc: Created Subpicture:\n");
901 printf(" xvimage_id=0x%X\n",subpicture.xvimage_id);
902 printf(" width=%d\n",subpicture.width);
903 printf(" height=%d\n",subpicture.height);
904 printf(" num_palette_entries=0x%X\n",subpicture.num_palette_entries);
905 printf(" entry_bytes=0x%X\n",subpicture.entry_bytes);
906
907 printf(" component_order=\"");
908 for(i=0; i<4; i++)
909 if(subpicture.component_order[i] >= 32)
910 printf("%c", subpicture.component_order[i]);
911 printf("\"\n");
912 }
913
914 //call init for the surface type
915 init_osd_fnc();//init palete,clear color etc ...
916 if(verbose > 3)
917 printf("vo_xvmc: clearing subpicture\n");
918 clear_osd_fnc(0, 0, subpicture.width, subpicture.height);
919
920 allocate_xvimage(subpicture.width, subpicture.height, subpicture_info.id);
921 subpicture_alloc = 1;
922 }
923
924 static void draw_osd_IA44(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){
925 int ox,oy;
926 int rez;
927
928 if(verbose > 3)
929 printf("vo_xvmc:composite AI44 subpicture (%d,%d - %d,%d)\n",x0,y0,w,h);
930
931 for(ox=0; ox<w; ox++){
932 for(oy=0; oy<h; oy++){
933 xvimage->data[oy*xvimage->width+ox] = (src[oy*stride+ox]>>4) | ((0-srca[oy*stride+ox])&0xf0);
934 }
935 }
936 rez = XvMCCompositeSubpicture(mDisplay, &subpicture, xvimage, 0, 0,
937 w,h,x0,y0);
938 if(rez != Success){
939 printf("vo_xvmc: composite subpicture failed\n");
940 assert(0);
941 }
942 }
943
944 static void draw_osd_AI44(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){
945 int ox,oy;
946 int rez;
947 if( verbose > 3)
948 printf("vo_xvmc:composite AI44 subpicture (%d,%d - %d,%d)\n",x0,y0,w,h);
949
950 for(ox=0; ox<w; ox++){
951 for(oy=0; oy<h; oy++){
952 xvimage->data[oy*xvimage->width+ox] = (src[oy*stride+ox]&0xf0) | (((0-srca[oy*stride+ox])>>4)&0xf);
953 }
954 }
955 rez = XvMCCompositeSubpicture(mDisplay, &subpicture, xvimage, 0, 0,
956 w,h,x0,y0);
957 if(rez != Success){
958 printf("vo_xvmc: composite subpicture failed\n");
959 assert(0);
960 }
528 } 961 }
529 962
530 static void draw_osd(void){ 963 static void draw_osd(void){
964 xvmc_render_state_t * osd_rndr;
965 int osd_has_changed;
966 int have_osd_to_draw;
967 int rez;
968
969 if(verbose > 3)
970 printf("vo_xvmc: draw_osd ,OSD_mode=%d, surface_to_show=%p\n",
971 subpicture_mode,p_render_surface_to_show);
972
973 if(subpicture_mode == BLEND_SUBPICTURE ||
974 subpicture_mode == BACKEND_SUBPICTURE ){
975
976 if(!subpicture_alloc) //allocate subpicture when dimensions are known
977 OSD_init();
978 if(!subpicture_alloc)
979 return;//dimensions still unknown.
980
981 osd_has_changed = vo_update_osd(subpicture.width, subpicture.height);
982 have_osd_to_draw = vo_osd_check_range_update(0, 0, subpicture.width,
983 subpicture.height);
984
985 if(!have_osd_to_draw)
986 return;//nothing to draw,no subpic, no blend
987
988 if(osd_has_changed){
989 //vo_remove_text(subpicture.width, subpicture.height,clear_osd_fnc)
990 clear_osd_fnc(0,0,subpicture.width,subpicture.height);
991 vo_draw_text(subpicture.width, subpicture.height, draw_osd_fnc);
992 }
993 XvMCSyncSubpicture(mDisplay,&subpicture);//todo usleeep wait!
994
995 if(subpicture_mode == BLEND_SUBPICTURE){
996 osd_rndr = find_free_surface();
997 if(osd_rndr == NULL)
998 return;// no free surface to draw OSD in
999
1000 rez = XvMCBlendSubpicture2(mDisplay,
1001 p_render_surface_to_show->p_surface, osd_rndr->p_surface,
1002 &subpicture,
1003 0, 0, subpicture.width, subpicture.height,
1004 0, 0, image_width, image_height);
1005 if(rez!=Success){
1006 printf("vo_xvmc: BlendSubpicture failed rez=%d\n",rez);
1007 assert(0);
1008 return;
1009 }
1010 // XvMCFlushSurface(mDisplay,osd_rndr->p_surface);//fixme- should I?
1011
1012 //When replaceing the surface with osd one, save the flags too!
1013 osd_rndr->picture_structure = p_render_surface_to_show->picture_structure;
1014 osd_rndr->display_flags = p_render_surface_to_show->display_flags;
1015 //add more if needed osd_rndr-> = p_render_surface_to_show->;
1016
1017 p_render_surface_to_show->state &= ~MP_XVMC_STATE_DISPLAY_PENDING;
1018 p_render_surface_to_show->state |= MP_XVMC_STATE_OSD_SOURCE;
1019 p_render_surface_to_show->p_osd_target_surface_render = osd_rndr;
1020
1021 p_render_surface_to_show = osd_rndr;
1022 p_render_surface_to_show->state = MP_XVMC_STATE_DISPLAY_PENDING;
1023
1024 if(verbose > 3)
1025 printf("vo_xvmc:draw_osd: surface_to_show changed to %p\n",osd_rndr);
1026 }//endof if(BLEND)
1027 if(subpicture_mode == BACKEND_SUBPICTURE){
1028 rez = XvMCBlendSubpicture(mDisplay,
1029 p_render_surface_to_show->p_surface,
1030 &subpicture,
1031 0, 0, subpicture.width, subpicture.height,
1032 0, 0, image_width, image_height);
1033
1034 }
1035
1036 }//if(BLEND||BACKEND)
531 } 1037 }
532 1038
533 static void xvmc_sync_surface(XvMCSurface * srf){ 1039 static void xvmc_sync_surface(XvMCSurface * srf){
534 int status,rez; 1040 int status,rez;
535 rez = XvMCGetSurfaceStatus(mDisplay,srf,&status); 1041 rez = XvMCGetSurfaceStatus(mDisplay,srf,&status);
536 assert(rez==Success); 1042 assert(rez==Success);
537 if( status & XVMC_RENDERING ) 1043 if((status & XVMC_RENDERING) == 0)
538 XvMCSyncSurface(mDisplay, srf); 1044 return;//surface is already complete
539 /* 1045 if(!busy_wait){
540 rez = XvMCFlushSurface(mDisplay, srf); 1046 rez = XvMCFlushSurface(mDisplay, srf);
541 assert(rez==Success); 1047 assert(rez==Success);
542 1048
543 do { 1049 do{
544 usleep(1); 1050 usec_sleep(1000);//1ms (may be 20ms on linux)
545 printf("waiting...\n"); 1051 XvMCGetSurfaceStatus(mDisplay,srf,&status);
546 XvMCGetSurfaceStatus(mDisplay,srf,&status); 1052 } while (status & XVMC_RENDERING);
547 } while (status & XVMC_RENDERING); 1053 return;//done
548 */ 1054 }
1055
1056 XvMCSyncSurface(mDisplay, srf);
549 } 1057 }
550 1058
551 static void flip_page(void){ 1059 static void flip_page(void){
552 int rez; 1060 int rez;
553 int clipX,clipY,clipW,clipH; 1061 int clipX,clipY,clipW,clipH;
1062 int i,cfs;
554 1063
555 clipX = drwX-(vo_panscan_x>>1); 1064 clipX = drwX-(vo_panscan_x>>1);
556 clipY = drwY-(vo_panscan_y>>1); 1065 clipY = drwY-(vo_panscan_y>>1);
557 clipW = vo_dwidth+vo_panscan_x; 1066 clipW = vo_dwidth+vo_panscan_x;
558 clipH = vo_dheight+vo_panscan_y;// 1067 clipH = vo_dheight+vo_panscan_y;
559 1068
560 if( verbose > 3 ) 1069 if( verbose > 3 )
561 printf("vo_xvmc: flip_page show(rndr=%p)\n\n",p_render_surface_to_show); 1070 printf("vo_xvmc: flip_page show(rndr=%p)\n\n",p_render_surface_to_show);
562 1071
563 if(p_render_surface_to_show == NULL) return; 1072 if(p_render_surface_to_show == NULL) return;
564 assert( p_render_surface_to_show->magic == MP_XVMC_RENDER_MAGIC ); 1073 assert( p_render_surface_to_show->magic == MP_XVMC_RENDER_MAGIC );
565 //fixme assert( p_render_surface_to_show != p_render_surface_visible); 1074 //fixme assert( p_render_surface_to_show != p_render_surface_visible);
566 1075
1076 if(use_queue){
1077 // fill the queue until only n free surfaces remain
1078 // after that start displaying
1079 cfs = count_free_surfaces();
1080 show_queue[free_element++] = p_render_surface_to_show;
1081 if(cfs > 3){//well have 3 free surfaces after add queue
1082 if(free_element > 1)//a little voodoo magic
1083 xvmc_sync_surface(show_queue[0]->p_surface);
1084 return;
1085 }
1086 p_render_surface_to_show=show_queue[0];
1087 if(verbose > 4)
1088 printf("vo_xvmc: flip_queue free_element=%d\n",free_element);
1089 free_element--;
1090 for(i=0; i<free_element; i++){
1091 show_queue[i] = show_queue[i+1];
1092 }
1093 show_queue[free_element] = NULL;
1094 }
1095
567 // make sure the rendering is done 1096 // make sure the rendering is done
568 xvmc_sync_surface(p_render_surface_to_show->p_surface); 1097 xvmc_sync_surface(p_render_surface_to_show->p_surface);
569 1098
570 //the visible surface won't be displayed anymore, mark it as free 1099 //the visible surface won't be displayed anymore, mark it as free
571 if( p_render_surface_visible!=NULL ) 1100 if(p_render_surface_visible != NULL)
572 p_render_surface_visible->state &= ~MP_XVMC_STATE_DISPLAY_PENDING; 1101 p_render_surface_visible->state &= ~MP_XVMC_STATE_DISPLAY_PENDING;
573 1102
574 //!!fixme assert(p_render_surface_to_show->state & MP_XVMC_STATE_DISPLAY_PENDING); 1103 //!!fixme assert(p_render_surface_to_show->state & MP_XVMC_STATE_DISPLAY_PENDING);
575 1104
576 // show it 1105 //show it, displaying is always vsynced, so skip it for benchmark
577 // if(benchmark) 1106 if(!benchmark){
578 rez=XvMCPutSurface(mDisplay, p_render_surface_to_show->p_surface, vo_window, 1107 rez = XvMCPutSurface(mDisplay, p_render_surface_to_show->p_surface,
579 0, 0, image_width, image_height, 1108 vo_window,
580 clipX, clipY, clipW, clipH, 1109 0, 0, image_width, image_height,
581 3);//p_render_surface_to_show->display_flags); 1110 clipX, clipY, clipW, clipH,
582 1111 3);//p_render_surface_to_show->display_flags);
583 assert(rez==Success); 1112 if(rez != Success){
584 1113 printf("vo_xvmc: PutSurface failer, critical error!\n");
1114 assert(0);
1115 }
1116 }
1117
585 p_render_surface_visible = p_render_surface_to_show; 1118 p_render_surface_visible = p_render_surface_to_show;
586 p_render_surface_to_show = NULL; 1119 p_render_surface_to_show = NULL;
587 } 1120 }
588 1121
589 static void check_events(void){ 1122 static void check_events(void){
593 1126
594 int e=vo_x11_check_events(mDisplay); 1127 int e=vo_x11_check_events(mDisplay);
595 if(e&VO_EVENT_RESIZE) 1128 if(e&VO_EVENT_RESIZE)
596 { 1129 {
597 e |= VO_EVENT_EXPOSE; 1130 e |= VO_EVENT_EXPOSE;
598 1131
599 XGetGeometry( mDisplay,vo_window,&mRoot,&drwX,&drwY,&vo_dwidth,&vo_dheight, 1132 XGetGeometry( mDisplay,vo_window,&mRoot,&drwX,&drwY,&vo_dwidth,&vo_dheight,
600 &drwBorderWidth,&drwDepth ); 1133 &drwBorderWidth,&drwDepth );
601 drwX = drwY = 0; 1134 drwX = drwY = 0;
602 mp_msg(MSGT_VO,MSGL_V, "[xvmc] dx: %d dy: %d dw: %d dh: %d\n",drwX,drwY, 1135 mp_msg(MSGT_VO,MSGL_V, "[xvmc] dx: %d dy: %d dw: %d dh: %d\n",drwX,drwY,
603 vo_dwidth,vo_dheight ); 1136 vo_dwidth,vo_dheight );
613 mp_msg(MSGT_VO,MSGL_V, "[xvmc-fs] dx: %d dy: %d dw: %d dh: %d\n",drwX,drwY,vo_dwidth,vo_dheight ); 1146 mp_msg(MSGT_VO,MSGL_V, "[xvmc-fs] dx: %d dy: %d dw: %d dh: %d\n",drwX,drwY,vo_dwidth,vo_dheight );
614 } 1147 }
615 } 1148 }
616 if ( e & VO_EVENT_EXPOSE ) 1149 if ( e & VO_EVENT_EXPOSE )
617 { 1150 {
618 mDrawColorKey(drwX,drwY,vo_dwidth,vo_dheight); 1151 mDrawColorKey(drwX,drwY,vo_dwidth,vo_dheight);
619 if(p_render_surface_visible != NULL) 1152 if(p_render_surface_visible != NULL)
620 XvMCPutSurface(mDisplay, p_render_surface_visible->p_surface,vo_window, 1153 XvMCPutSurface(mDisplay, p_render_surface_visible->p_surface,vo_window,
621 0, 0, image_width, image_height, 1154 0, 0, image_width, image_height,
622 drwX,drwY,vo_dwidth,vo_dheight, 1155 drwX,drwY,vo_dwidth,vo_dheight,
623 3);//,p_render_surface_visible->display_flags);!! 1156 3);//,p_render_surface_visible->display_flags);!!
624 } 1157 }
625 } 1158 }
626 1159
627 static void xvmc_free(void){ 1160 static void xvmc_free(void){
628 int i; 1161 int i;
1162 if( subpicture_alloc ){
1163
1164 XvMCDestroySubpicture(mDisplay,&subpicture);
1165 deallocate_xvimage();
1166
1167 subpicture_alloc = 0;
1168
1169 if(verbose > 3)
1170 printf("vo_xvmc: subpicture destroyed\n");
1171 }
629 1172
630 if( number_of_surfaces ){ 1173 if( number_of_surfaces ){
1174
631 XvMCDestroyMacroBlocks(mDisplay,&mv_blocks); 1175 XvMCDestroyMacroBlocks(mDisplay,&mv_blocks);
632 XvMCDestroyBlocks(mDisplay,&data_blocks); 1176 XvMCDestroyBlocks(mDisplay,&data_blocks);
1177
633 for(i=0; i<number_of_surfaces; i++) 1178 for(i=0; i<number_of_surfaces; i++)
634 { 1179 {
635 XvMCHideSurface(mDisplay,&surface_array[i]);//it doesn't hurt, I hope 1180 XvMCHideSurface(mDisplay,&surface_array[i]);//it doesn't hurt, I hope
636 XvMCDestroySurface(mDisplay,&surface_array[i]); 1181 XvMCDestroySurface(mDisplay,&surface_array[i]);
637 1182
638 if( (surface_render[i].state != 0) && 1183 if( (surface_render[i].state != 0) &&
639 (p_render_surface_visible != &surface_render[i]) ) 1184 (p_render_surface_visible != &surface_render[i]) )
640 printf("vo_xvmc::uninit surface_render[%d].status=%d\n",i, 1185 printf("vo_xvmc::uninit surface_render[%d].status=%d\n",i,
641 surface_render[i].state); 1186 surface_render[i].state);
642 } 1187 }
643 1188
644 free(surface_render);surface_render=NULL; 1189 free(surface_render);surface_render=NULL;
645 1190
646 XvMCDestroyContext(mDisplay,&ctx); 1191 XvMCDestroyContext(mDisplay,&ctx);
647 if( verbose > 3) printf("vo_xvmc: Context sucessfuly freed\n");
648 number_of_surfaces = 0; 1192 number_of_surfaces = 0;
649 } 1193
1194 if(verbose > 3) printf("vo_xvmc: Context sucessfuly freed\n");
1195 }
1196
1197
650 if( xv_port !=0 ){ 1198 if( xv_port !=0 ){
651 XvUngrabPort(mDisplay,xv_port,CurrentTime); 1199 XvUngrabPort(mDisplay,xv_port,CurrentTime);
652 xv_port = 0; 1200 xv_port = 0;
653 if( verbose > 3) printf("vo_xvmc: xv_port sucessfuly ungrabed\n"); 1201 if(verbose > 3) printf("vo_xvmc: xv_port sucessfuly ungrabed\n");
654 } 1202 }
655 } 1203 }
656 1204
657 static void uninit(void){ 1205 static void uninit(void){
658 if( verbose > 3 ) printf("vo_xvmc: uninit called\n"); 1206 if( verbose > 3 ) printf("vo_xvmc: uninit called\n");
673 1221
674 if(!IMGFMT_IS_XVMC(format)) return 0;// no caps supported 1222 if(!IMGFMT_IS_XVMC(format)) return 0;// no caps supported
675 mode_id = xvmc_find_surface_by_format(format, 16, 16, &qsurface_info, 1);//true=1 - quering 1223 mode_id = xvmc_find_surface_by_format(format, 16, 16, &qsurface_info, 1);//true=1 - quering
676 1224
677 if( mode_id == 0 ) return 0; 1225 if( mode_id == 0 ) return 0;
678 1226
679 flags = VFCAP_CSP_SUPPORTED | 1227 flags = VFCAP_CSP_SUPPORTED |
680 VFCAP_CSP_SUPPORTED_BY_HW | 1228 VFCAP_CSP_SUPPORTED_BY_HW |
681 VFCAP_ACCEPT_STRIDE; 1229 VFCAP_ACCEPT_STRIDE;
682 1230
683 // if(surfce_info.subpicture) 1231 if( (qsurface_info.subpicture_max_width != 0) &&
684 // flags|=VFCAP_OSD; 1232 (qsurface_info.subpicture_max_height != 0) )
1233 flags|=VFCAP_OSD;
685 return flags; 1234 return flags;
686 } 1235 }
687 1236
688 1237
689 static uint32_t draw_slice(uint8_t *image[], int stride[], 1238 static uint32_t draw_slice(uint8_t *image[], int stride[],
695 printf("vo_xvmc: draw_slice y=%d\n",y); 1244 printf("vo_xvmc: draw_slice y=%d\n",y);
696 1245
697 rndr = (xvmc_render_state_t*)image[2];//this is copy of priv-ate 1246 rndr = (xvmc_render_state_t*)image[2];//this is copy of priv-ate
698 assert( rndr != NULL ); 1247 assert( rndr != NULL );
699 assert( rndr->magic == MP_XVMC_RENDER_MAGIC ); 1248 assert( rndr->magic == MP_XVMC_RENDER_MAGIC );
700
701 if(rndr->p_past_surface != NULL)
702 xvmc_sync_surface(rndr->p_past_surface);
703 if(rndr->p_future_surface != NULL)
704 xvmc_sync_surface(rndr->p_future_surface);
705 1249
706 rez = XvMCRenderSurface(mDisplay,&ctx,rndr->picture_structure, 1250 rez = XvMCRenderSurface(mDisplay,&ctx,rndr->picture_structure,
707 rndr->p_surface, 1251 rndr->p_surface,
708 rndr->p_past_surface, 1252 rndr->p_past_surface,
709 rndr->p_future_surface, 1253 rndr->p_future_surface,
710 rndr->flags, 1254 rndr->flags,
711 rndr->filled_mv_blocks_num,rndr->start_mv_blocks_num, 1255 rndr->filled_mv_blocks_num,rndr->start_mv_blocks_num,
712 &mv_blocks,&data_blocks); 1256 &mv_blocks,&data_blocks);
713 #if 1 1257 #if 1
714 if(rez!=Success) 1258 if(rez != Success)
715 { 1259 {
716 int i; 1260 int i;
717 printf("vo_xvmc::slice: RenderSirface returned %d\n",rez); 1261 printf("vo_xvmc::slice: RenderSirface returned %d\n",rez);
718 1262
719 printf("vo_xvmc::slice: pict=%d,flags=%x,start_blocks=%d,num_blocks=%d\n", 1263 printf("vo_xvmc::slice: pict=%d,flags=%x,start_blocks=%d,num_blocks=%d\n",
720 rndr->picture_structure,rndr->flags,rndr->start_mv_blocks_num, 1264 rndr->picture_structure,rndr->flags,rndr->start_mv_blocks_num,
721 rndr->filled_mv_blocks_num); 1265 rndr->filled_mv_blocks_num);
722 printf("vo_xvmc::slice: this_surf=%p, past_surf=%p, future_surf=%p\n", 1266 printf("vo_xvmc::slice: this_surf=%p, past_surf=%p, future_surf=%p\n",
723 rndr->p_surface,rndr->p_past_surface,rndr->p_future_surface); 1267 rndr->p_surface,rndr->p_past_surface,rndr->p_future_surface);
724 1268
725 for(i=0;i<rndr->filled_mv_blocks_num;i++){ 1269 for(i=0; i<rndr->filled_mv_blocks_num; i++){
726 XvMCMacroBlock* testblock; 1270 XvMCMacroBlock* testblock;
727 testblock=&mv_blocks.macro_blocks[i]; 1271 testblock = &mv_blocks.macro_blocks[i];
728 1272
729 printf("vo_xvmc::slice: mv_block - x=%d,y=%d,mb_type=0x%x,mv_type=0x%x,mv_field_select=%d\n", 1273 printf("vo_xvmc::slice: mv_block - x=%d,y=%d,mb_type=0x%x,mv_type=0x%x,mv_field_select=%d\n",
730 testblock->x,testblock->y,testblock->macroblock_type, 1274 testblock->x,testblock->y,testblock->macroblock_type,
731 testblock->motion_type,testblock->motion_vertical_field_select); 1275 testblock->motion_type,testblock->motion_vertical_field_select);
732 printf("vo_xvmc::slice: dct_type=%d,data_index=0x%x,cbp=%d,pad0=%d\n", 1276 printf("vo_xvmc::slice: dct_type=%d,data_index=0x%x,cbp=%d,pad0=%d\n",
733 testblock->dct_type,testblock->index,testblock->coded_block_pattern, 1277 testblock->dct_type,testblock->index,testblock->coded_block_pattern,
734 testblock->pad0); 1278 testblock->pad0);
735 printf("vo_xvmc::slice: PMV[0][0][0/1]=(%d,%d)\n", 1279 printf("vo_xvmc::slice: PMV[0][0][0/1]=(%d,%d)\n",
736 testblock->PMV[0][0][0],testblock->PMV[0][0][1]); 1280 testblock->PMV[0][0][0],testblock->PMV[0][0][1]);
737
738 } 1281 }
739
740 } 1282 }
741 #endif 1283 #endif
742 assert(rez==Success); 1284 assert(rez==Success);
743 if(verbose > 3 ) printf("vo_xvmc: flush surface\n"); 1285 if(verbose > 3 ) printf("vo_xvmc: flush surface\n");
744 rez = XvMCFlushSurface(mDisplay, rndr->p_surface); 1286 rez = XvMCFlushSurface(mDisplay, rndr->p_surface);
751 rndr->next_free_data_block_num = 0; 1293 rndr->next_free_data_block_num = 0;
752 1294
753 return VO_TRUE; 1295 return VO_TRUE;
754 } 1296 }
755 1297
756 1298 //XvMCHide hides the surface on next retrace, so
757 static inline int find_free_surface(){ 1299 //check if the surface is not still displaying
758 int i,j,t; 1300 static void check_osd_source(xvmc_render_state_t * src_rndr){
1301 xvmc_render_state_t * osd_rndr;
759 int stat; 1302 int stat;
760 1303 //If this is source surface, check does the OSD rendering is compleate
761 j=-1; 1304 if(src_rndr->state & MP_XVMC_STATE_OSD_SOURCE){
1305 if(verbose > 3)
1306 printf("vo_xvmc: OSD surface=%p quering\n",src_rndr);
1307 osd_rndr = src_rndr->p_osd_target_surface_render;
1308 XvMCGetSurfaceStatus(mDisplay, osd_rndr->p_surface, &stat);
1309 if(!(stat & XVMC_RENDERING))
1310 src_rndr->state &= ~MP_XVMC_STATE_OSD_SOURCE;
1311 }
1312 }
1313 static int count_free_surfaces(){
1314 int i,num;
1315 num=0;
762 for(i=0; i<number_of_surfaces; i++){ 1316 for(i=0; i<number_of_surfaces; i++){
763 // printf("vo_xvmc: surface[%d].state=%d ( surf=%p)\n",i, 1317 check_osd_source(&surface_render[i]);
764 // surface_render[i].state, surface_render[i].p_surface); 1318 if(surface_render[i].state == 0)
1319 num++;
1320 }
1321 return num;
1322 }
1323
1324 static xvmc_render_state_t * find_free_surface(){
1325 int i,t;
1326 int stat;
1327 xvmc_render_state_t * visible_rndr;
1328
1329 visible_rndr = NULL;
1330 for(i=0; i<number_of_surfaces; i++){
1331
1332 check_osd_source(&surface_render[i]);
765 if( surface_render[i].state == 0){ 1333 if( surface_render[i].state == 0){
766 XvMCGetSurfaceStatus(mDisplay, surface_render[i].p_surface,&stat); 1334 XvMCGetSurfaceStatus(mDisplay, surface_render[i].p_surface,&stat);
767 if( (stat & XVMC_DISPLAYING) == 0 ) return i; 1335 if( (stat & XVMC_DISPLAYING) == 0 )
768 j=i; 1336 return &surface_render[i];
769 } 1337 visible_rndr = &surface_render[i];// remember it, use as last resort
770 } 1338 }
771 if(j>=0){//all surfaces are busy, but there is one that will be free 1339 }
1340
1341 //all surfaces are busy, but there is one that will be free
772 //on next monitor retrace, we just have to wait 1342 //on next monitor retrace, we just have to wait
773 for(t=0;t<1000;t++){ 1343 if(visible_rndr != NULL){
774 // usleep(10); //!!! 1344 printf("vo_xvmc: waiting retrace\n");
775 printf("vo_xvmc: waiting retrace\n"); 1345 for(t=0;t<1000;t++){
776 XvMCGetSurfaceStatus(mDisplay, surface_render[j].p_surface,&stat); 1346 usec_sleep(1000);//1ms
777 if( (stat & XVMC_DISPLAYING) == 0 ) return j; 1347 XvMCGetSurfaceStatus(mDisplay, visible_rndr->p_surface,&stat);
778 } 1348 if( (stat & XVMC_DISPLAYING) == 0 )
779 assert(0);//10 seconds wait for surface to get free! 1349 return visible_rndr;
780 exit(1); 1350 }
781 } 1351 }
782 return -1; 1352 //todo remove when stable
1353 printf("vo_xvmc: no free surfaces, this should not happen in g1\n");
1354 for(i=0;i<number_of_surfaces;i++)
1355 printf("vo_xvmc: surface[%d].state=%d\n",i,surface_render[i].state);
1356 return NULL;
783 } 1357 }
784 1358
785 static uint32_t get_image(mp_image_t *mpi){ 1359 static uint32_t get_image(mp_image_t *mpi){
786 int getsrf; 1360 xvmc_render_state_t * rndr;
787 1361
788 1362 rndr = find_free_surface();
789 getsrf=find_free_surface(); 1363
790 if(getsrf<0){ 1364 if(rndr == NULL){
791 int i; 1365 printf("vo_xvmc: get_image failed\n");
792 printf("vo_xvmc: no free surfaces, this should not happen in g1\n");
793 for(i=0;i<number_of_surfaces;i++)
794 printf("vo_xvmc: surface[%d].state=%d\n",i,surface_render[i].state);
795 return VO_FALSE; 1366 return VO_FALSE;
796 } 1367 }
797 1368
798 assert(surface_render[getsrf].start_mv_blocks_num == 0); 1369 assert(rndr->start_mv_blocks_num == 0);
799 assert(surface_render[getsrf].filled_mv_blocks_num == 0); 1370 assert(rndr->filled_mv_blocks_num == 0);
800 assert(surface_render[getsrf].next_free_data_block_num == 0); 1371 assert(rndr->next_free_data_block_num == 0);
801 1372
802 mpi->flags |= MP_IMGFLAG_DIRECT; 1373 mpi->flags |= MP_IMGFLAG_DIRECT;
803 //keep strides 0 to avoid field manipulations 1374 //keep strides 0 to avoid field manipulations
804 mpi->stride[0] = 0; 1375 mpi->stride[0] = 0;
805 mpi->stride[1] = 0; 1376 mpi->stride[1] = 0;
808 // these are shared!! so watch out 1379 // these are shared!! so watch out
809 // do call RenderSurface before overwriting 1380 // do call RenderSurface before overwriting
810 mpi->planes[0] = (char*)data_blocks.blocks; 1381 mpi->planes[0] = (char*)data_blocks.blocks;
811 mpi->planes[1] = (char*)mv_blocks.macro_blocks; 1382 mpi->planes[1] = (char*)mv_blocks.macro_blocks;
812 mpi->priv = 1383 mpi->priv =
813 mpi->planes[2] = (char*)&surface_render[getsrf]; 1384 mpi->planes[2] = (char*)rndr;
814 1385
815 surface_render[getsrf].picture_structure = 0; 1386 rndr->picture_structure = 0;
816 surface_render[getsrf].flags = 0; 1387 rndr->flags = 0;
817 surface_render[getsrf].state = 0; 1388 rndr->state = 0;
818 surface_render[getsrf].start_mv_blocks_num = 0; 1389 rndr->start_mv_blocks_num = 0;
819 surface_render[getsrf].filled_mv_blocks_num = 0; 1390 rndr->filled_mv_blocks_num = 0;
820 surface_render[getsrf].next_free_data_block_num = 0; 1391 rndr->next_free_data_block_num = 0;
821 1392
822 if( verbose > 3 ) 1393 if( verbose > 3 )
823 printf("vo_xvmc: get_image: .rndr=%p surface[%d]=%p \n", 1394 printf("vo_xvmc: get_image: rndr=%p (surface=%p) \n",
824 mpi->priv,getsrf,surface_render[getsrf].p_surface); 1395 rndr,rndr->p_surface);
825 return VO_TRUE; 1396 return VO_TRUE;
826 } 1397 }
827 1398
828 static uint32_t control(uint32_t request, void *data, ... ) 1399 static uint32_t control(uint32_t request, void *data, ... )
829 { 1400 {
840 case VOCTRL_FULLSCREEN: 1411 case VOCTRL_FULLSCREEN:
841 vo_x11_fullscreen(); 1412 vo_x11_fullscreen();
842 case VOCTRL_GET_PANSCAN: 1413 case VOCTRL_GET_PANSCAN:
843 if ( !vo_config_count || !vo_fs ) return VO_FALSE; 1414 if ( !vo_config_count || !vo_fs ) return VO_FALSE;
844 return VO_TRUE; 1415 return VO_TRUE;
845 // indended, fallthrough to update panscan on fullscreen/windowed switch 1416 // indended, fallthrough to update panscan on fullscreen/windowed switch
846 case VOCTRL_SET_PANSCAN: 1417 case VOCTRL_SET_PANSCAN:
847 if ( ( vo_fs && ( vo_panscan != vo_panscan_amount ) ) || ( !vo_fs && vo_panscan_amount ) ) 1418 if ( ( vo_fs && ( vo_panscan != vo_panscan_amount ) ) || ( !vo_fs && vo_panscan_amount ) )
848 { 1419 {
849 int old_y = vo_panscan_y; 1420 int old_y = vo_panscan_y;
850 panscan_calc(); 1421 panscan_calc();
851 1422
852 if(old_y != vo_panscan_y) 1423 if(old_y != vo_panscan_y)
853 { 1424 {
854 XClearWindow(mDisplay, vo_window); 1425 XClearWindow(mDisplay, vo_window);
855 XFlush(mDisplay); 1426 XFlush(mDisplay);
856 } 1427 }
859 1430
860 case VOCTRL_SET_EQUALIZER: 1431 case VOCTRL_SET_EQUALIZER:
861 { 1432 {
862 va_list ap; 1433 va_list ap;
863 int value; 1434 int value;
864 1435
865 va_start(ap, data); 1436 va_start(ap, data);
866 value = va_arg(ap, int); 1437 value = va_arg(ap, int);
867 va_end(ap); 1438 va_end(ap);
868 1439
869 return(vo_xv_set_eq(xv_port, data, value)); 1440 return(vo_xv_set_eq(xv_port, data, value));
870 } 1441 }
871 1442
872 case VOCTRL_GET_EQUALIZER: 1443 case VOCTRL_GET_EQUALIZER:
873 { 1444 {
874 va_list ap; 1445 va_list ap;
875 int *value; 1446 int *value;
876 1447
877 va_start(ap, data); 1448 va_start(ap, data);
878 value = va_arg(ap, int*); 1449 value = va_arg(ap, int*);
879 va_end(ap); 1450 va_end(ap);
880 1451
881 return(vo_xv_get_eq(xv_port, data, value)); 1452 return(vo_xv_get_eq(xv_port, data, value));
882 } 1453 }
883 } 1454 }
884 return VO_NOTIMPL; 1455 return VO_NOTIMPL;
885 } 1456 }
886