2 #include "fastmemcpy.h"
16 #include "video_out.h"
17 #include "video_out_internal.h"
22 #include "libmpdemux/mpeg_packetizer.h"
23 #include "x11_common.h"
25 #include <dxr2ioctl.h>
28 extern float monitor_aspect
;
29 extern float movie_aspect
;
33 static int movie_w
,movie_h
;
34 static int playing
= 0;
36 // vo device used to blank the screen for the overlay init
37 static const vo_functions_t
* sub_vo
= NULL
;
39 static uint8_t* sub_img
= NULL
;
40 static int sub_x
,sub_y
,sub_w
,sub_h
;
41 static int sub_x_off
,sub_y_off
;
42 static int sub_config_count
;
44 static int sub_vo_win
= 0;
46 static int use_ol
= 1;
47 static int ol_ratio
= 1000;
48 static char *norm
= NULL
;
49 static char *ucode
= NULL
;
50 static int ar_mode
= DXR2_ASPECTRATIOMODE_LETTERBOX
;
51 static int mv_mode
= DXR2_MACROVISION_OFF
;
52 static int _75ire_mode
= DXR2_75IRE_OFF
;
53 static int bw_mode
= DXR2_BLACKWHITE_OFF
;
54 static int interlaced_mode
= DXR2_INTERLACED_ON
;
55 static int pixel_mode
= DXR2_PIXEL_CCIR601
;
56 static int iec958_mode
= DXR2_IEC958_DECODED
;
57 static int mute_mode
= DXR2_AUDIO_MUTE_OFF
;
58 static int ignore_cache
= 0;
59 static int update_cache
= 0;
60 static int olw_cor
= 0, olh_cor
= 0,olx_cor
= 0, oly_cor
= 0;
61 static int ol_osd
= 0;
62 static int ck_rmin
= 0x40;
63 static int ck_rmax
= 0xFF;
64 static int ck_r
= 0xFF;
65 static int ck_gmin
= 0x00;
66 static int ck_gmax
= 0x20;
68 static int ck_bmin
= 0x40;
69 static int ck_bmax
= 0xFF;
70 static int ck_b
= 0xFF;
71 static int cr_left
= 0, cr_right
= 0;
72 static int cr_top
= 55, cr_bot
= 300;
74 m_option_t dxr2_opts
[] = {
75 { "overlay", &use_ol
, CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
76 { "nooverlay", &use_ol
, CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
77 { "overlay-ratio", &ol_ratio
, CONF_TYPE_INT
, CONF_RANGE
, 1, 2500, NULL
},
78 { "ucode", &ucode
, CONF_TYPE_STRING
,0, 0, 0, NULL
},
80 { "norm", &norm
, CONF_TYPE_STRING
,0, 0, 0, NULL
},
82 { "ar-mode",&ar_mode
, CONF_TYPE_INT
, CONF_RANGE
,0,2,NULL
},
84 { "macrovision",&mv_mode
,CONF_TYPE_INT
,CONF_RANGE
,0,3, NULL
},
86 { "75ire",&_75ire_mode
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
87 { "no75ire",&_75ire_mode
,CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
89 { "bw",&bw_mode
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
90 { "color",&bw_mode
,CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
92 { "interlaced",&interlaced_mode
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
93 { "nointerlaced",&interlaced_mode
,CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
95 { "square-pixel",&pixel_mode
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
96 { "ccir601-pixel",&pixel_mode
,CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
98 { "iec958-encoded",&iec958_mode
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
99 { "iec958-decoded",&iec958_mode
,CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
101 { "mute", &mute_mode
,CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
102 { "nomute",&mute_mode
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
104 { "ignore-cache",&ignore_cache
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
105 { "update-cache",&update_cache
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
107 { "olh-cor", &olh_cor
, CONF_TYPE_INT
, CONF_RANGE
, -20, 20, NULL
},
108 { "olw-cor", &olw_cor
, CONF_TYPE_INT
, CONF_RANGE
, -20, 20, NULL
},
109 { "olx-cor", &olx_cor
, CONF_TYPE_INT
, CONF_RANGE
, -20, 20, NULL
},
110 { "oly-cor", &oly_cor
, CONF_TYPE_INT
, CONF_RANGE
, -20, 20, NULL
},
112 { "ol-osd", &ol_osd
, CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
113 { "nool-osd", &ol_osd
, CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
115 { "ck-rmin", &ck_rmin
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
116 { "ck-rmax", &ck_rmax
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
117 { "ck-r", &ck_r
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
118 { "ck-gmin", &ck_gmin
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
119 { "ck-gmax", &ck_gmax
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
120 { "ck-g", &ck_g
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
121 { "ck-bmin", &ck_bmin
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
122 { "ck-bmax", &ck_bmax
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
123 { "ck-b", &ck_b
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
124 { "cr-left", &cr_left
, CONF_TYPE_INT
, CONF_RANGE
, 0, 500, NULL
},
125 { "cr-right", &cr_right
, CONF_TYPE_INT
, CONF_RANGE
, 0, 500, NULL
},
126 { "cr-top", &cr_top
, CONF_TYPE_INT
, CONF_RANGE
, 0, 500, NULL
},
127 { "cr-bot", &cr_bot
, CONF_TYPE_INT
, CONF_RANGE
, 0, 500, NULL
},
129 { NULL
,NULL
, 0, 0, 0, 0, NULL
}
132 static const vo_info_t info
= {
135 "Alban Bedel <albeu@free.fr> and Tobias Diedrich <ranma@gmx.at>",
139 const LIBVO_EXTERN (dxr2
)
141 static char *ucodesearchpath
[] = {
142 "/usr/local/lib/dxr2/dvd12.ux",
143 "/usr/lib/dxr2/dvd12.ux",
148 #define BUF_SIZE 2048
150 static unsigned char dxr2buf
[BUF_SIZE
];
151 static unsigned int dxr2bufpos
= 0;
153 int write_dxr2(const unsigned char *data
, int len
)
159 mp_msg (MSGT_VO
, MSGL_ERR
, "DXR2 fd is not valid\n");
163 while (len
>0) if ((dxr2bufpos
+len
) <= BUF_SIZE
) {
164 fast_memcpy(dxr2buf
+dxr2bufpos
, data
, len
);
168 int copylen
=BUF_SIZE
-dxr2bufpos
;
170 fast_memcpy(dxr2buf
+dxr2bufpos
, data
, copylen
);
171 dxr2bufpos
+= copylen
;
175 w
+= write(dxr2_fd
, dxr2buf
, BUF_SIZE
);
177 mp_msg(MSGT_VO
,MSGL_WARN
,"DXR2 : write failed : %s \n",strerror(errno
));
183 memmove(dxr2buf
,dxr2buf
+ w
,dxr2bufpos
);
189 static void flush_dxr2()
193 w
= write(dxr2_fd
, dxr2buf
, dxr2bufpos
);
195 mp_msg(MSGT_VO
,MSGL_WARN
,"DXR2 : write failed %s \n",strerror(errno
));
203 #define PACK_MAX_SIZE 2048
205 static unsigned char pack
[PACK_MAX_SIZE
];
207 static unsigned char mpg_eof
[]={
208 0x00, 0x00, 0x01, 0xb9
211 static void dxr2_send_eof(void)
213 write_dxr2(mpg_eof
, sizeof(mpg_eof
));
216 void dxr2_send_sub_packet(unsigned char* data
,int len
,int id
,unsigned int timestamp
) {
220 mp_msg(MSGT_VO
,MSGL_ERR
,"DXR2 fd is not valid\n");
224 if (((int) timestamp
)<0)
227 mp_msg(MSGT_VO
,MSGL_DBG2
,"dxr2_send_sub_packet(timestamp=%d)\n", timestamp
);
229 pack
[0]=pack
[1]=0;pack
[2]=0x01;
235 int payload_size
= PACK_MAX_SIZE
-(7+ptslen
+3);
236 if(payload_size
>len
) payload_size
= len
;
238 pack
[4]=(3+ptslen
+1+payload_size
)>>8;
239 pack
[5]=(3+ptslen
+1+payload_size
)&255;
246 // presentation time stamp:
247 x
=(0x02 << 4) | (((timestamp
>> 30) & 0x07) << 1) | 1;
249 x
=((((timestamp
>> 15) & 0x7fff) << 1) | 1);
250 pack
[10]=x
>>8; pack
[11]=x
&255;
251 x
=((((timestamp
) & 0x7fff) << 1) | 1);
252 pack
[12]=x
>>8; pack
[13]=x
&255;
259 write_dxr2(pack
,7+ptslen
+3);
260 write_dxr2(data
,payload_size
);
262 data
+= payload_size
;
267 static int dxr2_set_vga_params(dxr2_vgaParams_t
* vga
,int detect
) {
268 // Init the overlay, don't ask me how it work ;-)
278 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_CROPPING
, &crop
);
286 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_COLOUR
, &oc
);
289 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_RATIO
,&om
);
293 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_POSITION
,&win
);
295 win
.arg1
= vo_screenwidth
;
296 win
.arg2
= vo_screenheight
;
297 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_DIMENSION
,&win
);
300 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_IN_DELAY
,&om
);
303 // First we need a white screen
304 uint8_t* img
= malloc(vo_screenwidth
*vo_screenheight
*3);
305 uint8_t* src
[] = { img
, NULL
, NULL
};
306 int stride
[] = { vo_screenwidth
* 3 , 0, 0 };
307 int cc
= vo_config_count
;
309 memset(img
,255,vo_screenwidth
*vo_screenheight
*3);
310 vo_config_count
= sub_config_count
;
311 if(sub_vo
->config(vo_screenwidth
,vo_screenheight
,vo_screenwidth
,vo_screenheight
,
312 VOFLAG_FULLSCREEN
,"DXR2 sub vo",IMGFMT_BGR24
) != 0) {
313 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] sub vo config failed => No overlay\n");
317 vo_config_count
= cc
;
320 sub_vo
->draw_slice(src
,stride
,vo_screenwidth
,vo_screenheight
,0,0);
324 vo_config_count
= cc
;
326 om
.arg
= DXR2_OVERLAY_WINDOW_COLOUR_KEY
;
327 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_MODE
,&om
);
329 vga
->xScreen
= vo_screenwidth
;
330 vga
->yScreen
= vo_screenheight
;
331 vga
->hOffWinKey
= 100;
333 ioctl(dxr2_fd
, DXR2_IOC_CALCULATE_VGA_PARAMETERS
, vga
);
335 ioctl(dxr2_fd
, DXR2_IOC_SET_VGA_PARAMETERS
,vga
);
340 static int dxr2_save_vga_params(dxr2_vgaParams_t
* vga
,char* name
) {
342 char* p
= get_path("dxr2_cache");
343 int p_len
= strlen(p
), name_len
= strlen(name
);
344 char cache_path
[p_len
+ name_len
+ 2];
349 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] No vga cache dir found (%s)\n",strerror(errno
));
350 if(errno
== EACCES
) {
354 // Try to create the dir
355 if(mkdir(p
,S_IRWXU
) != 0) {
356 mp_msg(MSGT_VO
,MSGL_ERR
,"VO: [dxr2] Unable to create vga cache dir %s (%s)\n",p
,strerror(errno
));
361 sprintf(cache_path
,"%s/%s",p
,name
);
363 fd
= fopen(cache_path
,"w");
365 mp_msg(MSGT_VO
,MSGL_ERR
,"VO: [dxr2] Unable to open cache file %s for writing (%s)\n",cache_path
,strerror(errno
));
369 ret
= fprintf(fd
,"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
387 return ret
>= 11 ? 1 : 0;
390 static int dxr2_load_vga_params(dxr2_vgaParams_t
* vga
,char* name
) {
391 char* p
= get_path("dxr2_cache");
392 int p_len
= strlen(p
), name_len
= strlen(name
);
393 char cache_path
[p_len
+ name_len
+ 2];
398 sprintf(cache_path
,"%s/%s",p
,name
);
401 fd
= fopen(cache_path
,"r");
403 mp_msg(MSGT_VO
,MSGL_ERR
,"VO: [dxr2] Unable to open cache file %s for reading (%s)\n",cache_path
,strerror(errno
));
406 ret
= fscanf(fd
, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
424 if(ret
> 11 && !olx_cor
) olx_cor
= xc
;
425 if(ret
> 12 && !oly_cor
) oly_cor
= yc
;
426 if(ret
> 13 && !olw_cor
) olw_cor
= wc
;
427 if(ret
> 14 && !olh_cor
) olh_cor
= hc
;
428 return ret
>= 11 ? 1 : 0;
431 static int dxr2_setup_vga_params(void) {
432 const vo_info_t
* vi
= sub_vo
->info
;
433 dxr2_vgaParams_t vga
;
435 int loaded
= dxr2_load_vga_params(&vga
,(char*)vi
->short_name
);
436 if(!dxr2_set_vga_params(&vga
,(update_cache
|| ignore_cache
) ? 1 : !loaded
))
438 if(!loaded
|| update_cache
)
439 dxr2_save_vga_params(&vga
,(char*)vi
->short_name
);
443 static void dxr2_set_overlay_window(void) {
444 uint8_t* src
[] = { sub_img
, NULL
, NULL
};
445 int stride
[] = { movie_w
* 3 , 0, 0 };
448 int cc
= vo_config_count
;
449 vo_config_count
= sub_config_count
;
450 sub_vo
->draw_slice(src
,stride
,movie_w
,movie_h
,0,0);
452 vo_config_count
= cc
;
455 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
);
457 // Sub vo isn't a windowed one, fill in the needed stuff
460 vo_dwidth
= vo_screenwidth
;
461 vo_dheight
= vo_screenheight
;
465 vo_dheight
= movie_h
;
466 vo_dx
= (vo_screenwidth
- vo_dwidth
) / 2;
467 vo_dy
= (vo_screenheight
- vo_dheight
) / 2;
471 if(sub_w
!= vo_dwidth
|| sub_h
!= vo_dheight
) {
472 int new_aspect
= ((1<<16)*vo_dwidth
+ vo_dheight
/2)/vo_dheight
;
475 if(new_aspect
> aspect
)
476 sub_w
= (sub_h
*aspect
+ (1<<15))>>16;
478 sub_h
= ((sub_w
<<16) + (aspect
>>1)) /aspect
;
481 sub_x_off
= (vo_dwidth
-sub_w
) / 2;
482 sub_y_off
= (vo_dheight
-sub_h
) / 2;
483 sub_x
= -vo_dx
; // Be sure to also replace the overlay
486 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
);
487 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_DIMENSION
, &win
);
490 if(vo_dx
!= sub_x
|| vo_dy
!= sub_y
) {
491 sub_x
= vo_dx
+ olx_cor
+ sub_x_off
;
492 sub_y
= vo_dy
+ oly_cor
+ sub_y_off
;
493 win
.arg1
= (sub_x
> 0 ? sub_x
: 0);
494 win
.arg2
= (sub_y
> 0 ? sub_y
: 0);
495 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] set pos x=%d y=%d \n",win
.arg1
,win
.arg2
);
496 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_POSITION
,&win
);
501 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
)
504 dxr2_threeArg_t arg3
;
507 mp_msg(MSGT_VO
,MSGL_ERR
,"DXR2 fd is not valid\n");
514 ioctl(dxr2_fd
, DXR2_IOC_STOP
, NULL
);
518 // Video stream setup
519 arg3
.arg1
= DXR2_STREAM_VIDEO
;
521 ioctl(dxr2_fd
, DXR2_IOC_SELECT_STREAM
, &arg3
);
523 arg3
.arg1
= DXR2_SRC_VIDEO_FREQ_30
;
524 else arg3
.arg1
= DXR2_SRC_VIDEO_FREQ_25
;
526 arg3
.arg3
= s_height
;
527 ioctl(dxr2_fd
, DXR2_IOC_SET_SOURCE_VIDEO_FORMAT
, &arg3
);
528 arg
= DXR2_BITSTREAM_TYPE_MPEG_VOB
;
529 ioctl(dxr2_fd
, DXR2_IOC_SET_BITSTREAM_TYPE
, &arg
);
532 if (1.76 <= movie_aspect
&& movie_aspect
<= 1.80) {
533 arg
= DXR2_ASPECTRATIO_16_9
;
534 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] source aspect ratio 16:9\n");
536 arg
= DXR2_ASPECTRATIO_4_3
;
537 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] source aspect ratio 4:3\n");
539 ioctl(dxr2_fd
, DXR2_IOC_SET_SOURCE_ASPECT_RATIO
, &arg
);
540 if (1.76 <= monitor_aspect
&& monitor_aspect
<=1.80) {
541 arg
= DXR2_ASPECTRATIO_16_9
;
542 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] monitor aspect ratio 16:9\n");
544 arg
= DXR2_ASPECTRATIO_4_3
;
545 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] monitor aspect ratio 4:3\n");
547 ioctl(dxr2_fd
, DXR2_IOC_SET_OUTPUT_ASPECT_RATIO
, &arg
);
550 ioctl(dxr2_fd
, DXR2_IOC_SET_ASPECT_RATIO_MODE
, &arg
);
554 ioctl(dxr2_fd
, DXR2_IOC_SET_TV_MACROVISION_MODE
, &arg
);
556 ioctl(dxr2_fd
, DXR2_IOC_SET_TV_75IRE_MODE
, &arg
);
558 ioctl(dxr2_fd
, DXR2_IOC_SET_TV_BLACKWHITE_MODE
, &arg
);
559 arg
= interlaced_mode
;
560 ioctl(dxr2_fd
, DXR2_IOC_SET_TV_INTERLACED_MODE
, &arg
);
562 ioctl(dxr2_fd
, DXR2_IOC_SET_TV_PIXEL_MODE
, &arg
);
565 if (strcmp(norm
, "ntsc")==0)
566 arg
= DXR2_OUTPUTFORMAT_NTSC
;
567 else if (strcmp(norm
, "pal")==0) {
569 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] you want pal, but we play at 30 fps, selecting pal60 instead\n");
570 arg
= DXR2_OUTPUTFORMAT_PAL_60
;
572 } else arg
= DXR2_OUTPUTFORMAT_PAL_BDGHI
;
573 } else if (strcmp(norm
, "pal60")==0) {
575 arg
= DXR2_OUTPUTFORMAT_PAL_60
;
577 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] you want pal60, but we play at 25 fps, selecting pal instead\n");
578 arg
= DXR2_OUTPUTFORMAT_PAL_BDGHI
;
581 } else if (strcmp(norm
, "palm")==0)
582 arg
= DXR2_OUTPUTFORMAT_PAL_M
;
583 else if (strcmp(norm
, "paln")==0)
584 arg
= DXR2_OUTPUTFORMAT_PAL_N
;
585 else if (strcmp(norm
, "palnc")==0)
586 arg
= DXR2_OUTPUTFORMAT_PAL_Nc
;
588 mp_msg(MSGT_VO
,MSGL_WARN
,"[dxr2] invalid norm %s\n", norm
);
589 mp_msg(MSGT_VO
,MSGL_WARN
,"Valid values are ntsc,pal,pal60,palm,paln,palnc\n");
590 mp_msg(MSGT_VO
,MSGL_WARN
,"Using ntsc\n");
595 arg
= DXR2_OUTPUTFORMAT_NTSC
;
598 arg
= DXR2_OUTPUTFORMAT_PAL_BDGHI
;
602 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] output norm set to %s\n", norm
);
603 ioctl(dxr2_fd
, DXR2_IOC_SET_TV_OUTPUT_FORMAT
, &arg
);
607 arg
= DXR2_SUBPICTURE_ON
;
608 ioctl(dxr2_fd
,DXR2_IOC_ENABLE_SUBPICTURE
,&arg
);
609 arg3
.arg1
= DXR2_STREAM_SUBPICTURE
;
611 ioctl(dxr2_fd
, DXR2_IOC_SELECT_STREAM
, &arg3
);
615 ioctl(dxr2_fd
, DXR2_IOC_IEC958_OUTPUT_MODE
, &arg
);
616 arg
= DXR2_AUDIO_WIDTH_16
;
617 ioctl(dxr2_fd
, DXR2_IOC_SET_AUDIO_DATA_WIDTH
, &arg
);
618 arg
= DXR2_AUDIO_FREQ_48
;
619 ioctl(dxr2_fd
, DXR2_IOC_SET_AUDIO_SAMPLE_FREQUENCY
, &arg
);
620 arg3
.arg1
= DXR2_STREAM_AUDIO_LPCM
;
622 ioctl(dxr2_fd
, DXR2_IOC_SELECT_STREAM
, &arg3
);
624 ioctl(dxr2_fd
, DXR2_IOC_SET_AUDIO_VOLUME
, &arg
);
626 ioctl(dxr2_fd
, DXR2_IOC_AUDIO_MUTE
, &arg
);
630 //vo_fs = flags & VOFLAG_FULLSCREEN ? 1 : 0;
635 int cc
= vo_config_count
;
636 vo_config_count
= sub_config_count
;
637 // Load or detect the overlay stuff
638 if(!dxr2_setup_vga_params()) {
641 vo_config_count
= cc
;
644 // Does the sub vo support the x11 stuff
645 // Fix me : test the other x11 vo's and enable them
646 if(strcmp(sub_vo
->info
->short_name
,"x11") == 0)
651 // No window and no osd => we don't need any subdriver
652 if(!sub_vo_win
&& !ol_osd
) {
659 int i
,sub_flags
= VOFLAG_SWSCALE
| (flags
& VOFLAG_FULLSCREEN
);
660 if(sub_vo
->config(width
,height
,width
,height
,sub_flags
,
661 "MPlayer DXR2 render",IMGFMT_BGR24
) != 0) {
662 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] sub vo config failed => No X11 window\n");
669 // Feel free to try some other other color and report your results
676 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_COLOUR
, &oc
);
678 om
.arg
= DXR2_OVERLAY_WINDOW_COLOUR_KEY
;
679 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_MODE
,&om
);
680 sub_img
= malloc(width
*height
*3);
681 for(i
= 0 ; i
< width
*height
*3 ; i
+= 3) {
686 aspect
= ((1<<16)*width
+ height
/2)/height
;
688 dxr2_set_overlay_window();
691 vo_config_count
= cc
;
692 if(!sub_vo
) { // Fallback on non windowed overlay
693 vo_fs
= flags
& VOFLAG_FULLSCREEN
? 1 : 0;
694 om
.arg
= DXR2_OVERLAY_WINDOW_KEY
;
695 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_MODE
,&om
);
696 win
.arg1
= flags
& VOFLAG_FULLSCREEN
? vo_screenwidth
: width
;
697 win
.arg2
= flags
& VOFLAG_FULLSCREEN
? vo_screenheight
: height
;
698 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_DIMENSION
, &win
);
699 win
.arg1
= (vo_screenwidth
- win
.arg1
) / 2;
700 win
.arg2
= (vo_screenheight
- win
.arg2
) / 2;
701 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_POSITION
,&win
);
706 if (vo_ontop
) vo_x11_setlayer(mDisplay
, vo_window
, vo_ontop
);
709 if(ioctl(dxr2_fd
, DXR2_IOC_PLAY
, NULL
) == 0) {
716 static void clear_alpha(int x0
,int y0
, int w
,int h
) {
717 uint8_t* src
[] = { sub_img
, NULL
, NULL
};
718 int stride
[] = { movie_w
* 3, 0, 0 };
720 sub_vo
->draw_slice(src
,stride
,w
,h
,x0
,y0
);
723 static void draw_osd(void)
725 if(sub_vo
&& ol_osd
) {
726 vo_remove_text(movie_w
,movie_h
,clear_alpha
);
731 static int draw_frame(uint8_t * src
[])
733 vo_mpegpes_t
*p
=(vo_mpegpes_t
*)src
[0];
735 if(p
->id
== 0x1E0) {// Video
736 send_mpeg_ps_packet (p
->data
, p
->size
, p
->id
,
737 p
->timestamp
? p
->timestamp
: vo_pts
, 2, write_dxr2
);
738 } else if(p
->id
== 0x20) // Subtitles
739 dxr2_send_sub_packet(p
->data
, p
->size
, p
->id
, p
->timestamp
);
743 static void flip_page (void)
745 if(sub_vo
&& ol_osd
&& vo_osd_changed_flag
)
749 static int draw_slice( uint8_t *srcimg
[], int stride
[], int w
, int h
, int x0
, int y0
)
755 static int query_format(uint32_t format
)
757 if (format
==IMGFMT_MPEGPES
)
758 return VFCAP_CSP_SUPPORTED
|VFCAP_CSP_SUPPORTED_BY_HW
|VFCAP_TIMER
|VFCAP_SPU
;
763 static void uninit(void)
765 mp_msg(MSGT_VO
,MSGL_DBG2
, "VO: [dxr2] Uninitializing\n" );
781 int cc
= vo_config_count
;
782 vo_config_count
= sub_config_count
;
785 vo_config_count
= cc
;
790 static void check_events(void)
792 // I'd like to have this done in an x11 independent way
793 // It's because of this that we are limited to vo_x11 for windowed overlay :-(
794 #ifdef X11_FULLSCREEN
795 if(sub_vo
&& sub_vo_win
) {
796 int e
=vo_x11_check_events(mDisplay
);
797 if ( !(e
&VO_EVENT_RESIZE
) && !(e
&VO_EVENT_EXPOSE
) ) return;
798 XSetBackground(mDisplay
, vo_gc
, 0);
799 XClearWindow(mDisplay
, vo_window
);
800 dxr2_set_overlay_window();
805 static int preinit(const char *arg
) {
813 sub_config_count
= 0;
816 for(n
= 0 ; video_out_drivers
[n
] != NULL
; n
++) {
817 const vo_info_t
* vi
= video_out_drivers
[n
]->info
;
820 if(strcasecmp(arg
,vi
->short_name
) == 0)
823 sub_vo
= video_out_drivers
[n
];
825 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] We need a sub driver to initialize the overlay\n");
832 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] Sub driver '%s' not found => no overlay\n",arg
);
835 if(sub_vo
->preinit(NULL
) != 0) {
836 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] Sub vo %s preinit failed => no overlay\n",arg
);
840 uint32_t fmt
= IMGFMT_BGR24
;
841 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] Sub vo %s initialized\n",arg
);
842 if(sub_vo
->control(VOCTRL_QUERY_FORMAT
,&fmt
) <= 0) {
843 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] Sub vo %s doesn't support BGR24 => no overlay\n",arg
);
851 dxr2_fd
= open( "/dev/dxr2", O_WRONLY
);
853 mp_msg(MSGT_VO
,MSGL_V
, "VO: [dxr2] Error opening /dev/dxr2 for writing!\n" );
858 uCodeFD
= open(ucode
, O_RDONLY
);
859 else for (n
=0; ucodesearchpath
[n
] != NULL
; n
++) {
860 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] Looking for microcode in %s... ",
862 if ((uCodeFD
= open(ucodesearchpath
[n
], O_RDONLY
))>0) {
863 mp_msg(MSGT_VO
,MSGL_V
,"ok\n");
866 mp_msg(MSGT_VO
,MSGL_V
,"failed (%s)\n", strerror(errno
));
870 mp_msg(MSGT_VO
,MSGL_ERR
,"VO: [dxr2] Could not open microcode\n");
874 uCodeSize
= lseek(uCodeFD
, 0, SEEK_END
);
875 if ((uCode
= malloc(uCodeSize
+ 4)) == NULL
) {
877 mp_msg(MSGT_VO
,MSGL_FATAL
,"VO: [dxr2] Could not allocate memory for uCode: %s\n", strerror(errno
));
880 lseek(uCodeFD
, 0, SEEK_SET
);
881 if (read(uCodeFD
, uCode
+4, uCodeSize
) != uCodeSize
) {
883 mp_msg(MSGT_VO
,MSGL_ERR
,"VO: [dxr2] Could not read uCode uCode: %s\n", strerror(errno
));
887 uCode
->uCodeLength
= uCodeSize
;
890 ioctl(dxr2_fd
, DXR2_IOC_INIT_ZIVADS
, uCode
);
893 ioctl(dxr2_fd
, DXR2_IOC_RESET
, NULL
);
901 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_CROPPING
, &crop
);
906 static int control(uint32_t request
, void *data
, ...)
909 case VOCTRL_QUERY_FORMAT
:
910 return query_format(*((uint32_t*)data
));
912 ioctl(dxr2_fd
,DXR2_IOC_PAUSE
, NULL
);
915 ioctl(dxr2_fd
, DXR2_IOC_PLAY
, NULL
);
919 ioctl(dxr2_fd
, DXR2_IOC_PLAY
, NULL
);
924 case VOCTRL_FULLSCREEN
:
928 int r
= sub_vo
->control(VOCTRL_FULLSCREEN
,0);
929 if(r
== VO_TRUE
&& !sub_vo_win
)
930 dxr2_set_overlay_window();
935 win
.arg1
= vo_fs
? vo_screenwidth
: movie_w
;
936 win
.arg2
= vo_fs
? vo_screenheight
: movie_h
;
937 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_DIMENSION
, &win
);
938 win
.arg1
= (vo_screenwidth
- win
.arg1
) / 2;
939 win
.arg2
= (vo_screenheight
- win
.arg2
) / 2;
940 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_POSITION
,&win
);
943 case VOCTRL_SET_SPU_PALETTE
: {
944 if(ioctl(dxr2_fd
,DXR2_IOC_SET_SUBPICTURE_PALETTE
,data
) < 0) {
945 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] SPU palette loading failed\n");