2 #include "fastmemcpy.h"
16 #include "video_out.h"
17 #include "video_out_internal.h"
22 #include "libmpdemux/mpeg_packetizer.h"
25 #include "x11_common.h"
28 #include <dxr2ioctl.h>
31 extern float monitor_aspect
;
32 extern float movie_aspect
;
36 static int movie_w
,movie_h
;
37 static int playing
= 0;
39 // vo device used to blank the screen for the overlay init
40 static const vo_functions_t
* sub_vo
= NULL
;
42 static uint8_t* sub_img
= NULL
;
43 static int sub_x
,sub_y
,sub_w
,sub_h
;
44 static int sub_x_off
,sub_y_off
;
45 static int sub_config_count
;
47 static int sub_vo_win
= 0;
49 static int use_ol
= 1;
50 static int ol_ratio
= 1000;
51 static char *norm
= NULL
;
52 static char *ucode
= NULL
;
53 static int ar_mode
= DXR2_ASPECTRATIOMODE_LETTERBOX
;
54 static int mv_mode
= DXR2_MACROVISION_OFF
;
55 static int _75ire_mode
= DXR2_75IRE_OFF
;
56 static int bw_mode
= DXR2_BLACKWHITE_OFF
;
57 static int interlaced_mode
= DXR2_INTERLACED_ON
;
58 static int pixel_mode
= DXR2_PIXEL_CCIR601
;
59 static int iec958_mode
= DXR2_IEC958_DECODED
;
60 static int mute_mode
= DXR2_AUDIO_MUTE_OFF
;
61 static int ignore_cache
= 0;
62 static int update_cache
= 0;
63 static int olw_cor
= 0, olh_cor
= 0,olx_cor
= 0, oly_cor
= 0;
64 static int ol_osd
= 0;
65 static int ck_rmin
= 0x40;
66 static int ck_rmax
= 0xFF;
67 static int ck_r
= 0xFF;
68 static int ck_gmin
= 0x00;
69 static int ck_gmax
= 0x20;
71 static int ck_bmin
= 0x40;
72 static int ck_bmax
= 0xFF;
73 static int ck_b
= 0xFF;
74 static int cr_left
= 0, cr_right
= 0;
75 static int cr_top
= 55, cr_bot
= 300;
77 m_option_t dxr2_opts
[] = {
78 { "overlay", &use_ol
, CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
79 { "nooverlay", &use_ol
, CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
80 { "overlay-ratio", &ol_ratio
, CONF_TYPE_INT
, CONF_RANGE
, 1, 2500, NULL
},
81 { "ucode", &ucode
, CONF_TYPE_STRING
,0, 0, 0, NULL
},
83 { "norm", &norm
, CONF_TYPE_STRING
,0, 0, 0, NULL
},
85 { "ar-mode",&ar_mode
, CONF_TYPE_INT
, CONF_RANGE
,0,2,NULL
},
87 { "macrovision",&mv_mode
,CONF_TYPE_INT
,CONF_RANGE
,0,3, NULL
},
89 { "75ire",&_75ire_mode
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
90 { "no75ire",&_75ire_mode
,CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
92 { "bw",&bw_mode
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
93 { "color",&bw_mode
,CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
95 { "interlaced",&interlaced_mode
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
96 { "nointerlaced",&interlaced_mode
,CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
98 { "square-pixel",&pixel_mode
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
99 { "ccir601-pixel",&pixel_mode
,CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
101 { "iec958-encoded",&iec958_mode
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
102 { "iec958-decoded",&iec958_mode
,CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
104 { "mute", &mute_mode
,CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
105 { "nomute",&mute_mode
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
107 { "ignore-cache",&ignore_cache
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
108 { "update-cache",&update_cache
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
110 { "olh-cor", &olh_cor
, CONF_TYPE_INT
, CONF_RANGE
, -20, 20, NULL
},
111 { "olw-cor", &olw_cor
, CONF_TYPE_INT
, CONF_RANGE
, -20, 20, NULL
},
112 { "olx-cor", &olx_cor
, CONF_TYPE_INT
, CONF_RANGE
, -20, 20, NULL
},
113 { "oly-cor", &oly_cor
, CONF_TYPE_INT
, CONF_RANGE
, -20, 20, NULL
},
115 { "ol-osd", &ol_osd
, CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
116 { "nool-osd", &ol_osd
, CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
118 { "ck-rmin", &ck_rmin
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
119 { "ck-rmax", &ck_rmax
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
120 { "ck-r", &ck_r
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
121 { "ck-gmin", &ck_gmin
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
122 { "ck-gmax", &ck_gmax
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
123 { "ck-g", &ck_g
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
124 { "ck-bmin", &ck_bmin
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
125 { "ck-bmax", &ck_bmax
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
126 { "ck-b", &ck_b
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
127 { "cr-left", &cr_left
, CONF_TYPE_INT
, CONF_RANGE
, 0, 500, NULL
},
128 { "cr-right", &cr_right
, CONF_TYPE_INT
, CONF_RANGE
, 0, 500, NULL
},
129 { "cr-top", &cr_top
, CONF_TYPE_INT
, CONF_RANGE
, 0, 500, NULL
},
130 { "cr-bot", &cr_bot
, CONF_TYPE_INT
, CONF_RANGE
, 0, 500, NULL
},
132 { NULL
,NULL
, 0, 0, 0, 0, NULL
}
135 static const vo_info_t info
= {
138 "Alban Bedel <albeu@free.fr> and Tobias Diedrich <ranma@gmx.at>",
142 const LIBVO_EXTERN (dxr2
)
144 static char *ucodesearchpath
[] = {
145 "/usr/local/lib/dxr2/dvd12.ux",
146 "/usr/lib/dxr2/dvd12.ux",
151 #define BUF_SIZE 2048
153 static unsigned char dxr2buf
[BUF_SIZE
];
154 static unsigned int dxr2bufpos
= 0;
156 int write_dxr2(unsigned char *data
, int len
)
162 mp_msg (MSGT_VO
, MSGL_ERR
, "DXR2 fd is not valid\n");
166 while (len
>0) if ((dxr2bufpos
+len
) <= BUF_SIZE
) {
167 fast_memcpy(dxr2buf
+dxr2bufpos
, data
, len
);
171 int copylen
=BUF_SIZE
-dxr2bufpos
;
173 fast_memcpy(dxr2buf
+dxr2bufpos
, data
, copylen
);
174 dxr2bufpos
+= copylen
;
178 w
+= write(dxr2_fd
, dxr2buf
, BUF_SIZE
);
180 mp_msg(MSGT_VO
,MSGL_WARN
,"DXR2 : write failed : %s \n",strerror(errno
));
186 memmove(dxr2buf
,dxr2buf
+ w
,dxr2bufpos
);
192 static void flush_dxr2()
196 w
= write(dxr2_fd
, dxr2buf
, dxr2bufpos
);
198 mp_msg(MSGT_VO
,MSGL_WARN
,"DXR2 : write failed %s \n",strerror(errno
));
206 #define PACK_MAX_SIZE 2048
208 static unsigned char pack
[PACK_MAX_SIZE
];
210 static unsigned char mpg_eof
[]={
211 0x00, 0x00, 0x01, 0xb9
214 static void dxr2_send_eof(void)
216 write_dxr2(mpg_eof
, sizeof(mpg_eof
));
219 void dxr2_send_sub_packet(unsigned char* data
,int len
,int id
,unsigned int timestamp
) {
223 mp_msg(MSGT_VO
,MSGL_ERR
,"DXR2 fd is not valid\n");
227 if (((int) timestamp
)<0)
230 mp_msg(MSGT_VO
,MSGL_DBG2
,"dxr2_send_sub_packet(timestamp=%d)\n", timestamp
);
232 pack
[0]=pack
[1]=0;pack
[2]=0x01;
238 int payload_size
= PACK_MAX_SIZE
-(7+ptslen
+3);
239 if(payload_size
>len
) payload_size
= len
;
241 pack
[4]=(3+ptslen
+1+payload_size
)>>8;
242 pack
[5]=(3+ptslen
+1+payload_size
)&255;
249 // presentation time stamp:
250 x
=(0x02 << 4) | (((timestamp
>> 30) & 0x07) << 1) | 1;
252 x
=((((timestamp
>> 15) & 0x7fff) << 1) | 1);
253 pack
[10]=x
>>8; pack
[11]=x
&255;
254 x
=((((timestamp
) & 0x7fff) << 1) | 1);
255 pack
[12]=x
>>8; pack
[13]=x
&255;
262 write_dxr2(pack
,7+ptslen
+3);
263 write_dxr2(data
,payload_size
);
265 data
+= payload_size
;
270 static int dxr2_set_vga_params(dxr2_vgaParams_t
* vga
,int detect
) {
271 // Init the overlay, don't ask me how it work ;-)
281 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_CROPPING
, &crop
);
289 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_COLOUR
, &oc
);
292 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_RATIO
,&om
);
296 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_POSITION
,&win
);
298 win
.arg1
= vo_screenwidth
;
299 win
.arg2
= vo_screenheight
;
300 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_DIMENSION
,&win
);
303 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_IN_DELAY
,&om
);
306 // First we need a white screen
307 uint8_t* img
= malloc(vo_screenwidth
*vo_screenheight
*3);
308 uint8_t* src
[] = { img
, NULL
, NULL
};
309 int stride
[] = { vo_screenwidth
* 3 , 0, 0 };
310 int cc
= vo_config_count
;
312 memset(img
,255,vo_screenwidth
*vo_screenheight
*3);
313 vo_config_count
= sub_config_count
;
314 if(sub_vo
->config(vo_screenwidth
,vo_screenheight
,vo_screenwidth
,vo_screenheight
,
315 VOFLAG_FULLSCREEN
,"DXR2 sub vo",IMGFMT_BGR24
) != 0) {
316 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] sub vo config failed => No overlay\n");
320 vo_config_count
= cc
;
323 sub_vo
->draw_slice(src
,stride
,vo_screenwidth
,vo_screenheight
,0,0);
327 vo_config_count
= cc
;
329 om
.arg
= DXR2_OVERLAY_WINDOW_COLOUR_KEY
;
330 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_MODE
,&om
);
332 vga
->xScreen
= vo_screenwidth
;
333 vga
->yScreen
= vo_screenheight
;
334 vga
->hOffWinKey
= 100;
336 ioctl(dxr2_fd
, DXR2_IOC_CALCULATE_VGA_PARAMETERS
, vga
);
338 ioctl(dxr2_fd
, DXR2_IOC_SET_VGA_PARAMETERS
,vga
);
343 static int dxr2_save_vga_params(dxr2_vgaParams_t
* vga
,char* name
) {
345 char* p
= get_path("dxr2_cache");
346 int p_len
= strlen(p
), name_len
= strlen(name
);
347 char cache_path
[p_len
+ name_len
+ 2];
352 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] No vga cache dir found (%s)\n",strerror(errno
));
353 if(errno
== EACCES
) {
357 // Try to create the dir
358 if(mkdir(p
,S_IRWXU
) != 0) {
359 mp_msg(MSGT_VO
,MSGL_ERR
,"VO: [dxr2] Unable to create vga cache dir %s (%s)\n",p
,strerror(errno
));
364 sprintf(cache_path
,"%s/%s",p
,name
);
366 fd
= fopen(cache_path
,"w");
368 mp_msg(MSGT_VO
,MSGL_ERR
,"VO: [dxr2] Unable to open cache file %s for writing (%s)\n",cache_path
,strerror(errno
));
372 ret
= fprintf(fd
,"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
390 return ret
>= 11 ? 1 : 0;
393 static int dxr2_load_vga_params(dxr2_vgaParams_t
* vga
,char* name
) {
394 char* p
= get_path("dxr2_cache");
395 int p_len
= strlen(p
), name_len
= strlen(name
);
396 char cache_path
[p_len
+ name_len
+ 2];
401 sprintf(cache_path
,"%s/%s",p
,name
);
404 fd
= fopen(cache_path
,"r");
406 mp_msg(MSGT_VO
,MSGL_ERR
,"VO: [dxr2] Unable to open cache file %s for reading (%s)\n",cache_path
,strerror(errno
));
409 ret
= fscanf(fd
, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
427 if(ret
> 11 && !olx_cor
) olx_cor
= xc
;
428 if(ret
> 12 && !oly_cor
) oly_cor
= yc
;
429 if(ret
> 13 && !olw_cor
) olw_cor
= wc
;
430 if(ret
> 14 && !olh_cor
) olh_cor
= hc
;
431 return ret
>= 11 ? 1 : 0;
434 static int dxr2_setup_vga_params(void) {
435 const vo_info_t
* vi
= sub_vo
->info
;
436 dxr2_vgaParams_t vga
;
438 int loaded
= dxr2_load_vga_params(&vga
,(char*)vi
->short_name
);
439 if(!dxr2_set_vga_params(&vga
,(update_cache
|| ignore_cache
) ? 1 : !loaded
))
441 if(!loaded
|| update_cache
)
442 dxr2_save_vga_params(&vga
,(char*)vi
->short_name
);
446 static void dxr2_set_overlay_window(void) {
447 uint8_t* src
[] = { sub_img
, NULL
, NULL
};
448 int stride
[] = { movie_w
* 3 , 0, 0 };
451 int cc
= vo_config_count
;
452 vo_config_count
= sub_config_count
;
453 sub_vo
->draw_slice(src
,stride
,movie_w
,movie_h
,0,0);
455 vo_config_count
= cc
;
458 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] setting overlay with correction x=%d y=%d w=%d h=%d\n",olx_cor
,oly_cor
, olw_cor
,olh_cor
);
460 // Sub vo isn't a windowed one, fill in the needed stuff
463 vo_dwidth
= vo_screenwidth
;
464 vo_dheight
= vo_screenheight
;
468 vo_dheight
= movie_h
;
469 vo_dx
= (vo_screenwidth
- vo_dwidth
) / 2;
470 vo_dy
= (vo_screenheight
- vo_dheight
) / 2;
474 if(sub_w
!= vo_dwidth
|| sub_h
!= vo_dheight
) {
475 int new_aspect
= ((1<<16)*vo_dwidth
+ vo_dheight
/2)/vo_dheight
;
478 if(new_aspect
> aspect
)
479 sub_w
= (sub_h
*aspect
+ (1<<15))>>16;
481 sub_h
= ((sub_w
<<16) + (aspect
>>1)) /aspect
;
484 sub_x_off
= (vo_dwidth
-sub_w
) / 2;
485 sub_y_off
= (vo_dheight
-sub_h
) / 2;
486 sub_x
= -vo_dx
; // Be sure to also replace the overlay
489 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] set win size w=%d h=%d and offset x=%d y=%d \n",win
.arg1
,win
.arg2
,sub_x_off
,sub_y_off
);
490 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_DIMENSION
, &win
);
493 if(vo_dx
!= sub_x
|| vo_dy
!= sub_y
) {
494 sub_x
= vo_dx
+ olx_cor
+ sub_x_off
;
495 sub_y
= vo_dy
+ oly_cor
+ sub_y_off
;
496 win
.arg1
= (sub_x
> 0 ? sub_x
: 0);
497 win
.arg2
= (sub_y
> 0 ? sub_y
: 0);
498 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] set pos x=%d y=%d \n",win
.arg1
,win
.arg2
);
499 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_POSITION
,&win
);
504 static int config(uint32_t s_width
, uint32_t s_height
, uint32_t width
, uint32_t height
, uint32_t flags
, char *title
, uint32_t format
)
507 dxr2_threeArg_t arg3
;
510 mp_msg(MSGT_VO
,MSGL_ERR
,"DXR2 fd is not valid\n");
517 ioctl(dxr2_fd
, DXR2_IOC_STOP
, NULL
);
521 // Video stream setup
522 arg3
.arg1
= DXR2_STREAM_VIDEO
;
524 ioctl(dxr2_fd
, DXR2_IOC_SELECT_STREAM
, &arg3
);
526 arg3
.arg1
= DXR2_SRC_VIDEO_FREQ_30
;
527 else arg3
.arg1
= DXR2_SRC_VIDEO_FREQ_25
;
529 arg3
.arg3
= s_height
;
530 ioctl(dxr2_fd
, DXR2_IOC_SET_SOURCE_VIDEO_FORMAT
, &arg3
);
531 arg
= DXR2_BITSTREAM_TYPE_MPEG_VOB
;
532 ioctl(dxr2_fd
, DXR2_IOC_SET_BITSTREAM_TYPE
, &arg
);
535 if (1.76 <= movie_aspect
&& movie_aspect
<= 1.80) {
536 arg
= DXR2_ASPECTRATIO_16_9
;
537 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] source aspect ratio 16:9\n");
539 arg
= DXR2_ASPECTRATIO_4_3
;
540 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] source aspect ratio 4:3\n");
542 ioctl(dxr2_fd
, DXR2_IOC_SET_SOURCE_ASPECT_RATIO
, &arg
);
543 if (1.76 <= monitor_aspect
&& monitor_aspect
<=1.80) {
544 arg
= DXR2_ASPECTRATIO_16_9
;
545 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] monitor aspect ratio 16:9\n");
547 arg
= DXR2_ASPECTRATIO_4_3
;
548 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] monitor aspect ratio 4:3\n");
550 ioctl(dxr2_fd
, DXR2_IOC_SET_OUTPUT_ASPECT_RATIO
, &arg
);
553 ioctl(dxr2_fd
, DXR2_IOC_SET_ASPECT_RATIO_MODE
, &arg
);
557 ioctl(dxr2_fd
, DXR2_IOC_SET_TV_MACROVISION_MODE
, &arg
);
559 ioctl(dxr2_fd
, DXR2_IOC_SET_TV_75IRE_MODE
, &arg
);
561 ioctl(dxr2_fd
, DXR2_IOC_SET_TV_BLACKWHITE_MODE
, &arg
);
562 arg
= interlaced_mode
;
563 ioctl(dxr2_fd
, DXR2_IOC_SET_TV_INTERLACED_MODE
, &arg
);
565 ioctl(dxr2_fd
, DXR2_IOC_SET_TV_PIXEL_MODE
, &arg
);
568 if (strcmp(norm
, "ntsc")==0)
569 arg
= DXR2_OUTPUTFORMAT_NTSC
;
570 else if (strcmp(norm
, "pal")==0) {
572 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] you want pal, but we play at 30 fps, selecting pal60 instead\n");
573 arg
= DXR2_OUTPUTFORMAT_PAL_60
;
575 } else arg
= DXR2_OUTPUTFORMAT_PAL_BDGHI
;
576 } else if (strcmp(norm
, "pal60")==0) {
578 arg
= DXR2_OUTPUTFORMAT_PAL_60
;
580 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] you want pal60, but we play at 25 fps, selecting pal instead\n");
581 arg
= DXR2_OUTPUTFORMAT_PAL_BDGHI
;
584 } else if (strcmp(norm
, "palm")==0)
585 arg
= DXR2_OUTPUTFORMAT_PAL_M
;
586 else if (strcmp(norm
, "paln")==0)
587 arg
= DXR2_OUTPUTFORMAT_PAL_N
;
588 else if (strcmp(norm
, "palnc")==0)
589 arg
= DXR2_OUTPUTFORMAT_PAL_Nc
;
591 mp_msg(MSGT_VO
,MSGL_WARN
,"[dxr2] invalid norm %s\n", norm
);
592 mp_msg(MSGT_VO
,MSGL_WARN
,"Valid values are ntsc,pal,pal60,palm,paln,palnc\n");
593 mp_msg(MSGT_VO
,MSGL_WARN
,"Using ntsc\n");
598 arg
= DXR2_OUTPUTFORMAT_NTSC
;
601 arg
= DXR2_OUTPUTFORMAT_PAL_BDGHI
;
605 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] output norm set to %s\n", norm
);
606 ioctl(dxr2_fd
, DXR2_IOC_SET_TV_OUTPUT_FORMAT
, &arg
);
610 arg
= DXR2_SUBPICTURE_ON
;
611 ioctl(dxr2_fd
,DXR2_IOC_ENABLE_SUBPICTURE
,&arg
);
612 arg3
.arg1
= DXR2_STREAM_SUBPICTURE
;
614 ioctl(dxr2_fd
, DXR2_IOC_SELECT_STREAM
, &arg3
);
618 ioctl(dxr2_fd
, DXR2_IOC_IEC958_OUTPUT_MODE
, &arg
);
619 arg
= DXR2_AUDIO_WIDTH_16
;
620 ioctl(dxr2_fd
, DXR2_IOC_SET_AUDIO_DATA_WIDTH
, &arg
);
621 arg
= DXR2_AUDIO_FREQ_48
;
622 ioctl(dxr2_fd
, DXR2_IOC_SET_AUDIO_SAMPLE_FREQUENCY
, &arg
);
623 arg3
.arg1
= DXR2_STREAM_AUDIO_LPCM
;
625 ioctl(dxr2_fd
, DXR2_IOC_SELECT_STREAM
, &arg3
);
627 ioctl(dxr2_fd
, DXR2_IOC_SET_AUDIO_VOLUME
, &arg
);
629 ioctl(dxr2_fd
, DXR2_IOC_AUDIO_MUTE
, &arg
);
633 //vo_fs = flags & VOFLAG_FULLSCREEN ? 1 : 0;
638 int cc
= vo_config_count
;
639 vo_config_count
= sub_config_count
;
640 // Load or detect the overlay stuff
641 if(!dxr2_setup_vga_params()) {
644 vo_config_count
= cc
;
647 // Does the sub vo support the x11 stuff
648 // Fix me : test the other x11 vo's and enable them
649 if(strcmp(sub_vo
->info
->short_name
,"x11") == 0)
654 // No window and no osd => we don't need any subdriver
655 if(!sub_vo_win
&& !ol_osd
) {
662 int i
,sub_flags
= VOFLAG_SWSCALE
| (flags
& VOFLAG_FULLSCREEN
);
663 if(sub_vo
->config(width
,height
,width
,height
,sub_flags
,
664 "MPlayer DXR2 render",IMGFMT_BGR24
) != 0) {
665 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] sub vo config failed => No X11 window\n");
672 // Feel free to try some other other color and report your results
679 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_COLOUR
, &oc
);
681 om
.arg
= DXR2_OVERLAY_WINDOW_COLOUR_KEY
;
682 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_MODE
,&om
);
683 sub_img
= malloc(width
*height
*3);
684 for(i
= 0 ; i
< width
*height
*3 ; i
+= 3) {
689 aspect
= ((1<<16)*width
+ height
/2)/height
;
691 dxr2_set_overlay_window();
694 vo_config_count
= cc
;
695 if(!sub_vo
) { // Fallback on non windowed overlay
696 vo_fs
= flags
& VOFLAG_FULLSCREEN
? 1 : 0;
697 om
.arg
= DXR2_OVERLAY_WINDOW_KEY
;
698 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_MODE
,&om
);
699 win
.arg1
= flags
& VOFLAG_FULLSCREEN
? vo_screenwidth
: width
;
700 win
.arg2
= flags
& VOFLAG_FULLSCREEN
? vo_screenheight
: height
;
701 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_DIMENSION
, &win
);
702 win
.arg1
= (vo_screenwidth
- win
.arg1
) / 2;
703 win
.arg2
= (vo_screenheight
- win
.arg2
) / 2;
704 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_POSITION
,&win
);
709 if (vo_ontop
) vo_x11_setlayer(mDisplay
, vo_window
, vo_ontop
);
712 if(ioctl(dxr2_fd
, DXR2_IOC_PLAY
, NULL
) == 0) {
719 static void clear_alpha(int x0
,int y0
, int w
,int h
) {
720 uint8_t* src
[] = { sub_img
, NULL
, NULL
};
721 int stride
[] = { movie_w
* 3, 0, 0 };
723 sub_vo
->draw_slice(src
,stride
,w
,h
,x0
,y0
);
726 static void draw_osd(void)
728 if(sub_vo
&& ol_osd
) {
729 vo_remove_text(movie_w
,movie_h
,clear_alpha
);
734 static int draw_frame(uint8_t * src
[])
736 vo_mpegpes_t
*p
=(vo_mpegpes_t
*)src
[0];
738 if(p
->id
== 0x1E0) {// Video
739 send_mpeg_ps_packet (p
->data
, p
->size
, p
->id
,
740 p
->timestamp
? p
->timestamp
: vo_pts
, 2, write_dxr2
);
741 } else if(p
->id
== 0x20) // Subtitles
742 dxr2_send_sub_packet(p
->data
, p
->size
, p
->id
, p
->timestamp
);
746 static void flip_page (void)
748 if(sub_vo
&& ol_osd
&& vo_osd_changed_flag
)
752 static int draw_slice( uint8_t *srcimg
[], int stride
[], int w
, int h
, int x0
, int y0
)
758 static int query_format(uint32_t format
)
760 if (format
==IMGFMT_MPEGPES
)
761 return VFCAP_CSP_SUPPORTED
|VFCAP_CSP_SUPPORTED_BY_HW
|VFCAP_TIMER
|VFCAP_SPU
;
766 static void uninit(void)
768 mp_msg(MSGT_VO
,MSGL_DBG2
, "VO: [dxr2] Uninitializing\n" );
784 int cc
= vo_config_count
;
785 vo_config_count
= sub_config_count
;
788 vo_config_count
= cc
;
793 static void check_events(void)
795 // I'd like to have this done in an x11 independent way
796 // It's because of this that we are limited to vo_x11 for windowed overlay :-(
797 #ifdef X11_FULLSCREEN
798 if(sub_vo
&& sub_vo_win
) {
799 int e
=vo_x11_check_events(mDisplay
);
800 if ( !(e
&VO_EVENT_RESIZE
) && !(e
&VO_EVENT_EXPOSE
) ) return;
801 XSetBackground(mDisplay
, vo_gc
, 0);
802 XClearWindow(mDisplay
, vo_window
);
803 dxr2_set_overlay_window();
808 static int preinit(const char *arg
) {
816 sub_config_count
= 0;
819 for(n
= 0 ; video_out_drivers
[n
] != NULL
; n
++) {
820 const vo_info_t
* vi
= video_out_drivers
[n
]->info
;
823 if(strcasecmp(arg
,vi
->short_name
) == 0)
826 sub_vo
= video_out_drivers
[n
];
828 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] We need a sub driver to initialize the overlay\n");
835 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] Sub driver '%s' not found => no overlay\n",arg
);
838 if(sub_vo
->preinit(NULL
) != 0) {
839 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] Sub vo %s preinit failed => no overlay\n",arg
);
843 uint32_t fmt
= IMGFMT_BGR24
;
844 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] Sub vo %s inited\n",arg
);
845 if(sub_vo
->control(VOCTRL_QUERY_FORMAT
,&fmt
) <= 0) {
846 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] Sub vo %s doesn't support BGR24 => no overlay\n",arg
);
854 dxr2_fd
= open( "/dev/dxr2", O_WRONLY
);
856 mp_msg(MSGT_VO
,MSGL_V
, "VO: [dxr2] Error opening /dev/dxr2 for writing!\n" );
861 uCodeFD
= open(ucode
, O_RDONLY
);
862 else for (n
=0; ucodesearchpath
[n
] != NULL
; n
++) {
863 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] Looking for microcode in %s... ",
865 if ((uCodeFD
= open(ucodesearchpath
[n
], O_RDONLY
))>0) {
866 mp_msg(MSGT_VO
,MSGL_V
,"ok\n");
869 mp_msg(MSGT_VO
,MSGL_V
,"failed (%s)\n", strerror(errno
));
873 mp_msg(MSGT_VO
,MSGL_ERR
,"VO: [dxr2] Could not open microcode\n");
877 uCodeSize
= lseek(uCodeFD
, 0, SEEK_END
);
878 if ((uCode
= malloc(uCodeSize
+ 4)) == NULL
) {
880 mp_msg(MSGT_VO
,MSGL_FATAL
,"VO: [dxr2] Could not allocate memory for uCode: %s\n", strerror(errno
));
883 lseek(uCodeFD
, 0, SEEK_SET
);
884 if (read(uCodeFD
, uCode
+4, uCodeSize
) != uCodeSize
) {
886 mp_msg(MSGT_VO
,MSGL_ERR
,"VO: [dxr2] Could not read uCode uCode: %s\n", strerror(errno
));
890 uCode
->uCodeLength
= uCodeSize
;
893 ioctl(dxr2_fd
, DXR2_IOC_INIT_ZIVADS
, uCode
);
896 ioctl(dxr2_fd
, DXR2_IOC_RESET
, NULL
);
904 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_CROPPING
, &crop
);
909 static int control(uint32_t request
, void *data
, ...)
912 case VOCTRL_QUERY_FORMAT
:
913 return query_format(*((uint32_t*)data
));
915 ioctl(dxr2_fd
,DXR2_IOC_PAUSE
, NULL
);
918 ioctl(dxr2_fd
, DXR2_IOC_PLAY
, NULL
);
922 ioctl(dxr2_fd
, DXR2_IOC_PLAY
, NULL
);
927 case VOCTRL_FULLSCREEN
:
931 int r
= sub_vo
->control(VOCTRL_FULLSCREEN
,0);
932 if(r
== VO_TRUE
&& !sub_vo_win
)
933 dxr2_set_overlay_window();
938 win
.arg1
= vo_fs
? vo_screenwidth
: movie_w
;
939 win
.arg2
= vo_fs
? vo_screenheight
: movie_h
;
940 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_DIMENSION
, &win
);
941 win
.arg1
= (vo_screenwidth
- win
.arg1
) / 2;
942 win
.arg2
= (vo_screenheight
- win
.arg2
) / 2;
943 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_POSITION
,&win
);
946 case VOCTRL_SET_SPU_PALETTE
: {
947 if(ioctl(dxr2_fd
,DXR2_IOC_SET_SUBPICTURE_PALETTE
,data
) < 0) {
948 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] SPU palette loading failed\n");