2 #include "fastmemcpy.h"
16 #include "video_out.h"
17 #include "video_out_internal.h"
21 #include "libmpdemux/mpeg_packetizer.h"
24 #include "x11_common.h"
27 #include <dxr2ioctl.h>
30 extern char *get_path(const char *filename
);
32 extern float monitor_aspect
;
33 extern float movie_aspect
;
37 static int movie_w
,movie_h
;
38 static int playing
= 0;
40 // vo device used to blank the screen for the overlay init
41 static vo_functions_t
* sub_vo
= NULL
;
43 static uint8_t* sub_img
= NULL
;
44 static int sub_x
,sub_y
,sub_w
,sub_h
;
45 static int sub_x_off
,sub_y_off
;
46 static int sub_config_count
;
48 static int sub_vo_win
= 0;
50 static int use_ol
= 1;
51 static int ol_ratio
= 1000;
52 static char *norm
= NULL
;
53 static char *ucode
= NULL
;
54 static int ar_mode
= DXR2_ASPECTRATIOMODE_LETTERBOX
;
55 static int mv_mode
= DXR2_MACROVISION_OFF
;
56 static int _75ire_mode
= DXR2_75IRE_OFF
;
57 static int bw_mode
= DXR2_BLACKWHITE_OFF
;
58 static int interlaced_mode
= DXR2_INTERLACED_ON
;
59 static int pixel_mode
= DXR2_PIXEL_CCIR601
;
60 static int iec958_mode
= DXR2_IEC958_DECODED
;
61 static int mute_mode
= DXR2_AUDIO_MUTE_OFF
;
62 static int ignore_cache
= 0;
63 static int update_cache
= 0;
64 static int olw_cor
= 0, olh_cor
= 0,olx_cor
= 0, oly_cor
= 0;
65 static int ol_osd
= 0;
66 static int ck_rmin
= 0x40;
67 static int ck_rmax
= 0xFF;
68 static int ck_r
= 0xFF;
69 static int ck_gmin
= 0x00;
70 static int ck_gmax
= 0x20;
72 static int ck_bmin
= 0x40;
73 static int ck_bmax
= 0xFF;
74 static int ck_b
= 0xFF;
75 static int cr_left
= 0, cr_right
= 0;
76 static int cr_top
= 55, cr_bot
= 300;
78 m_option_t dxr2_opts
[] = {
79 { "overlay", &use_ol
, CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
80 { "nooverlay", &use_ol
, CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
81 { "overlay-ratio", &ol_ratio
, CONF_TYPE_INT
, CONF_RANGE
, 1, 2500, NULL
},
82 { "ucode", &ucode
, CONF_TYPE_STRING
,0, 0, 0, NULL
},
84 { "norm", &norm
, CONF_TYPE_STRING
,0, 0, 0, NULL
},
86 { "ar-mode",&ar_mode
, CONF_TYPE_INT
, CONF_RANGE
,0,2,NULL
},
88 { "macrovision",&mv_mode
,CONF_TYPE_INT
,CONF_RANGE
,0,3, NULL
},
90 { "75ire",&_75ire_mode
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
91 { "no75ire",&_75ire_mode
,CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
93 { "bw",&bw_mode
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
94 { "color",&bw_mode
,CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
96 { "interlaced",&interlaced_mode
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
97 { "nointerlaced",&interlaced_mode
,CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
99 { "square-pixel",&pixel_mode
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
100 { "ccir601-pixel",&pixel_mode
,CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
102 { "iec958-encoded",&iec958_mode
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
103 { "iec958-decoded",&iec958_mode
,CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
105 { "mute", &mute_mode
,CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
106 { "nomute",&mute_mode
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
108 { "ignore-cache",&ignore_cache
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
109 { "update-cache",&update_cache
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
111 { "olh-cor", &olh_cor
, CONF_TYPE_INT
, CONF_RANGE
, -20, 20, NULL
},
112 { "olw-cor", &olw_cor
, CONF_TYPE_INT
, CONF_RANGE
, -20, 20, NULL
},
113 { "olx-cor", &olx_cor
, CONF_TYPE_INT
, CONF_RANGE
, -20, 20, NULL
},
114 { "oly-cor", &oly_cor
, CONF_TYPE_INT
, CONF_RANGE
, -20, 20, NULL
},
116 { "ol-osd", &ol_osd
, CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
117 { "nool-osd", &ol_osd
, CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
119 { "ck-rmin", &ck_rmin
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
120 { "ck-rmax", &ck_rmax
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
121 { "ck-r", &ck_r
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
122 { "ck-gmin", &ck_gmin
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
123 { "ck-gmax", &ck_gmax
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
124 { "ck-g", &ck_g
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
125 { "ck-bmin", &ck_bmin
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
126 { "ck-bmax", &ck_bmax
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
127 { "ck-b", &ck_b
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
128 { "cr-left", &cr_left
, CONF_TYPE_INT
, CONF_RANGE
, 0, 500, NULL
},
129 { "cr-right", &cr_right
, CONF_TYPE_INT
, CONF_RANGE
, 0, 500, NULL
},
130 { "cr-top", &cr_top
, CONF_TYPE_INT
, CONF_RANGE
, 0, 500, NULL
},
131 { "cr-bot", &cr_bot
, CONF_TYPE_INT
, CONF_RANGE
, 0, 500, NULL
},
133 { NULL
,NULL
, 0, 0, 0, 0, NULL
}
136 static vo_info_t info
= {
139 "Alban Bedel <albeu@free.fr> and Tobias Diedrich <ranma@gmx.at>",
145 static char *ucodesearchpath
[] = {
146 "/usr/local/lib/dxr2/dvd12.ux",
147 "/usr/lib/dxr2/dvd12.ux",
152 #define BUF_SIZE 2048
154 static unsigned char dxr2buf
[BUF_SIZE
];
155 static unsigned int dxr2bufpos
= 0;
157 int write_dxr2(unsigned char *data
, int len
)
163 mp_msg (MSGT_VO
, MSGL_ERR
, "DXR2 fd is not valid\n");
167 while (len
>0) if ((dxr2bufpos
+len
) <= BUF_SIZE
) {
168 fast_memcpy(dxr2buf
+dxr2bufpos
, data
, len
);
172 int copylen
=BUF_SIZE
-dxr2bufpos
;
174 fast_memcpy(dxr2buf
+dxr2bufpos
, data
, copylen
);
175 dxr2bufpos
+= copylen
;
179 w
+= write(dxr2_fd
, dxr2buf
, BUF_SIZE
);
181 mp_msg(MSGT_VO
,MSGL_WARN
,"DXR2 : write failed : %s \n",strerror(errno
));
187 memmove(dxr2buf
,dxr2buf
+ w
,dxr2bufpos
);
193 static void flush_dxr2()
197 w
= write(dxr2_fd
, dxr2buf
, dxr2bufpos
);
199 mp_msg(MSGT_VO
,MSGL_WARN
,"DXR2 : write failed %s \n",strerror(errno
));
207 #define PACK_MAX_SIZE 2048
209 static unsigned char pack
[PACK_MAX_SIZE
];
211 static unsigned char mpg_eof
[]={
212 0x00, 0x00, 0x01, 0xb9
215 static void dxr2_send_eof(void)
217 write_dxr2(mpg_eof
, sizeof(mpg_eof
));
220 void dxr2_send_sub_packet(unsigned char* data
,int len
,int id
,unsigned int timestamp
) {
224 mp_msg(MSGT_VO
,MSGL_ERR
,"DXR2 fd is not valid\n");
228 if (((int) timestamp
)<0)
231 mp_msg(MSGT_VO
,MSGL_DBG2
,"dxr2_send_sub_packet(timestamp=%d)\n", timestamp
);
233 pack
[0]=pack
[1]=0;pack
[2]=0x01;
239 int payload_size
= PACK_MAX_SIZE
-(7+ptslen
+3);
240 if(payload_size
>len
) payload_size
= len
;
242 pack
[4]=(3+ptslen
+1+payload_size
)>>8;
243 pack
[5]=(3+ptslen
+1+payload_size
)&255;
250 // presentation time stamp:
251 x
=(0x02 << 4) | (((timestamp
>> 30) & 0x07) << 1) | 1;
253 x
=((((timestamp
>> 15) & 0x7fff) << 1) | 1);
254 pack
[10]=x
>>8; pack
[11]=x
&255;
255 x
=((((timestamp
) & 0x7fff) << 1) | 1);
256 pack
[12]=x
>>8; pack
[13]=x
&255;
263 write_dxr2(pack
,7+ptslen
+3);
264 write_dxr2(data
,payload_size
);
266 data
+= payload_size
;
271 static int dxr2_set_vga_params(dxr2_vgaParams_t
* vga
,int detect
) {
272 // Init the overlay, don't ask me how it work ;-)
282 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_CROPPING
, &crop
);
290 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_COLOUR
, &oc
);
293 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_RATIO
,&om
);
297 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_POSITION
,&win
);
299 win
.arg1
= vo_screenwidth
;
300 win
.arg2
= vo_screenheight
;
301 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_DIMENSION
,&win
);
304 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_IN_DELAY
,&om
);
307 // First we need a white screen
308 uint8_t* img
= malloc(vo_screenwidth
*vo_screenheight
*3);
309 uint8_t* src
[] = { img
, NULL
, NULL
};
310 int stride
[] = { vo_screenwidth
* 3 , 0, 0 };
311 int cc
= vo_config_count
;
313 memset(img
,255,vo_screenwidth
*vo_screenheight
*3);
314 vo_config_count
= sub_config_count
;
315 if(sub_vo
->config(vo_screenwidth
,vo_screenheight
,vo_screenwidth
,vo_screenheight
,
316 VOFLAG_FULLSCREEN
,"DXR2 sub vo",IMGFMT_BGR24
) != 0) {
317 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] sub vo config failed => No overlay\n");
321 vo_config_count
= cc
;
324 sub_vo
->draw_slice(src
,stride
,vo_screenwidth
,vo_screenheight
,0,0);
328 vo_config_count
= cc
;
330 om
.arg
= DXR2_OVERLAY_WINDOW_COLOUR_KEY
;
331 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_MODE
,&om
);
333 vga
->xScreen
= vo_screenwidth
;
334 vga
->yScreen
= vo_screenheight
;
335 vga
->hOffWinKey
= 100;
337 ioctl(dxr2_fd
, DXR2_IOC_CALCULATE_VGA_PARAMETERS
, vga
);
339 ioctl(dxr2_fd
, DXR2_IOC_SET_VGA_PARAMETERS
,vga
);
344 static int dxr2_save_vga_params(dxr2_vgaParams_t
* vga
,char* name
) {
346 char* p
= get_path("dxr2_cache");
347 int p_len
= strlen(p
), name_len
= strlen(name
);
348 char cache_path
[p_len
+ name_len
+ 2];
353 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] No vga cache dir found (%s)\n",strerror(errno
));
354 if(errno
== EACCES
) {
358 // Try to create the dir
359 if(mkdir(p
,S_IRWXU
) != 0) {
360 mp_msg(MSGT_VO
,MSGL_ERR
,"VO: [dxr2] Unable to create vga cache dir %s (%s)\n",p
,strerror(errno
));
365 sprintf(cache_path
,"%s/%s",p
,name
);
367 fd
= fopen(cache_path
,"w");
369 mp_msg(MSGT_VO
,MSGL_ERR
,"VO: [dxr2] Unable to open cache file %s for writing (%s)\n",cache_path
,strerror(errno
));
373 ret
= fprintf(fd
,"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
391 return ret
>= 11 ? 1 : 0;
394 static int dxr2_load_vga_params(dxr2_vgaParams_t
* vga
,char* name
) {
395 char* p
= get_path("dxr2_cache");
396 int p_len
= strlen(p
), name_len
= strlen(name
);
397 char cache_path
[p_len
+ name_len
+ 2];
402 sprintf(cache_path
,"%s/%s",p
,name
);
405 fd
= fopen(cache_path
,"r");
407 mp_msg(MSGT_VO
,MSGL_ERR
,"VO: [dxr2] Unable to open cache file %s for reading (%s)\n",cache_path
,strerror(errno
));
410 ret
= fscanf(fd
, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
428 if(ret
> 11 && !olx_cor
) olx_cor
= xc
;
429 if(ret
> 12 && !oly_cor
) oly_cor
= yc
;
430 if(ret
> 13 && !olw_cor
) olw_cor
= wc
;
431 if(ret
> 14 && !olh_cor
) olh_cor
= hc
;
432 return ret
>= 11 ? 1 : 0;
435 static int dxr2_setup_vga_params(void) {
436 const vo_info_t
* vi
= sub_vo
->info
;
437 dxr2_vgaParams_t vga
;
439 int loaded
= dxr2_load_vga_params(&vga
,(char*)vi
->short_name
);
440 if(!dxr2_set_vga_params(&vga
,(update_cache
|| ignore_cache
) ? 1 : !loaded
))
442 if(!loaded
|| update_cache
)
443 dxr2_save_vga_params(&vga
,(char*)vi
->short_name
);
447 static void dxr2_set_overlay_window(void) {
448 uint8_t* src
[] = { sub_img
, NULL
, NULL
};
449 int stride
[] = { movie_w
* 3 , 0, 0 };
452 int cc
= vo_config_count
;
453 vo_config_count
= sub_config_count
;
454 sub_vo
->draw_slice(src
,stride
,movie_w
,movie_h
,0,0);
456 vo_config_count
= cc
;
459 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
);
461 // Sub vo isn't a windowed one, fill in the needed stuff
464 vo_dwidth
= vo_screenwidth
;
465 vo_dheight
= vo_screenheight
;
469 vo_dheight
= movie_h
;
470 vo_dx
= (vo_screenwidth
- vo_dwidth
) / 2;
471 vo_dy
= (vo_screenheight
- vo_dheight
) / 2;
475 if(sub_w
!= vo_dwidth
|| sub_h
!= vo_dheight
) {
476 int new_aspect
= ((1<<16)*vo_dwidth
+ vo_dheight
/2)/vo_dheight
;
479 if(new_aspect
> aspect
)
480 sub_w
= (sub_h
*aspect
+ (1<<15))>>16;
482 sub_h
= ((sub_w
<<16) + (aspect
>>1)) /aspect
;
485 sub_x_off
= (vo_dwidth
-sub_w
) / 2;
486 sub_y_off
= (vo_dheight
-sub_h
) / 2;
487 sub_x
= -vo_dx
; // Be sure to also replace the overlay
490 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
);
491 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_DIMENSION
, &win
);
494 if(vo_dx
!= sub_x
|| vo_dy
!= sub_y
) {
495 sub_x
= vo_dx
+ olx_cor
+ sub_x_off
;
496 sub_y
= vo_dy
+ oly_cor
+ sub_y_off
;
497 win
.arg1
= (sub_x
> 0 ? sub_x
: 0);
498 win
.arg2
= (sub_y
> 0 ? sub_y
: 0);
499 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] set pos x=%d y=%d \n",win
.arg1
,win
.arg2
);
500 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_POSITION
,&win
);
505 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
)
508 dxr2_threeArg_t arg3
;
511 mp_msg(MSGT_VO
,MSGL_ERR
,"DXR2 fd is not valid\n");
518 ioctl(dxr2_fd
, DXR2_IOC_STOP
, NULL
);
522 // Video stream setup
523 arg3
.arg1
= DXR2_STREAM_VIDEO
;
525 ioctl(dxr2_fd
, DXR2_IOC_SELECT_STREAM
, &arg3
);
527 arg3
.arg1
= DXR2_SRC_VIDEO_FREQ_30
;
528 else arg3
.arg1
= DXR2_SRC_VIDEO_FREQ_25
;
530 arg3
.arg3
= s_height
;
531 ioctl(dxr2_fd
, DXR2_IOC_SET_SOURCE_VIDEO_FORMAT
, &arg3
);
532 arg
= DXR2_BITSTREAM_TYPE_MPEG_VOB
;
533 ioctl(dxr2_fd
, DXR2_IOC_SET_BITSTREAM_TYPE
, &arg
);
536 if (1.76 <= movie_aspect
&& movie_aspect
<= 1.80) {
537 arg
= DXR2_ASPECTRATIO_16_9
;
538 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] source aspect ratio 16:9\n");
540 arg
= DXR2_ASPECTRATIO_4_3
;
541 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] source aspect ratio 4:3\n");
543 ioctl(dxr2_fd
, DXR2_IOC_SET_SOURCE_ASPECT_RATIO
, &arg
);
544 if (1.76 <= monitor_aspect
&& monitor_aspect
<=1.80) {
545 arg
= DXR2_ASPECTRATIO_16_9
;
546 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] monitor aspect ratio 16:9\n");
548 arg
= DXR2_ASPECTRATIO_4_3
;
549 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] monitor aspect ratio 4:3\n");
551 ioctl(dxr2_fd
, DXR2_IOC_SET_OUTPUT_ASPECT_RATIO
, &arg
);
554 ioctl(dxr2_fd
, DXR2_IOC_SET_ASPECT_RATIO_MODE
, &arg
);
558 ioctl(dxr2_fd
, DXR2_IOC_SET_TV_MACROVISION_MODE
, &arg
);
560 ioctl(dxr2_fd
, DXR2_IOC_SET_TV_75IRE_MODE
, &arg
);
562 ioctl(dxr2_fd
, DXR2_IOC_SET_TV_BLACKWHITE_MODE
, &arg
);
563 arg
= interlaced_mode
;
564 ioctl(dxr2_fd
, DXR2_IOC_SET_TV_INTERLACED_MODE
, &arg
);
566 ioctl(dxr2_fd
, DXR2_IOC_SET_TV_PIXEL_MODE
, &arg
);
569 if (strcmp(norm
, "ntsc")==0)
570 arg
= DXR2_OUTPUTFORMAT_NTSC
;
571 else if (strcmp(norm
, "pal")==0) {
573 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] you want pal, but we play at 30 fps, selecting pal60 instead\n");
574 arg
= DXR2_OUTPUTFORMAT_PAL_60
;
576 } else arg
= DXR2_OUTPUTFORMAT_PAL_BDGHI
;
577 } else if (strcmp(norm
, "pal60")==0) {
579 arg
= DXR2_OUTPUTFORMAT_PAL_60
;
581 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] you want pal60, but we play at 25 fps, selecting pal instead\n");
582 arg
= DXR2_OUTPUTFORMAT_PAL_BDGHI
;
585 } else if (strcmp(norm
, "palm")==0)
586 arg
= DXR2_OUTPUTFORMAT_PAL_M
;
587 else if (strcmp(norm
, "paln")==0)
588 arg
= DXR2_OUTPUTFORMAT_PAL_N
;
589 else if (strcmp(norm
, "palnc")==0)
590 arg
= DXR2_OUTPUTFORMAT_PAL_Nc
;
592 mp_msg(MSGT_VO
,MSGL_WARN
,"[dxr2] invalid norm %s\n", norm
);
593 mp_msg(MSGT_VO
,MSGL_WARN
,"Valid values are ntsc,pal,pal60,palm,paln,palnc\n");
594 mp_msg(MSGT_VO
,MSGL_WARN
,"Using ntsc\n");
599 arg
= DXR2_OUTPUTFORMAT_NTSC
;
602 arg
= DXR2_OUTPUTFORMAT_PAL_BDGHI
;
606 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] output norm set to %s\n", norm
);
607 ioctl(dxr2_fd
, DXR2_IOC_SET_TV_OUTPUT_FORMAT
, &arg
);
611 arg
= DXR2_SUBPICTURE_ON
;
612 ioctl(dxr2_fd
,DXR2_IOC_ENABLE_SUBPICTURE
,&arg
);
613 arg3
.arg1
= DXR2_STREAM_SUBPICTURE
;
615 ioctl(dxr2_fd
, DXR2_IOC_SELECT_STREAM
, &arg3
);
619 ioctl(dxr2_fd
, DXR2_IOC_IEC958_OUTPUT_MODE
, &arg
);
620 arg
= DXR2_AUDIO_WIDTH_16
;
621 ioctl(dxr2_fd
, DXR2_IOC_SET_AUDIO_DATA_WIDTH
, &arg
);
622 arg
= DXR2_AUDIO_FREQ_48
;
623 ioctl(dxr2_fd
, DXR2_IOC_SET_AUDIO_SAMPLE_FREQUENCY
, &arg
);
624 arg3
.arg1
= DXR2_STREAM_AUDIO_LPCM
;
626 ioctl(dxr2_fd
, DXR2_IOC_SELECT_STREAM
, &arg3
);
628 ioctl(dxr2_fd
, DXR2_IOC_SET_AUDIO_VOLUME
, &arg
);
630 ioctl(dxr2_fd
, DXR2_IOC_AUDIO_MUTE
, &arg
);
634 //vo_fs = flags & VOFLAG_FULLSCREEN ? 1 : 0;
639 int cc
= vo_config_count
;
640 vo_config_count
= sub_config_count
;
641 // Load or detect the overlay stuff
642 if(!dxr2_setup_vga_params()) {
645 vo_config_count
= cc
;
648 // Does the sub vo support the x11 stuff
649 // Fix me : test the other x11 vo's and enable them
650 if(strcmp(sub_vo
->info
->short_name
,"x11") == 0)
655 // No window and no osd => we don't need any subdriver
656 if(!sub_vo_win
&& !ol_osd
) {
663 int i
,sub_flags
= VOFLAG_SWSCALE
| (flags
& VOFLAG_FULLSCREEN
);
664 if(sub_vo
->config(width
,height
,width
,height
,sub_flags
,
665 "MPlayer DXR2 render",IMGFMT_BGR24
) != 0) {
666 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] sub vo config failed => No X11 window\n");
673 // Feel free to try some other other color and report your results
680 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_COLOUR
, &oc
);
682 om
.arg
= DXR2_OVERLAY_WINDOW_COLOUR_KEY
;
683 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_MODE
,&om
);
684 sub_img
= malloc(width
*height
*3);
685 for(i
= 0 ; i
< width
*height
*3 ; i
+= 3) {
690 aspect
= ((1<<16)*width
+ height
/2)/height
;
692 dxr2_set_overlay_window();
695 vo_config_count
= cc
;
696 if(!sub_vo
) { // Fallback on non windowed overlay
697 vo_fs
= flags
& VOFLAG_FULLSCREEN
? 1 : 0;
698 om
.arg
= DXR2_OVERLAY_WINDOW_KEY
;
699 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_MODE
,&om
);
700 win
.arg1
= flags
& VOFLAG_FULLSCREEN
? vo_screenwidth
: width
;
701 win
.arg2
= flags
& VOFLAG_FULLSCREEN
? vo_screenheight
: height
;
702 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_DIMENSION
, &win
);
703 win
.arg1
= (vo_screenwidth
- win
.arg1
) / 2;
704 win
.arg2
= (vo_screenheight
- win
.arg2
) / 2;
705 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_POSITION
,&win
);
710 if (vo_ontop
) vo_x11_setlayer(mDisplay
, vo_window
, vo_ontop
);
713 if(ioctl(dxr2_fd
, DXR2_IOC_PLAY
, NULL
) == 0) {
720 static void clear_alpha(int x0
,int y0
, int w
,int h
) {
721 uint8_t* src
[] = { sub_img
, NULL
, NULL
};
722 int stride
[] = { movie_w
* 3, 0, 0 };
724 sub_vo
->draw_slice(src
,stride
,w
,h
,x0
,y0
);
727 static void draw_osd(void)
729 if(sub_vo
&& ol_osd
) {
730 vo_remove_text(movie_w
,movie_h
,clear_alpha
);
735 static int draw_frame(uint8_t * src
[])
737 vo_mpegpes_t
*p
=(vo_mpegpes_t
*)src
[0];
739 if(p
->id
== 0x1E0) {// Video
740 send_mpeg_ps_packet (p
->data
, p
->size
, p
->id
,
741 p
->timestamp
? p
->timestamp
: vo_pts
, 2, write_dxr2
);
742 } else if(p
->id
== 0x20) // Subtitles
743 dxr2_send_sub_packet(p
->data
, p
->size
, p
->id
, p
->timestamp
);
747 static void flip_page (void)
749 if(sub_vo
&& ol_osd
&& vo_osd_changed_flag
)
753 static int draw_slice( uint8_t *srcimg
[], int stride
[], int w
, int h
, int x0
, int y0
)
759 static int query_format(uint32_t format
)
761 if (format
==IMGFMT_MPEGPES
)
762 return VFCAP_CSP_SUPPORTED
|VFCAP_CSP_SUPPORTED_BY_HW
|VFCAP_TIMER
|VFCAP_SPU
;
767 static void uninit(void)
769 mp_msg(MSGT_VO
,MSGL_DBG2
, "VO: [dxr2] Uninitializing\n" );
785 int cc
= vo_config_count
;
786 vo_config_count
= sub_config_count
;
789 vo_config_count
= cc
;
794 static void check_events(void)
796 // I'd like to have this done in an x11 independent way
797 // It's because of this that we are limited to vo_x11 for windowed overlay :-(
798 #ifdef X11_FULLSCREEN
799 if(sub_vo
&& sub_vo_win
) {
800 int e
=vo_x11_check_events(mDisplay
);
801 if ( !(e
&VO_EVENT_RESIZE
) && !(e
&VO_EVENT_EXPOSE
) ) return;
802 XSetBackground(mDisplay
, vo_gc
, 0);
803 XClearWindow(mDisplay
, vo_window
);
804 dxr2_set_overlay_window();
809 static int preinit(const char *arg
) {
817 sub_config_count
= 0;
820 for(n
= 0 ; video_out_drivers
[n
] != NULL
; n
++) {
821 const vo_info_t
* vi
= video_out_drivers
[n
]->info
;
824 if(strcasecmp(arg
,vi
->short_name
) == 0)
827 sub_vo
= video_out_drivers
[n
];
829 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] We need a sub driver to initialize the overlay\n");
836 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] Sub driver '%s' not found => no overlay\n",arg
);
839 if(sub_vo
->preinit(NULL
) != 0) {
840 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] Sub vo %s preinit failed => no overlay\n",arg
);
844 uint32_t fmt
= IMGFMT_BGR24
;
845 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] Sub vo %s inited\n",arg
);
846 if(sub_vo
->control(VOCTRL_QUERY_FORMAT
,&fmt
) <= 0) {
847 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] Sub vo %s doesn't support BGR24 => no overlay\n",arg
);
855 dxr2_fd
= open( "/dev/dxr2", O_WRONLY
);
857 mp_msg(MSGT_VO
,MSGL_V
, "VO: [dxr2] Error opening /dev/dxr2 for writing!\n" );
862 uCodeFD
= open(ucode
, O_RDONLY
);
863 else for (n
=0; ucodesearchpath
[n
] != NULL
; n
++) {
864 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] Looking for microcode in %s... ",
866 if ((uCodeFD
= open(ucodesearchpath
[n
], O_RDONLY
))>0) {
867 mp_msg(MSGT_VO
,MSGL_V
,"ok\n");
870 mp_msg(MSGT_VO
,MSGL_V
,"failed (%s)\n", strerror(errno
));
874 mp_msg(MSGT_VO
,MSGL_ERR
,"VO: [dxr2] Could not open microcode\n");
878 uCodeSize
= lseek(uCodeFD
, 0, SEEK_END
);
879 if ((uCode
= malloc(uCodeSize
+ 4)) == NULL
) {
881 mp_msg(MSGT_VO
,MSGL_FATAL
,"VO: [dxr2] Could not allocate memory for uCode: %s\n", strerror(errno
));
884 lseek(uCodeFD
, 0, SEEK_SET
);
885 if (read(uCodeFD
, uCode
+4, uCodeSize
) != uCodeSize
) {
887 mp_msg(MSGT_VO
,MSGL_ERR
,"VO: [dxr2] Could not read uCode uCode: %s\n", strerror(errno
));
891 uCode
->uCodeLength
= uCodeSize
;
894 ioctl(dxr2_fd
, DXR2_IOC_INIT_ZIVADS
, uCode
);
897 ioctl(dxr2_fd
, DXR2_IOC_RESET
, NULL
);
905 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_CROPPING
, &crop
);
910 static int control(uint32_t request
, void *data
, ...)
913 case VOCTRL_QUERY_FORMAT
:
914 return query_format(*((uint32_t*)data
));
916 ioctl(dxr2_fd
,DXR2_IOC_PAUSE
, NULL
);
919 ioctl(dxr2_fd
, DXR2_IOC_PLAY
, NULL
);
923 ioctl(dxr2_fd
, DXR2_IOC_PLAY
, NULL
);
928 case VOCTRL_FULLSCREEN
:
932 int r
= sub_vo
->control(VOCTRL_FULLSCREEN
,0);
933 if(r
== VO_TRUE
&& !sub_vo_win
)
934 dxr2_set_overlay_window();
939 win
.arg1
= vo_fs
? vo_screenwidth
: movie_w
;
940 win
.arg2
= vo_fs
? vo_screenheight
: movie_h
;
941 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_DIMENSION
, &win
);
942 win
.arg1
= (vo_screenwidth
- win
.arg1
) / 2;
943 win
.arg2
= (vo_screenheight
- win
.arg2
) / 2;
944 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_POSITION
,&win
);
947 case VOCTRL_SET_SPU_PALETTE
: {
948 if(ioctl(dxr2_fd
,DXR2_IOC_SET_SUBPICTURE_PALETTE
,data
) < 0) {
949 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] SPU palette loading failed\n");