Cosmetics part2. Indent local variable definitions like the rest of the code.
[mplayer/glamo.git] / libvo / vo_xvmc.c
blob54a319e32c454e73854129ed7fe944f424521b95
1 /*
2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <unistd.h>
24 #include "config.h"
25 #include "mp_msg.h"
26 #include "video_out.h"
27 #include "video_out_internal.h"
28 #include "osdep/timer.h"
30 #include <X11/Xlib.h>
31 #include <X11/Xutil.h>
32 #include <X11/Xatom.h>
34 #ifdef HAVE_SHM
35 #include <sys/ipc.h>
36 #include <sys/shm.h>
37 #include <X11/extensions/XShm.h>
38 #endif
40 #include <X11/extensions/Xv.h>
41 #include <X11/extensions/Xvlib.h>
42 #include <X11/extensions/XvMClib.h>
44 #include "x11_common.h"
45 #include "libavcodec/avcodec.h"
46 #include "libavcodec/xvmc.h"
48 #include "sub.h"
49 #include "aspect.h"
51 #include "subopt-helper.h"
52 #include "gui/interface.h"
54 #include "libavutil/common.h"
56 //no chance for xinerama to be supported in the near future
57 #undef CONFIG_XINERAMA
59 #undef NDEBUG
60 #include <assert.h>
63 #define UNUSED(x) ((void)(x))
65 #if LIBAVCODEC_BUILD < ((51<<16)+(40<<8)+2)
66 #error You need at least libavcodecs v51.40.2
67 #endif
70 static int benchmark;
71 static int use_sleep;
72 static int first_frame;//draw colorkey on first frame
73 static int use_queue;
74 static int xv_port_request = 0;
75 static int xv_adaptor = -1;
76 static int bob_deinterlace;
77 static int top_field_first;
79 static int image_width,image_height;
80 static int image_format;
82 #define NO_SUBPICTURE 0
83 #define OVERLAY_SUBPICTURE 1
84 #define BLEND_SUBPICTURE 2
85 #define BACKEND_SUBPICTURE 3
87 static int subpicture_mode;
88 static int subpicture_alloc;
89 static XvMCSubpicture subpicture;
90 static XvImageFormatValues subpicture_info;
91 static int subpicture_clear_color;//transparent color for the subpicture or color key for overlay
93 static XvMCSurfaceInfo surface_info;
94 static XvMCContext ctx;
95 static XvMCBlockArray data_blocks;
96 static XvMCMacroBlockArray mv_blocks;
98 #define MAX_SURFACES 8
99 static int number_of_surfaces=0;
100 static XvMCSurface surface_array[MAX_SURFACES];
101 static struct xvmc_pix_fmt *surface_render;
103 static struct xvmc_pix_fmt *p_render_surface_to_show = NULL;
104 static struct xvmc_pix_fmt *p_render_surface_visible = NULL;
106 //display queue, kinda render ahead
107 static struct xvmc_pix_fmt *show_queue[MAX_SURFACES];
108 static int free_element;
111 static void (*draw_osd_fnc)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride);
112 static void (*clear_osd_fnc)(int x0,int y0, int w,int h);
113 static void (*init_osd_fnc)(void);
115 static void draw_osd_AI44(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride);
116 static void draw_osd_IA44(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride);
117 static void clear_osd_subpic(int x0,int y0, int w,int h);
118 static void init_osd_yuv_pal(void);
121 static const struct{
122 int id;//id as xvimages or as mplayer RGB|{8,15,16,24,32}
123 void (* init_func_ptr)();
124 void (* draw_func_ptr)();
125 void (* clear_func_ptr)();
126 } osd_render[]={
127 {0x34344149,init_osd_yuv_pal,draw_osd_AI44,clear_osd_subpic},
128 {0x34344941,init_osd_yuv_pal,draw_osd_IA44,clear_osd_subpic},
129 {0,NULL,NULL,NULL}
132 static void xvmc_free(void);
133 static void xvmc_clean_surfaces(void);
134 static int count_free_surfaces(void);
135 static struct xvmc_pix_fmt *find_free_surface(void);
137 static const vo_info_t info = {
138 "XVideo Motion Compensation",
139 "xvmc",
140 "Ivan Kalvachev <iive@users.sf.net>",
144 const LIBVO_EXTERN(xvmc);
146 //shm stuff from vo_xv
147 #ifdef HAVE_SHM
148 static XShmSegmentInfo Shminfo;
149 static int Shmem_Flag;
150 #endif
151 XvImage * xvimage;
154 static void allocate_xvimage(int xvimage_width,int xvimage_height,int xv_format)
157 * allocate XvImages. FIXME: no error checking, without
158 * mit-shm this will bomb... trzing to fix ::atmos
160 #ifdef HAVE_SHM
161 if ( mLocalDisplay && XShmQueryExtension( mDisplay ) ) Shmem_Flag = 1;
162 else
164 Shmem_Flag = 0;
165 mp_msg(MSGT_VO,MSGL_INFO, "Shared memory not supported\nReverting to normal Xv\n" );
167 if ( Shmem_Flag )
169 xvimage = (XvImage *) XvShmCreateImage(mDisplay, xv_port, xv_format,
170 NULL, xvimage_width, xvimage_height, &Shminfo);
172 Shminfo.shmid = shmget(IPC_PRIVATE, xvimage->data_size, IPC_CREAT | 0777);
173 Shminfo.shmaddr = (char *) shmat(Shminfo.shmid, 0, 0);
174 Shminfo.readOnly = False;
176 xvimage->data = Shminfo.shmaddr;
177 XShmAttach(mDisplay, &Shminfo);
178 XSync(mDisplay, False);
179 shmctl(Shminfo.shmid, IPC_RMID, 0);
181 else
182 #endif
184 xvimage = (XvImage *) XvCreateImage(mDisplay, xv_port, xv_format, NULL, xvimage_width, xvimage_height);
185 xvimage->data = malloc(xvimage->data_size);
186 XSync(mDisplay,False);
188 // memset(xvimage->data,128,xvimage->data_size);
189 return;
192 static void deallocate_xvimage(void)
194 #ifdef HAVE_SHM
195 if ( Shmem_Flag )
197 XShmDetach( mDisplay,&Shminfo );
198 shmdt( Shminfo.shmaddr );
200 else
201 #endif
203 free(xvimage->data);
205 XFree(xvimage);
207 XSync(mDisplay, False);
208 return;
210 //end of vo_xv shm/xvimage code
212 static int xvmc_check_surface_format(uint32_t format, XvMCSurfaceInfo * surf_info){
213 if ( format == IMGFMT_XVMC_IDCT_MPEG2 ){
214 if( surf_info->mc_type != (XVMC_IDCT|XVMC_MPEG_2) ) return -1;
215 if( surf_info->chroma_format != XVMC_CHROMA_FORMAT_420 ) return -1;
216 return 0;
218 if ( format == IMGFMT_XVMC_MOCO_MPEG2 ){
219 if(surf_info->mc_type != XVMC_MPEG_2) return -1;
220 if(surf_info->chroma_format != XVMC_CHROMA_FORMAT_420) return -1;
221 return 0;
223 return -1;//fail
226 //print all info needed to add new format
227 static void print_xvimage_format_values(XvImageFormatValues *xifv){
228 int i;
230 printf("Format_ID = 0x%X\n",xifv->id);
232 printf(" type = ");
233 if(xifv->type == XvRGB) printf("RGB\n");
234 else if(xifv->type == XvYUV) printf("YUV\n");
235 else printf("Unknown\n");
237 printf(" byte_order = ");
238 if(xifv->byte_order == LSBFirst) printf("LSB First\n");
239 else if(xifv->type == MSBFirst) printf("MSB First\n");
240 else printf("Unknown\n");//yes Linux support other types too
242 printf(" guid = ");
243 for(i=0;i<16;i++)
244 printf("%02X ",(unsigned char)xifv->guid[i]);
245 printf("\n");
247 printf(" bits_per_pixel = %d\n",xifv->bits_per_pixel);
249 printf(" format = ");
250 if(xifv->format == XvPacked) printf("XvPacked\n");
251 else if(xifv->format == XvPlanar) printf("XvPlanar\n");
252 else printf("Unknown\n");
254 printf(" num_planes = %d\n",xifv->num_planes);
256 if(xifv->type == XvRGB){
257 printf(" red_mask = %0X\n", xifv->red_mask);
258 printf(" green_mask = %0X\n",xifv->green_mask);
259 printf(" blue_mask = %0X\n", xifv->blue_mask);
261 if(xifv->type == XvYUV){
262 printf(" y_sample_bits = %d\n u_sample_bits = %d\n v_sample_bits = %d\n",
263 xifv->y_sample_bits,xifv->u_sample_bits,xifv->v_sample_bits);
264 printf(" horz_y_period = %d\n horz_u_period = %d\n horz_v_period = %d\n",
265 xifv->horz_y_period,xifv->horz_u_period,xifv->horz_v_period);
266 printf(" vert_y_period = %d\n vert_u_period = %d\n vert_v_period = %d\n",
267 xifv->vert_y_period,xifv->vert_u_period,xifv->vert_v_period);
269 printf(" component_order = ");
270 for(i=0;i<32;i++)
271 if(xifv->component_order[i]>=32)
272 printf("%c",xifv->component_order[i]);
273 printf("\n");
275 printf(" scanline = ");
276 if(xifv->scanline_order == XvTopToBottom) printf("XvTopToBottom\n");
277 else if(xifv->scanline_order == XvBottomToTop) printf("XvBottomToTop\n");
278 else printf("Unknown\n");
280 printf("\n");
283 // WARNING This function may changes xv_port and surface_info!
284 static int xvmc_find_surface_by_format(int format,int width,int height,
285 XvMCSurfaceInfo * surf_info,int query){
286 int rez;
287 XvAdaptorInfo * ai;
288 int num_adaptors,i;
289 unsigned long p;
290 int s,mc_surf_num;
291 XvMCSurfaceInfo * mc_surf_list;
293 rez = XvQueryAdaptors(mDisplay,DefaultRootWindow(mDisplay),&num_adaptors,&ai);
294 if( rez != Success ) return -1;
295 if( mp_msg_test(MSGT_VO,MSGL_DBG3) ) {
296 printf("vo_xvmc: Querying %d adaptors\n",num_adaptors); }
297 for(i=0; i<num_adaptors; i++)
299 /* check if adaptor number has been specified */
300 if (xv_adaptor != -1 && xv_adaptor != i)
301 continue;
302 if( mp_msg_test(MSGT_VO,MSGL_DBG3) ) {
303 printf("vo_xvmc: Quering adaptor #%d\n",i); }
304 if( ai[i].type == 0 ) continue;// we need at least dummy type!
305 //probing ports
306 for(p=ai[i].base_id; p<ai[i].base_id+ai[i].num_ports; p++)
308 if( mp_msg_test(MSGT_VO,MSGL_DBG3) ) {
309 printf("vo_xvmc: probing port #%ld\n",p); }
310 mc_surf_list = XvMCListSurfaceTypes(mDisplay,p,&mc_surf_num);
311 if( mc_surf_list == NULL || mc_surf_num == 0){
312 if( mp_msg_test(MSGT_VO,MSGL_DBG3) ) {
313 printf("vo_xvmc: No XvMC supported. \n"); }
314 continue;
316 if( mp_msg_test(MSGT_VO,MSGL_DBG3) ) {
317 printf("vo_xvmc: XvMC list have %d surfaces\n",mc_surf_num); }
318 //we have XvMC list!
319 for(s=0; s<mc_surf_num; s++)
321 if( width > mc_surf_list[s].max_width ) continue;
322 if( height > mc_surf_list[s].max_height ) continue;
323 if( xvmc_check_surface_format(format,&mc_surf_list[s])<0 ) continue;
324 //we have match!
325 /* respect the users wish */
326 if ( xv_port_request != 0 && xv_port_request != p )
328 continue;
331 if(!query){
332 rez = XvGrabPort(mDisplay,p,CurrentTime);
333 if(rez != Success){
334 if ( mp_msg_test(MSGT_VO,MSGL_DBG3) ) {
335 printf("vo_xvmc: Fail to grab port %ld\n",p); }
336 continue;
338 printf("vo_xvmc: Using Xv Adaptor #%d (%s)\n", i, ai[i].name);
339 printf("vo_xvmc: Port %ld grabed\n",p);
340 xv_port = p;
342 goto surface_found;
343 }//for mc surf
344 XFree(mc_surf_list);//if mc_surf_num==0 is list==NULL ?
345 }//for ports
346 }//for adaptors
347 XvFreeAdaptorInfo(ai);
349 if(!query) printf("vo_xvmc: Could not find free matching surface. Sorry.\n");
350 return 0;
352 // somebody know cleaner way to escape from 3 internal loops?
353 surface_found:
354 XvFreeAdaptorInfo(ai);
356 memcpy(surf_info,&mc_surf_list[s],sizeof(XvMCSurfaceInfo));
357 if( mp_msg_test(MSGT_VO,MSGL_DBG3) || !query)
358 printf("vo_xvmc: Found matching surface with id=%X on %ld port at %d adapter\n",
359 mc_surf_list[s].surface_type_id,p,i);
360 return mc_surf_list[s].surface_type_id;
363 static uint32_t xvmc_draw_image(mp_image_t *mpi){
364 struct xvmc_pix_fmt *rndr;
366 assert(mpi!=NULL);
367 assert(mpi->flags &MP_IMGFLAG_DIRECT);
368 // assert(mpi->flags &MP_IMGFLAGS_DRAWBACK);
370 rndr = (struct xvmc_pix_fmt*)mpi->priv; //there is copy in plane[2]
371 assert( rndr != NULL );
372 assert( rndr->xvmc_id == AV_XVMC_ID );
373 if( mp_msg_test(MSGT_VO,MSGL_DBG4) )
374 printf("vo_xvmc: draw_image(show rndr=%p)\n",rndr);
375 // the surface have passed vf system without been skiped, it will be displayed
376 rndr->state |= AV_XVMC_STATE_DISPLAY_PENDING;
377 p_render_surface_to_show = rndr;
378 top_field_first = mpi->fields & MP_IMGFIELD_TOP_FIRST;
379 return VO_TRUE;
382 static int preinit(const char *arg){
383 int xv_version,xv_release,xv_request_base,xv_event_base,xv_error_base;
384 int mc_eventBase,mc_errorBase;
385 int mc_ver,mc_rev;
386 strarg_t ck_src_arg = { 0, NULL };
387 strarg_t ck_method_arg = { 0, NULL };
388 opt_t subopts [] =
390 /* name arg type arg var test */
391 { "port", OPT_ARG_INT, &xv_port_request, (opt_test_f)int_pos },
392 { "adaptor", OPT_ARG_INT, &xv_adaptor, (opt_test_f)int_non_neg },
393 { "ck", OPT_ARG_STR, &ck_src_arg, xv_test_ck },
394 { "ck-method", OPT_ARG_STR, &ck_method_arg, xv_test_ckm },
395 { "benchmark", OPT_ARG_BOOL, &benchmark, NULL },
396 { "sleep", OPT_ARG_BOOL, &use_sleep, NULL },
397 { "queue", OPT_ARG_BOOL, &use_queue, NULL },
398 { "bobdeint", OPT_ARG_BOOL, &bob_deinterlace, NULL },
399 { NULL }
402 //Obtain display handler
403 if (!vo_init()) return -1;//vo_xv
405 //XvMC is subdivision of XVideo
406 if (Success != XvQueryExtension(mDisplay,&xv_version,&xv_release,&xv_request_base,
407 &xv_event_base,&xv_error_base) ){
408 mp_msg(MSGT_VO,MSGL_ERR,"Sorry, Xv(MC) not supported by this X11 version/driver\n");
409 mp_msg(MSGT_VO,MSGL_ERR,"********** Try with -vo x11 or -vo sdl ***********\n");
410 return -1;
412 printf("vo_xvmc: X-Video extension %d.%d\n",xv_version,xv_release);
414 if( True != XvMCQueryExtension(mDisplay,&mc_eventBase,&mc_errorBase) ){
415 printf("vo_xvmc: No X-Video MotionCompensation Extension on %s\n",
416 XDisplayName(NULL));
417 return -1;
420 if(Success == XvMCQueryVersion(mDisplay, &mc_ver, &mc_rev) ){
421 printf("vo_xvmc: X-Video MotionCompensation Extension version %i.%i\n",
422 mc_ver,mc_rev);
424 else{
425 printf("vo_xvmc: Error querying version info!\n");
426 return -1;
428 surface_render = NULL;
429 xv_port = 0;
430 number_of_surfaces = 0;
431 subpicture_alloc = 0;
433 benchmark = 0; //disable PutImageto allow faster display than screen refresh
434 use_sleep = 0;
435 use_queue = 0;
436 bob_deinterlace = 0;
438 /* parse suboptions */
439 if ( subopt_parse( arg, subopts ) != 0 )
441 return -1;
444 xv_setup_colorkeyhandling( ck_method_arg.str, ck_src_arg.str );
446 return 0;
449 static int config(uint32_t width, uint32_t height,
450 uint32_t d_width, uint32_t d_height,
451 uint32_t flags, char *title, uint32_t format){
452 int i,mode_id,rez;
453 int numblocks,blocks_per_macroblock;//bpmb we have 6,8,12
455 //from vo_xv
456 XVisualInfo vinfo;
457 XSetWindowAttributes xswa;
458 XWindowAttributes attribs;
459 unsigned long xswamask;
460 int depth;
461 #ifdef CONFIG_XF86VM
462 int vm = flags & VOFLAG_MODESWITCHING;
463 #endif
464 //end of vo_xv
466 if( !IMGFMT_IS_XVMC(format) )
468 assert(0);//should never happen, abort on debug or
469 return 1;//return error on relese
472 // Find free port that supports MC, by querying adaptors
473 if( xv_port != 0 || number_of_surfaces != 0 ){
474 if( height==image_height && width==image_width && image_format==format){
475 xvmc_clean_surfaces();
476 goto skip_surface_allocation;
478 xvmc_free();
480 numblocks=((width+15)/16)*((height+15)/16);
481 // Find Supported Surface Type
482 mode_id = xvmc_find_surface_by_format(format,width,height,&surface_info,0);//false=1 to grab port, not query
483 if ( mode_id == 0 )
485 return -1;
488 rez = XvMCCreateContext(mDisplay, xv_port,mode_id,width,height,XVMC_DIRECT,&ctx);
489 if( rez != Success ){
490 printf("vo_xvmc: XvMCCreateContext failed with error %d\n",rez);
491 return -1;
493 if( ctx.flags & XVMC_DIRECT ){
494 printf("vo_xvmc: Allocated Direct Context\n");
495 }else{
496 printf("vo_xvmc: Allocated Indirect Context!\n");
500 blocks_per_macroblock = 6;
501 if(surface_info.chroma_format == XVMC_CHROMA_FORMAT_422)
502 blocks_per_macroblock = 8;
503 if(surface_info.chroma_format == XVMC_CHROMA_FORMAT_444)
504 blocks_per_macroblock = 12;
506 rez = XvMCCreateBlocks(mDisplay,&ctx,numblocks*blocks_per_macroblock,&data_blocks);
507 if( rez != Success ){
508 XvMCDestroyContext(mDisplay,&ctx);
509 return -1;
511 printf("vo_xvmc: data_blocks allocated\n");
513 rez = XvMCCreateMacroBlocks(mDisplay,&ctx,numblocks,&mv_blocks);
514 if( rez != Success ){
515 XvMCDestroyBlocks(mDisplay,&data_blocks);
516 XvMCDestroyContext(mDisplay,&ctx);
517 return -1;
519 printf("vo_xvmc: mv_blocks allocated\n");
521 if(surface_render==NULL)
522 surface_render = malloc(MAX_SURFACES * sizeof(struct xvmc_pix_fmt)); //easy mem debug
523 memset(surface_render, 0, MAX_SURFACES * sizeof(struct xvmc_pix_fmt));
525 for(i=0; i<MAX_SURFACES; i++){
526 rez=XvMCCreateSurface(mDisplay,&ctx,&surface_array[i]);
527 if( rez != Success )
528 break;
529 surface_render[i].xvmc_id = AV_XVMC_ID;
530 surface_render[i].data_blocks = data_blocks.blocks;
531 surface_render[i].mv_blocks = mv_blocks.macro_blocks;
532 surface_render[i].allocated_mv_blocks = numblocks;
533 surface_render[i].allocated_data_blocks = numblocks*blocks_per_macroblock;
534 surface_render[i].idct = (surface_info.mc_type & XVMC_IDCT) == XVMC_IDCT;
535 surface_render[i].unsigned_intra = (surface_info.flags & XVMC_INTRA_UNSIGNED) == XVMC_INTRA_UNSIGNED;
536 surface_render[i].p_surface = &surface_array[i];
537 if( mp_msg_test(MSGT_VO,MSGL_DBG4) )
538 printf("vo_xvmc: surface[%d] = %p .rndr=%p\n",i,&surface_array[i], &surface_render[i]);
540 number_of_surfaces = i;
541 if( number_of_surfaces < 4 ){// +2 I or P and +2 for B (to avoid visible motion drawing)
542 printf("vo_xvmc: Unable to allocate at least 4 Surfaces\n");
543 uninit();
544 return -1;
546 printf("vo_xvmc: Motion Compensation context allocated - %d surfaces\n",
547 number_of_surfaces);
549 //debug
550 printf("vo_xvmc: idct=%d unsigned_intra=%d\n",
551 (surface_info.mc_type & XVMC_IDCT) == XVMC_IDCT,
552 (surface_info.flags & XVMC_INTRA_UNSIGNED) == XVMC_INTRA_UNSIGNED);
554 // Find way to display OSD & subtitle
555 printf("vo_xvmc: looking for OSD support\n");
556 subpicture_mode = NO_SUBPICTURE;
557 if(surface_info.flags & XVMC_OVERLAID_SURFACE)
558 subpicture_mode = OVERLAY_SUBPICTURE;
560 if(surface_info.subpicture_max_width != 0 &&
561 surface_info.subpicture_max_height != 0 ){
562 int s,k,num_subpic;
564 XvImageFormatValues * xvfmv;
565 xvfmv = XvMCListSubpictureTypes(mDisplay, xv_port,
566 surface_info.surface_type_id, &num_subpic);
568 if(num_subpic != 0 && xvfmv != NULL){
569 if( mp_msg_test(MSGT_VO,MSGL_DBG4) ){//Print all subpicture types for debug
570 for(s=0;s<num_subpic;s++)
571 print_xvimage_format_values(&xvfmv[s]);
574 for(s=0;s<num_subpic;s++){
575 for(k=0;osd_render[k].draw_func_ptr!=NULL;k++){
576 if(xvfmv[s].id == osd_render[k].id)
578 init_osd_fnc = osd_render[k].init_func_ptr;
579 draw_osd_fnc = osd_render[k].draw_func_ptr;
580 clear_osd_fnc = osd_render[k].clear_func_ptr;
582 subpicture_mode = BLEND_SUBPICTURE;
583 subpicture_info = xvfmv[s];
584 printf(" Subpicture id 0x%08X\n",subpicture_info.id);
585 goto found_subpic;
589 found_subpic:
590 XFree(xvfmv);
592 //Blend2 supicture is always possible, blend1 only at backend
593 if( (subpicture_mode == BLEND_SUBPICTURE) &&
594 (surface_info.flags & XVMC_BACKEND_SUBPICTURE) )
596 subpicture_mode = BACKEND_SUBPICTURE;
601 switch(subpicture_mode){
602 case NO_SUBPICTURE:
603 printf("vo_xvmc: No OSD support for this mode\n");
604 break;
605 case OVERLAY_SUBPICTURE:
606 printf("vo_xvmc: OSD support via color key tricks\n");
607 printf("vo_xvmc: not yet implemented:(\n");
608 break;
609 case BLEND_SUBPICTURE:
610 printf("vo_xvmc: OSD support by additional frontend rendering\n");
611 break;
612 case BACKEND_SUBPICTURE:
613 printf("vo_xvmc: OSD support by backend rendering (fast)\n");
614 printf("vo_xvmc: Please send feedback to confirm that it works,otherwise send bugreport!\n");
615 break;
618 //take keycolor value and choose method for handling it
619 if ( !vo_xv_init_colorkey() )
621 return -1; // bail out, colorkey setup failed
624 vo_xv_enable_vsync();//it won't break anything
626 //taken from vo_xv
627 image_height = height;
628 image_width = width;
630 skip_surface_allocation:
632 #ifdef CONFIG_GUI
633 if(use_gui)
634 guiGetEvent( guiSetShVideo,0 ); // let the GUI to setup/resize our window
635 else
636 #endif
638 #ifdef CONFIG_XF86VM
639 if ( vm )
641 vo_vm_switch();
643 // else
644 #endif
645 XGetWindowAttributes(mDisplay, DefaultRootWindow(mDisplay), &attribs);
646 depth=attribs.depth;
647 if (depth != 15 && depth != 16 && depth != 24 && depth != 32) depth = 24;
648 XMatchVisualInfo(mDisplay, mScreen, depth, TrueColor, &vinfo);
650 xswa.background_pixel = 0;
651 if (xv_ck_info.method == CK_METHOD_BACKGROUND)
652 xswa.background_pixel = xv_colorkey;
653 xswa.border_pixel = 0;
654 xswamask = CWBackPixel | CWBorderPixel;
656 vo_x11_create_vo_window(&vinfo, vo_dx, vo_dy, d_width, d_height, flags,
657 CopyFromParent, "xvmc", title);
658 XChangeWindowAttributes(mDisplay, vo_window, xswamask, &xswa);
660 #ifdef CONFIG_XF86VM
661 if ( vm )
663 /* Grab the mouse pointer in our window */
664 if(vo_grabpointer)
665 XGrabPointer(mDisplay, vo_window, True, 0,
666 GrabModeAsync, GrabModeAsync,
667 vo_window, None, CurrentTime );
668 XSetInputFocus(mDisplay, vo_window, RevertToNone, CurrentTime);
670 #endif
673 if ((flags & VOFLAG_FULLSCREEN) && WinID <= 0) vo_fs = 1;
675 //end vo_xv
677 /* store image dimesions for displaying */
678 p_render_surface_visible = NULL;
679 p_render_surface_to_show = NULL;
681 free_element = 0;
682 first_frame = 1;
684 image_format=format;
685 return 0;
688 static int draw_frame(uint8_t *srcp[]){
689 UNUSED(srcp);
690 assert(0);
693 static void init_osd_yuv_pal(void) {
694 char * palette;
695 int rez;
696 int i,j;
697 int snum,seb;
698 int Y,U,V;
700 subpicture_clear_color = 0;
702 if(subpicture.num_palette_entries > 0){
704 snum = subpicture.num_palette_entries;
705 seb = subpicture.entry_bytes;
706 palette = malloc(snum*seb);//check fail
707 if(palette == NULL) return;
708 for(i=0; i<snum; i++){
709 // 0-black max-white the other are gradients
710 Y = i*(1 << subpicture_info.y_sample_bits)/snum;//snum=2;->(0),(1*(1<<1)/2)
711 U = 1 << (subpicture_info.u_sample_bits - 1);
712 V = 1 << (subpicture_info.v_sample_bits - 1);
713 for(j=0; j<seb; j++)
714 switch(subpicture.component_order[j]){
715 case 'U': palette[i*seb+j] = U; break;
716 case 'V': palette[i*seb+j] = V; break;
717 case 'Y':
718 default:
719 palette[i*seb+j] = Y; break;
722 rez = XvMCSetSubpicturePalette(mDisplay, &subpicture, palette);
723 if(rez!=Success){
724 printf("vo_xvmc: Setting palette failed.\n");
726 free(palette);
730 static void clear_osd_subpic(int x0, int y0, int w, int h){
731 int rez;
733 rez=XvMCClearSubpicture(mDisplay, &subpicture,
734 x0, y0, w,h,
735 subpicture_clear_color);
736 if(rez != Success)
737 printf("vo_xvmc: XvMCClearSubpicture failed!\n");
740 static void OSD_init(void) {
741 unsigned short osd_height, osd_width;
742 int rez;
744 if(subpicture_alloc){
745 if( mp_msg_test(MSGT_VO,MSGL_DBG4) )
746 printf("vo_xvmc: destroying subpicture\n");
747 XvMCDestroySubpicture(mDisplay,&subpicture);
748 deallocate_xvimage();
749 subpicture_alloc = 0;
752 /* if(surface_info.flags & XVMC_SUBPICTURE_INDEPENDENT_SCALING){
753 osd_width = vo_dwidth;
754 osd_height = vo_dheight;
755 }else*/
757 osd_width = image_width;
758 osd_height = image_height;
761 if(osd_width > surface_info.subpicture_max_width)
762 osd_width = surface_info.subpicture_max_width;
763 if(osd_height > surface_info.subpicture_max_height)
764 osd_height = surface_info.subpicture_max_height;
765 if(osd_width == 0 || osd_height == 0)
766 return;//if called before window size is known
768 if( mp_msg_test(MSGT_VO,MSGL_DBG4) )
769 printf("vo_xvmc: creating subpicture (%d,%d) format %X\n",
770 osd_width,osd_height,subpicture_info.id);
772 rez = XvMCCreateSubpicture(mDisplay,&ctx,&subpicture,
773 osd_width,osd_height,subpicture_info.id);
774 if(rez != Success){
775 subpicture_mode = NO_SUBPICTURE;
776 printf("vo_xvmc: Create Subpicture failed, OSD disabled\n");
777 return;
779 if( mp_msg_test(MSGT_VO,MSGL_DBG4) ){
780 int i;
781 printf("vo_xvmc: Created Subpicture:\n");
782 printf(" xvimage_id=0x%X\n",subpicture.xvimage_id);
783 printf(" width=%d\n",subpicture.width);
784 printf(" height=%d\n",subpicture.height);
785 printf(" num_palette_entries=0x%X\n",subpicture.num_palette_entries);
786 printf(" entry_bytes=0x%X\n",subpicture.entry_bytes);
788 printf(" component_order=\"");
789 for(i=0; i<4; i++)
790 if(subpicture.component_order[i] >= 32)
791 printf("%c", subpicture.component_order[i]);
792 printf("\"\n");
795 //call init for the surface type
796 init_osd_fnc();//init palete,clear color etc ...
797 if( mp_msg_test(MSGT_VO,MSGL_DBG4) )
798 printf("vo_xvmc: clearing subpicture\n");
799 clear_osd_fnc(0, 0, subpicture.width, subpicture.height);
801 allocate_xvimage(subpicture.width, subpicture.height, subpicture_info.id);
802 subpicture_alloc = 1;
805 static void draw_osd_IA44(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){
806 int ox,oy;
807 int rez;
809 if( mp_msg_test(MSGT_VO,MSGL_DBG4) )
810 printf("vo_xvmc:composite AI44 subpicture (%d,%d - %d,%d)\n",x0,y0,w,h);
812 for(ox=0; ox<w; ox++){
813 for(oy=0; oy<h; oy++){
814 xvimage->data[oy*xvimage->width+ox] = (src[oy*stride+ox]>>4) | ((0-srca[oy*stride+ox])&0xf0);
817 rez = XvMCCompositeSubpicture(mDisplay, &subpicture, xvimage, 0, 0,
818 w,h,x0,y0);
819 if(rez != Success){
820 printf("vo_xvmc: composite subpicture failed\n");
821 assert(0);
825 static void draw_osd_AI44(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){
826 int ox,oy;
827 int rez;
829 if( mp_msg_test(MSGT_VO,MSGL_DBG4) )
830 printf("vo_xvmc:composite AI44 subpicture (%d,%d - %d,%d)\n",x0,y0,w,h);
832 for(ox=0; ox<w; ox++){
833 for(oy=0; oy<h; oy++){
834 xvimage->data[oy*xvimage->width+ox] = (src[oy*stride+ox]&0xf0) | (((0-srca[oy*stride+ox])>>4)&0xf);
837 rez = XvMCCompositeSubpicture(mDisplay, &subpicture, xvimage, 0, 0,
838 w,h,x0,y0);
839 if(rez != Success){
840 printf("vo_xvmc: composite subpicture failed\n");
841 assert(0);
845 static void draw_osd(void){
846 struct xvmc_pix_fmt *osd_rndr;
847 int osd_has_changed;
848 int have_osd_to_draw;
849 int rez;
851 if( mp_msg_test(MSGT_VO,MSGL_DBG4) )
852 printf("vo_xvmc: draw_osd ,OSD_mode=%d, surface_to_show=%p\n",
853 subpicture_mode,p_render_surface_to_show);
855 if(subpicture_mode == BLEND_SUBPICTURE ||
856 subpicture_mode == BACKEND_SUBPICTURE ){
858 if(!subpicture_alloc) //allocate subpicture when dimensions are known
859 OSD_init();
860 if(!subpicture_alloc)
861 return;//dimensions still unknown.
863 osd_has_changed = vo_update_osd(subpicture.width, subpicture.height);
864 have_osd_to_draw = vo_osd_check_range_update(0, 0, subpicture.width,
865 subpicture.height);
867 if(!have_osd_to_draw)
868 return;//nothing to draw,no subpic, no blend
870 if(osd_has_changed){
871 //vo_remove_text(subpicture.width, subpicture.height,clear_osd_fnc)
872 clear_osd_fnc(0,0,subpicture.width,subpicture.height);
873 vo_draw_text(subpicture.width, subpicture.height, draw_osd_fnc);
875 XvMCSyncSubpicture(mDisplay,&subpicture);//todo usleeep wait!
877 if(subpicture_mode == BLEND_SUBPICTURE){
878 osd_rndr = find_free_surface();
879 if(osd_rndr == NULL)
880 return;// no free surface to draw OSD in
882 rez = XvMCBlendSubpicture2(mDisplay,
883 p_render_surface_to_show->p_surface, osd_rndr->p_surface,
884 &subpicture,
885 0, 0, subpicture.width, subpicture.height,
886 0, 0, image_width, image_height);
887 if(rez!=Success){
888 printf("vo_xvmc: BlendSubpicture failed rez=%d\n",rez);
889 assert(0);
890 return;
892 // XvMCFlushSurface(mDisplay,osd_rndr->p_surface);//fixme- should I?
894 //When replaceing the surface with osd one, save the flags too!
895 osd_rndr->picture_structure = p_render_surface_to_show->picture_structure;
896 //add more if needed osd_rndr-> = p_render_surface_to_show->;
898 p_render_surface_to_show->state &= ~AV_XVMC_STATE_DISPLAY_PENDING;
899 p_render_surface_to_show->state |= AV_XVMC_STATE_OSD_SOURCE;
900 p_render_surface_to_show->p_osd_target_surface_render = osd_rndr;
902 p_render_surface_to_show = osd_rndr;
903 p_render_surface_to_show->state = AV_XVMC_STATE_DISPLAY_PENDING;
905 if( mp_msg_test(MSGT_VO,MSGL_DBG4) )
906 printf("vo_xvmc:draw_osd: surface_to_show changed to %p\n",osd_rndr);
907 }//endof if(BLEND)
908 if(subpicture_mode == BACKEND_SUBPICTURE){
909 rez = XvMCBlendSubpicture(mDisplay,
910 p_render_surface_to_show->p_surface,
911 &subpicture,
912 0, 0, subpicture.width, subpicture.height,
913 0, 0, image_width, image_height);
917 }//if(BLEND||BACKEND)
920 static void xvmc_sync_surface(XvMCSurface * srf){
921 int status,rez;
923 rez = XvMCGetSurfaceStatus(mDisplay,srf,&status);
924 assert(rez==Success);
925 if((status & XVMC_RENDERING) == 0)
926 return;//surface is already complete
927 if(use_sleep){
928 rez = XvMCFlushSurface(mDisplay, srf);
929 assert(rez==Success);
932 usec_sleep(1000);//1ms (may be 20ms on linux)
933 XvMCGetSurfaceStatus(mDisplay,srf,&status);
934 } while (status & XVMC_RENDERING);
935 return;//done
938 XvMCSyncSurface(mDisplay, srf);
941 static void put_xvmc_image(struct xvmc_pix_fmt *p_render_surface,
942 int draw_ck){
943 int rez;
944 struct vo_rect src_rect, dst_rect;
945 int i;
947 if(p_render_surface == NULL)
948 return;
950 calc_src_dst_rects(image_width, image_height, &src_rect, &dst_rect, NULL, NULL);
952 if(draw_ck)
953 vo_xv_draw_colorkey(dst_rect.left, dst_rect.top, dst_rect.width, dst_rect.height);
955 if(benchmark)
956 return;
958 for (i = 1; i <= bob_deinterlace + 1; i++) {
959 int field = top_field_first ? i : i ^ 3;
960 rez = XvMCPutSurface(mDisplay, p_render_surface->p_surface,
961 vo_window,
962 src_rect.left, src_rect.top, src_rect.width, src_rect.height,
963 dst_rect.left, dst_rect.top, dst_rect.width, dst_rect.height,
964 bob_deinterlace ? field : 3);
965 if(rez != Success){
966 printf("vo_xvmc: PutSurface failer, critical error %d!\n",rez);
967 assert(0);
970 XFlush(mDisplay);
973 static void flip_page(void){
974 int i,cfs;
976 if( mp_msg_test(MSGT_VO,MSGL_DBG4) )
977 printf("vo_xvmc: flip_page show(rndr=%p)\n\n",p_render_surface_to_show);
979 if(p_render_surface_to_show == NULL) return;
980 assert( p_render_surface_to_show->xvmc_id == AV_XVMC_ID );
981 //fixme assert( p_render_surface_to_show != p_render_surface_visible);
983 if(use_queue){
984 // fill the queue until only n free surfaces remain
985 // after that start displaying
986 cfs = count_free_surfaces();
987 show_queue[free_element++] = p_render_surface_to_show;
988 if(cfs > 3){//well have 3 free surfaces after add queue
989 if(free_element > 1)//a little voodoo magic
990 xvmc_sync_surface(show_queue[0]->p_surface);
991 return;
993 p_render_surface_to_show=show_queue[0];
994 if( mp_msg_test(MSGT_VO,MSGL_DBG5) )
995 printf("vo_xvmc: flip_queue free_element=%d\n",free_element);
996 free_element--;
997 for(i=0; i<free_element; i++){
998 show_queue[i] = show_queue[i+1];
1000 show_queue[free_element] = NULL;
1003 // make sure the rendering is done
1004 xvmc_sync_surface(p_render_surface_to_show->p_surface);
1006 //the visible surface won't be displayed anymore, mark it as free
1007 if(p_render_surface_visible != NULL)
1008 p_render_surface_visible->state &= ~AV_XVMC_STATE_DISPLAY_PENDING;
1010 //!!fixme assert(p_render_surface_to_show->state & AV_XVMC_STATE_DISPLAY_PENDING);
1012 //show it, displaying is always vsynced, so skip it for benchmark
1013 put_xvmc_image(p_render_surface_to_show,first_frame);
1014 first_frame=0;//make sure we won't draw it anymore
1016 p_render_surface_visible = p_render_surface_to_show;
1017 p_render_surface_to_show = NULL;
1020 static void check_events(void){
1021 int e=vo_x11_check_events(mDisplay);
1023 if(e&VO_EVENT_RESIZE)
1025 e |= VO_EVENT_EXPOSE;
1027 if ( e & VO_EVENT_EXPOSE )
1029 put_xvmc_image(p_render_surface_visible,1);
1033 static void xvmc_free(void){
1034 int i;
1036 if( subpicture_alloc ){
1038 XvMCDestroySubpicture(mDisplay,&subpicture);
1039 deallocate_xvimage();
1041 subpicture_alloc = 0;
1043 if( mp_msg_test(MSGT_VO,MSGL_DBG4) )
1044 printf("vo_xvmc: subpicture destroyed\n");
1047 if( number_of_surfaces ){
1049 XvMCDestroyMacroBlocks(mDisplay,&mv_blocks);
1050 XvMCDestroyBlocks(mDisplay,&data_blocks);
1052 for(i=0; i<number_of_surfaces; i++)
1054 XvMCHideSurface(mDisplay,&surface_array[i]);//it doesn't hurt, I hope
1055 XvMCDestroySurface(mDisplay,&surface_array[i]);
1057 if( (surface_render[i].state != 0) &&
1058 (p_render_surface_visible != &surface_render[i]) )
1059 printf("vo_xvmc::uninit surface_render[%d].status=%d\n",i,
1060 surface_render[i].state);
1063 memset(surface_render, 0, MAX_SURFACES * sizeof(struct xvmc_pix_fmt)); //for debugging
1064 free(surface_render);surface_render=NULL;
1066 XvMCDestroyContext(mDisplay,&ctx);
1067 number_of_surfaces = 0;
1069 if( mp_msg_test(MSGT_VO,MSGL_DBG4) ) {
1070 printf("vo_xvmc: Context sucessfuly freed\n"); }
1074 if( xv_port !=0 ){
1075 XvUngrabPort(mDisplay,xv_port,CurrentTime);
1076 xv_port = 0;
1077 if( mp_msg_test(MSGT_VO,MSGL_DBG4) ) {
1078 printf("vo_xvmc: xv_port sucessfuly ungrabed\n"); }
1082 static void uninit(void){
1083 if( mp_msg_test(MSGT_VO,MSGL_DBG4) ) {
1084 printf("vo_xvmc: uninit called\n"); }
1085 xvmc_free();
1086 //from vo_xv
1087 #ifdef CONFIG_XF86VM
1088 vo_vm_close();
1089 #endif
1090 vo_x11_uninit();
1093 static int query_format(uint32_t format){
1094 uint32_t flags;
1095 XvMCSurfaceInfo qsurface_info;
1096 int mode_id;
1098 if( mp_msg_test(MSGT_VO,MSGL_DBG4) )
1099 printf("vo_xvmc: query_format=%X\n",format);
1101 if(!IMGFMT_IS_XVMC(format)) return 0;// no caps supported
1102 mode_id = xvmc_find_surface_by_format(format, 16, 16, &qsurface_info, 1);//true=1 - quering
1104 if( mode_id == 0 ) return 0;
1106 flags = VFCAP_CSP_SUPPORTED |
1107 VFCAP_CSP_SUPPORTED_BY_HW |
1108 VFCAP_ACCEPT_STRIDE;
1110 if( (qsurface_info.subpicture_max_width != 0) &&
1111 (qsurface_info.subpicture_max_height != 0) )
1112 flags|=VFCAP_OSD;
1113 return flags;
1117 static int draw_slice(uint8_t *image[], int stride[],
1118 int w, int h, int x, int y){
1119 struct xvmc_pix_fmt *rndr;
1120 int rez;
1122 if( mp_msg_test(MSGT_VO,MSGL_DBG4) )
1123 printf("vo_xvmc: draw_slice y=%d\n",y);
1125 rndr = (struct xvmc_pix_fmt*)image[2]; //this is copy of priv-ate
1126 assert( rndr != NULL );
1127 assert( rndr->xvmc_id == AV_XVMC_ID );
1129 rez = XvMCRenderSurface(mDisplay,&ctx,rndr->picture_structure,
1130 rndr->p_surface,
1131 rndr->p_past_surface,
1132 rndr->p_future_surface,
1133 rndr->flags,
1134 rndr->filled_mv_blocks_num,rndr->start_mv_blocks_num,
1135 &mv_blocks,&data_blocks);
1136 #if 1
1137 if(rez != Success)
1139 int i;
1140 printf("vo_xvmc::slice: RenderSirface returned %d\n",rez);
1142 printf("vo_xvmc::slice: pict=%d,flags=%x,start_blocks=%d,num_blocks=%d\n",
1143 rndr->picture_structure,rndr->flags,rndr->start_mv_blocks_num,
1144 rndr->filled_mv_blocks_num);
1145 printf("vo_xvmc::slice: this_surf=%p, past_surf=%p, future_surf=%p\n",
1146 rndr->p_surface,rndr->p_past_surface,rndr->p_future_surface);
1148 for(i=0; i<rndr->filled_mv_blocks_num; i++){
1149 XvMCMacroBlock* testblock;
1150 testblock = &mv_blocks.macro_blocks[i];
1152 printf("vo_xvmc::slice: mv_block - x=%d,y=%d,mb_type=0x%x,mv_type=0x%x,mv_field_select=%d\n",
1153 testblock->x,testblock->y,testblock->macroblock_type,
1154 testblock->motion_type,testblock->motion_vertical_field_select);
1155 printf("vo_xvmc::slice: dct_type=%d,data_index=0x%x,cbp=%d,pad0=%d\n",
1156 testblock->dct_type,testblock->index,testblock->coded_block_pattern,
1157 testblock->pad0);
1158 printf("vo_xvmc::slice: PMV[0][0][0/1]=(%d,%d)\n",
1159 testblock->PMV[0][0][0],testblock->PMV[0][0][1]);
1162 #endif
1163 assert(rez==Success);
1164 if( mp_msg_test(MSGT_VO,MSGL_DBG4) ) printf("vo_xvmc: flush surface\n");
1165 rez = XvMCFlushSurface(mDisplay, rndr->p_surface);
1166 assert(rez==Success);
1168 // rndr->start_mv_blocks_num += rndr->filled_mv_blocks_num;
1169 rndr->start_mv_blocks_num = 0;
1170 rndr->filled_mv_blocks_num = 0;
1172 rndr->next_free_data_block_num = 0;
1174 return VO_TRUE;
1177 //XvMCHide hides the surface on next retrace, so
1178 //check if the surface is not still displaying
1179 static void check_osd_source(struct xvmc_pix_fmt *src_rndr) {
1180 struct xvmc_pix_fmt *osd_rndr;
1181 int stat;
1183 //If this is source surface, check does the OSD rendering is compleate
1184 if(src_rndr->state & AV_XVMC_STATE_OSD_SOURCE){
1185 if( mp_msg_test(MSGT_VO,MSGL_DBG4) )
1186 printf("vo_xvmc: OSD surface=%p quering\n",src_rndr);
1187 osd_rndr = src_rndr->p_osd_target_surface_render;
1188 XvMCGetSurfaceStatus(mDisplay, osd_rndr->p_surface, &stat);
1189 if(!(stat & XVMC_RENDERING))
1190 src_rndr->state &= ~AV_XVMC_STATE_OSD_SOURCE;
1193 static int count_free_surfaces(void) {
1194 int i,num;
1196 num=0;
1197 for(i=0; i<number_of_surfaces; i++){
1198 check_osd_source(&surface_render[i]);
1199 if(surface_render[i].state == 0)
1200 num++;
1202 return num;
1205 static struct xvmc_pix_fmt *find_free_surface(void) {
1206 int i,t;
1207 int stat;
1208 struct xvmc_pix_fmt *visible_rndr;
1210 visible_rndr = NULL;
1211 for(i=0; i<number_of_surfaces; i++){
1213 check_osd_source(&surface_render[i]);
1214 if( surface_render[i].state == 0){
1215 XvMCGetSurfaceStatus(mDisplay, surface_render[i].p_surface,&stat);
1216 if( (stat & XVMC_DISPLAYING) == 0 )
1217 return &surface_render[i];
1218 visible_rndr = &surface_render[i];// remember it, use as last resort
1222 //all surfaces are busy, but there is one that will be free
1223 //on next monitor retrace, we just have to wait
1224 if(visible_rndr != NULL){
1225 printf("vo_xvmc: waiting retrace\n");
1226 for(t=0;t<1000;t++){
1227 usec_sleep(1000);//1ms
1228 XvMCGetSurfaceStatus(mDisplay, visible_rndr->p_surface,&stat);
1229 if( (stat & XVMC_DISPLAYING) == 0 )
1230 return visible_rndr;
1233 //todo remove when stable
1234 printf("vo_xvmc: no free surfaces, this should not happen in g1\n");
1235 for(i=0;i<number_of_surfaces;i++)
1236 printf("vo_xvmc: surface[%d].state=%d\n",i,surface_render[i].state);
1237 return NULL;
1240 static void xvmc_clean_surfaces(void){
1241 int i;
1243 for(i=0; i<number_of_surfaces; i++){
1245 surface_render[i].state&=!( AV_XVMC_STATE_DISPLAY_PENDING |
1246 AV_XVMC_STATE_OSD_SOURCE |
1248 surface_render[i].p_osd_target_surface_render=NULL;
1249 if(surface_render[i].state != 0){
1250 mp_msg(MSGT_VO,MSGL_WARN,"vo_xvmc: surface[%d].state=%d\n",
1251 i,surface_render[i].state);
1254 free_element=0;//clean up the queue
1257 static uint32_t get_image(mp_image_t *mpi){
1258 struct xvmc_pix_fmt *rndr;
1260 rndr = find_free_surface();
1262 if(rndr == NULL){
1263 printf("vo_xvmc: get_image failed\n");
1264 return VO_FALSE;
1267 assert(rndr->start_mv_blocks_num == 0);
1268 assert(rndr->filled_mv_blocks_num == 0);
1269 assert(rndr->next_free_data_block_num == 0);
1271 mpi->flags |= MP_IMGFLAG_DIRECT;
1272 //keep strides 0 to avoid field manipulations
1273 mpi->stride[0] = 0;
1274 mpi->stride[1] = 0;
1275 mpi->stride[2] = 0;
1277 // these are shared!! so watch out
1278 // do call RenderSurface before overwriting
1279 mpi->planes[0] = (char*)data_blocks.blocks;
1280 mpi->planes[1] = (char*)mv_blocks.macro_blocks;
1281 mpi->priv =
1282 mpi->planes[2] = (char*)rndr;
1284 rndr->picture_structure = 0;
1285 rndr->flags = 0;
1286 rndr->state = 0;
1287 rndr->start_mv_blocks_num = 0;
1288 rndr->filled_mv_blocks_num = 0;
1289 rndr->next_free_data_block_num = 0;
1291 if( mp_msg_test(MSGT_VO,MSGL_DBG4) )
1292 printf("vo_xvmc: get_image: rndr=%p (surface=%p) \n",
1293 rndr,rndr->p_surface);
1294 return VO_TRUE;
1297 static int control(uint32_t request, void *data, ... )
1299 switch (request){
1300 case VOCTRL_GET_DEINTERLACE:
1301 *(int*)data = bob_deinterlace;
1302 return VO_TRUE;
1303 case VOCTRL_SET_DEINTERLACE:
1304 bob_deinterlace = *(int*)data;
1305 return VO_TRUE;
1306 case VOCTRL_QUERY_FORMAT:
1307 return query_format(*((uint32_t*)data));
1308 case VOCTRL_DRAW_IMAGE:
1309 return xvmc_draw_image((mp_image_t *)data);
1310 case VOCTRL_GET_IMAGE:
1311 return get_image((mp_image_t *)data);
1312 //vo_xv
1313 case VOCTRL_GUISUPPORT:
1314 return VO_TRUE;
1315 case VOCTRL_ONTOP:
1316 vo_x11_ontop();
1317 return VO_TRUE;
1318 case VOCTRL_FULLSCREEN:
1319 vo_x11_fullscreen();
1320 // indended, fallthrough to update panscan on fullscreen/windowed switch
1321 case VOCTRL_SET_PANSCAN:
1322 if ( ( vo_fs && ( vo_panscan != vo_panscan_amount ) ) || ( !vo_fs && vo_panscan_amount ) )
1324 int old_y = vo_panscan_y;
1325 panscan_calc();
1327 if(old_y != vo_panscan_y)
1329 //this also draws the colorkey
1330 put_xvmc_image(p_render_surface_visible,1);
1333 return VO_TRUE;
1334 case VOCTRL_GET_PANSCAN:
1335 if ( !vo_config_count || !vo_fs ) return VO_FALSE;
1336 return VO_TRUE;
1337 case VOCTRL_SET_EQUALIZER:
1339 va_list ap;
1340 int value;
1342 va_start(ap, data);
1343 value = va_arg(ap, int);
1344 va_end(ap);
1346 return vo_xv_set_eq(xv_port, data, value);
1349 case VOCTRL_GET_EQUALIZER:
1351 va_list ap;
1352 int *value;
1354 va_start(ap, data);
1355 value = va_arg(ap, int*);
1356 va_end(ap);
1358 return vo_xv_get_eq(xv_port, data, value);
1360 case VOCTRL_UPDATE_SCREENINFO:
1361 update_xinerama_info();
1362 return VO_TRUE;
1364 return VO_NOTIMPL;