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 "fastmemcpy.h"
24 #include <sys/ioctl.h>
26 #include <sys/types.h>
33 #include "video_out.h"
34 #include "video_out_internal.h"
39 #include "libmpdemux/mpeg_packetizer.h"
40 #include "x11_common.h"
42 #include <dxr2ioctl.h>
49 static int movie_w
,movie_h
;
50 static int playing
= 0;
52 // vo device used to blank the screen for the overlay init
53 static const struct vo_old_functions
*sub_vo
= NULL
;
54 static const struct vo_info_s
*sub_info
;
56 static uint8_t* sub_img
= NULL
;
57 static int sub_x
,sub_y
,sub_w
,sub_h
;
58 static int sub_x_off
,sub_y_off
;
59 static int sub_config_count
;
61 static int sub_vo_win
= 0;
63 static int use_ol
= 1;
64 static int ol_ratio
= 1000;
65 static char *norm
= NULL
;
66 static char *ucode
= NULL
;
67 static int ar_mode
= DXR2_ASPECTRATIOMODE_LETTERBOX
;
68 static int mv_mode
= DXR2_MACROVISION_OFF
;
69 static int _75ire_mode
= DXR2_75IRE_OFF
;
70 static int bw_mode
= DXR2_BLACKWHITE_OFF
;
71 static int interlaced_mode
= DXR2_INTERLACED_ON
;
72 static int pixel_mode
= DXR2_PIXEL_CCIR601
;
73 static int iec958_mode
= DXR2_IEC958_DECODED
;
74 static int mute_mode
= DXR2_AUDIO_MUTE_OFF
;
75 static int ignore_cache
= 0;
76 static int update_cache
= 0;
77 static int olw_cor
= 0, olh_cor
= 0,olx_cor
= 0, oly_cor
= 0;
78 static int ol_osd
= 0;
79 static int ck_rmin
= 0x40;
80 static int ck_rmax
= 0xFF;
81 static int ck_r
= 0xFF;
82 static int ck_gmin
= 0x00;
83 static int ck_gmax
= 0x20;
85 static int ck_bmin
= 0x40;
86 static int ck_bmax
= 0xFF;
87 static int ck_b
= 0xFF;
88 static int cr_left
= 0, cr_right
= 0;
89 static int cr_top
= 55, cr_bot
= 300;
91 const m_option_t dxr2_opts
[] = {
92 { "overlay", &use_ol
, CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
93 { "nooverlay", &use_ol
, CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
94 { "overlay-ratio", &ol_ratio
, CONF_TYPE_INT
, CONF_RANGE
, 1, 2500, NULL
},
95 { "ucode", &ucode
, CONF_TYPE_STRING
,0, 0, 0, NULL
},
97 { "norm", &norm
, CONF_TYPE_STRING
,0, 0, 0, NULL
},
99 { "ar-mode",&ar_mode
, CONF_TYPE_INT
, CONF_RANGE
,0,2,NULL
},
101 { "macrovision",&mv_mode
,CONF_TYPE_INT
,CONF_RANGE
,0,3, NULL
},
103 { "75ire",&_75ire_mode
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
104 { "no75ire",&_75ire_mode
,CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
106 { "bw",&bw_mode
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
107 { "color",&bw_mode
,CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
109 { "interlaced",&interlaced_mode
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
110 { "nointerlaced",&interlaced_mode
,CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
112 { "square-pixel",&pixel_mode
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
113 { "ccir601-pixel",&pixel_mode
,CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
115 { "iec958-encoded",&iec958_mode
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
116 { "iec958-decoded",&iec958_mode
,CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
118 { "mute", &mute_mode
,CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
119 { "nomute",&mute_mode
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
121 { "ignore-cache",&ignore_cache
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
122 { "update-cache",&update_cache
,CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
124 { "olh-cor", &olh_cor
, CONF_TYPE_INT
, CONF_RANGE
, -20, 20, NULL
},
125 { "olw-cor", &olw_cor
, CONF_TYPE_INT
, CONF_RANGE
, -20, 20, NULL
},
126 { "olx-cor", &olx_cor
, CONF_TYPE_INT
, CONF_RANGE
, -20, 20, NULL
},
127 { "oly-cor", &oly_cor
, CONF_TYPE_INT
, CONF_RANGE
, -20, 20, NULL
},
129 { "ol-osd", &ol_osd
, CONF_TYPE_FLAG
, 0, 0, 1, NULL
},
130 { "nool-osd", &ol_osd
, CONF_TYPE_FLAG
, 0, 1, 0, NULL
},
132 { "ck-rmin", &ck_rmin
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
133 { "ck-rmax", &ck_rmax
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
134 { "ck-r", &ck_r
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
135 { "ck-gmin", &ck_gmin
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
136 { "ck-gmax", &ck_gmax
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
137 { "ck-g", &ck_g
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
138 { "ck-bmin", &ck_bmin
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
139 { "ck-bmax", &ck_bmax
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
140 { "ck-b", &ck_b
, CONF_TYPE_INT
, CONF_RANGE
, 0, 0xFF, NULL
},
141 { "cr-left", &cr_left
, CONF_TYPE_INT
, CONF_RANGE
, 0, 500, NULL
},
142 { "cr-right", &cr_right
, CONF_TYPE_INT
, CONF_RANGE
, 0, 500, NULL
},
143 { "cr-top", &cr_top
, CONF_TYPE_INT
, CONF_RANGE
, 0, 500, NULL
},
144 { "cr-bot", &cr_bot
, CONF_TYPE_INT
, CONF_RANGE
, 0, 500, NULL
},
146 { NULL
,NULL
, 0, 0, 0, 0, NULL
}
149 static const vo_info_t info
= {
152 "Alban Bedel <albeu@free.fr> and Tobias Diedrich <ranma@gmx.at>",
156 const LIBVO_EXTERN (dxr2
)
158 static char *ucodesearchpath
[] = {
159 "/usr/local/lib/dxr2/dvd12.ux",
160 "/usr/lib/dxr2/dvd12.ux",
165 #define BUF_SIZE 2048
167 static unsigned char dxr2buf
[BUF_SIZE
];
168 static unsigned int dxr2bufpos
= 0;
170 int write_dxr2(const unsigned char *data
, int len
)
176 mp_msg (MSGT_VO
, MSGL_ERR
, "DXR2 fd is not valid\n");
180 while (len
>0) if ((dxr2bufpos
+len
) <= BUF_SIZE
) {
181 fast_memcpy(dxr2buf
+dxr2bufpos
, data
, len
);
185 int copylen
=BUF_SIZE
-dxr2bufpos
;
187 fast_memcpy(dxr2buf
+dxr2bufpos
, data
, copylen
);
188 dxr2bufpos
+= copylen
;
192 w
+= write(dxr2_fd
, dxr2buf
, BUF_SIZE
);
194 mp_msg(MSGT_VO
,MSGL_WARN
,"DXR2 : write failed : %s \n",strerror(errno
));
200 memmove(dxr2buf
,dxr2buf
+ w
,dxr2bufpos
);
206 static void flush_dxr2(void)
210 w
= write(dxr2_fd
, dxr2buf
, dxr2bufpos
);
212 mp_msg(MSGT_VO
,MSGL_WARN
,"DXR2 : write failed %s \n",strerror(errno
));
220 #define PACK_MAX_SIZE 2048
222 static unsigned char pack
[PACK_MAX_SIZE
];
224 static unsigned char mpg_eof
[]={
225 0x00, 0x00, 0x01, 0xb9
228 static void dxr2_send_eof(void)
230 write_dxr2(mpg_eof
, sizeof(mpg_eof
));
233 void dxr2_send_sub_packet(unsigned char* data
,int len
,int id
,unsigned int timestamp
) {
237 mp_msg(MSGT_VO
,MSGL_ERR
,"DXR2 fd is not valid\n");
241 if (((int) timestamp
)<0)
244 mp_msg(MSGT_VO
,MSGL_DBG2
,"dxr2_send_sub_packet(timestamp=%d)\n", timestamp
);
246 pack
[0]=pack
[1]=0;pack
[2]=0x01;
252 int payload_size
= PACK_MAX_SIZE
-(7+ptslen
+3);
253 if(payload_size
>len
) payload_size
= len
;
255 pack
[4]=(3+ptslen
+1+payload_size
)>>8;
256 pack
[5]=(3+ptslen
+1+payload_size
)&255;
263 // presentation time stamp:
264 x
=(0x02 << 4) | (((timestamp
>> 30) & 0x07) << 1) | 1;
266 x
=((((timestamp
>> 15) & 0x7fff) << 1) | 1);
267 pack
[10]=x
>>8; pack
[11]=x
&255;
268 x
=((((timestamp
) & 0x7fff) << 1) | 1);
269 pack
[12]=x
>>8; pack
[13]=x
&255;
276 write_dxr2(pack
,7+ptslen
+3);
277 write_dxr2(data
,payload_size
);
279 data
+= payload_size
;
284 static int dxr2_set_vga_params(dxr2_vgaParams_t
* vga
,int detect
) {
285 // Init the overlay, don't ask me how it work ;-)
295 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_CROPPING
, &crop
);
303 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_COLOUR
, &oc
);
306 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_RATIO
,&om
);
310 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_POSITION
,&win
);
312 win
.arg1
= vo_screenwidth
;
313 win
.arg2
= vo_screenheight
;
314 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_DIMENSION
,&win
);
317 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_IN_DELAY
,&om
);
320 // First we need a white screen
321 uint8_t* img
= malloc(vo_screenwidth
*vo_screenheight
*3);
322 uint8_t* src
[] = { img
, NULL
, NULL
};
323 int stride
[] = { vo_screenwidth
* 3 , 0, 0 };
324 int cc
= vo_config_count
;
326 memset(img
,255,vo_screenwidth
*vo_screenheight
*3);
327 vo_config_count
= sub_config_count
;
328 if(sub_vo
->config(vo_screenwidth
,vo_screenheight
,vo_screenwidth
,vo_screenheight
,
329 VOFLAG_FULLSCREEN
,"DXR2 sub vo",IMGFMT_BGR24
) != 0) {
330 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] sub vo config failed => No overlay\n");
334 vo_config_count
= cc
;
337 sub_vo
->draw_slice(src
,stride
,vo_screenwidth
,vo_screenheight
,0,0);
341 vo_config_count
= cc
;
343 om
.arg
= DXR2_OVERLAY_WINDOW_COLOUR_KEY
;
344 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_MODE
,&om
);
346 vga
->xScreen
= vo_screenwidth
;
347 vga
->yScreen
= vo_screenheight
;
348 vga
->hOffWinKey
= 100;
350 ioctl(dxr2_fd
, DXR2_IOC_CALCULATE_VGA_PARAMETERS
, vga
);
352 ioctl(dxr2_fd
, DXR2_IOC_SET_VGA_PARAMETERS
,vga
);
357 static int dxr2_save_vga_params(dxr2_vgaParams_t
* vga
,char* name
) {
359 char* p
= get_path("dxr2_cache");
360 int p_len
= strlen(p
), name_len
= strlen(name
);
361 char cache_path
[p_len
+ name_len
+ 2];
366 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] No vga cache dir found (%s)\n",strerror(errno
));
367 if(errno
== EACCES
) {
371 // Try to create the dir
372 if(mkdir(p
,S_IRWXU
) != 0) {
373 mp_msg(MSGT_VO
,MSGL_ERR
,"VO: [dxr2] Unable to create vga cache dir %s (%s)\n",p
,strerror(errno
));
378 sprintf(cache_path
,"%s/%s",p
,name
);
380 fd
= fopen(cache_path
,"w");
382 mp_msg(MSGT_VO
,MSGL_ERR
,"VO: [dxr2] Unable to open cache file %s for writing (%s)\n",cache_path
,strerror(errno
));
386 ret
= fprintf(fd
,"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
404 return ret
>= 11 ? 1 : 0;
407 static int dxr2_load_vga_params(dxr2_vgaParams_t
* vga
,char* name
) {
408 char* p
= get_path("dxr2_cache");
409 int p_len
= strlen(p
), name_len
= strlen(name
);
410 char cache_path
[p_len
+ name_len
+ 2];
415 sprintf(cache_path
,"%s/%s",p
,name
);
418 fd
= fopen(cache_path
,"r");
420 mp_msg(MSGT_VO
,MSGL_ERR
,"VO: [dxr2] Unable to open cache file %s for reading (%s)\n",cache_path
,strerror(errno
));
423 ret
= fscanf(fd
, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
441 if(ret
> 11 && !olx_cor
) olx_cor
= xc
;
442 if(ret
> 12 && !oly_cor
) oly_cor
= yc
;
443 if(ret
> 13 && !olw_cor
) olw_cor
= wc
;
444 if(ret
> 14 && !olh_cor
) olh_cor
= hc
;
445 return ret
>= 11 ? 1 : 0;
448 static int dxr2_setup_vga_params(void) {
449 const vo_info_t
* vi
= sub_info
;
450 dxr2_vgaParams_t vga
;
452 int loaded
= dxr2_load_vga_params(&vga
,(char*)vi
->short_name
);
453 if(!dxr2_set_vga_params(&vga
,(update_cache
|| ignore_cache
) ? 1 : !loaded
))
455 if(!loaded
|| update_cache
)
456 dxr2_save_vga_params(&vga
,(char*)vi
->short_name
);
460 static void dxr2_set_overlay_window(void) {
461 uint8_t* src
[] = { sub_img
, NULL
, NULL
};
462 int stride
[] = { movie_w
* 3 , 0, 0 };
465 int cc
= vo_config_count
;
466 vo_config_count
= sub_config_count
;
467 sub_vo
->draw_slice(src
,stride
,movie_w
,movie_h
,0,0);
469 vo_config_count
= cc
;
472 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
);
474 // Sub vo isn't a windowed one, fill in the needed stuff
477 vo_dwidth
= vo_screenwidth
;
478 vo_dheight
= vo_screenheight
;
482 vo_dheight
= movie_h
;
483 vo_dx
= (vo_screenwidth
- vo_dwidth
) / 2;
484 vo_dy
= (vo_screenheight
- vo_dheight
) / 2;
488 if(sub_w
!= vo_dwidth
|| sub_h
!= vo_dheight
) {
489 int new_aspect
= ((1<<16)*vo_dwidth
+ vo_dheight
/2)/vo_dheight
;
492 if(new_aspect
> aspect
)
493 sub_w
= (sub_h
*aspect
+ (1<<15))>>16;
495 sub_h
= ((sub_w
<<16) + (aspect
>>1)) /aspect
;
498 sub_x_off
= (vo_dwidth
-sub_w
) / 2;
499 sub_y_off
= (vo_dheight
-sub_h
) / 2;
500 sub_x
= -vo_dx
; // Be sure to also replace the overlay
503 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
);
504 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_DIMENSION
, &win
);
507 if(vo_dx
!= sub_x
|| vo_dy
!= sub_y
) {
508 sub_x
= vo_dx
+ olx_cor
+ sub_x_off
;
509 sub_y
= vo_dy
+ oly_cor
+ sub_y_off
;
510 win
.arg1
= (sub_x
> 0 ? sub_x
: 0);
511 win
.arg2
= (sub_y
> 0 ? sub_y
: 0);
512 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] set pos x=%d y=%d \n",win
.arg1
,win
.arg2
);
513 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_POSITION
,&win
);
518 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
)
521 dxr2_threeArg_t arg3
;
524 mp_msg(MSGT_VO
,MSGL_ERR
,"DXR2 fd is not valid\n");
531 ioctl(dxr2_fd
, DXR2_IOC_STOP
, NULL
);
535 // Video stream setup
536 arg3
.arg1
= DXR2_STREAM_VIDEO
;
538 ioctl(dxr2_fd
, DXR2_IOC_SELECT_STREAM
, &arg3
);
540 arg3
.arg1
= DXR2_SRC_VIDEO_FREQ_30
;
541 else arg3
.arg1
= DXR2_SRC_VIDEO_FREQ_25
;
543 arg3
.arg3
= s_height
;
544 ioctl(dxr2_fd
, DXR2_IOC_SET_SOURCE_VIDEO_FORMAT
, &arg3
);
545 arg
= DXR2_BITSTREAM_TYPE_MPEG_VOB
;
546 ioctl(dxr2_fd
, DXR2_IOC_SET_BITSTREAM_TYPE
, &arg
);
549 if (1.76 <= movie_aspect
&& movie_aspect
<= 1.80) {
550 arg
= DXR2_ASPECTRATIO_16_9
;
551 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] source aspect ratio 16:9\n");
553 arg
= DXR2_ASPECTRATIO_4_3
;
554 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] source aspect ratio 4:3\n");
556 ioctl(dxr2_fd
, DXR2_IOC_SET_SOURCE_ASPECT_RATIO
, &arg
);
557 if (1.76 <= monitor_aspect
&& monitor_aspect
<=1.80) {
558 arg
= DXR2_ASPECTRATIO_16_9
;
559 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] monitor aspect ratio 16:9\n");
561 arg
= DXR2_ASPECTRATIO_4_3
;
562 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] monitor aspect ratio 4:3\n");
564 ioctl(dxr2_fd
, DXR2_IOC_SET_OUTPUT_ASPECT_RATIO
, &arg
);
567 ioctl(dxr2_fd
, DXR2_IOC_SET_ASPECT_RATIO_MODE
, &arg
);
571 ioctl(dxr2_fd
, DXR2_IOC_SET_TV_MACROVISION_MODE
, &arg
);
573 ioctl(dxr2_fd
, DXR2_IOC_SET_TV_75IRE_MODE
, &arg
);
575 ioctl(dxr2_fd
, DXR2_IOC_SET_TV_BLACKWHITE_MODE
, &arg
);
576 arg
= interlaced_mode
;
577 ioctl(dxr2_fd
, DXR2_IOC_SET_TV_INTERLACED_MODE
, &arg
);
579 ioctl(dxr2_fd
, DXR2_IOC_SET_TV_PIXEL_MODE
, &arg
);
582 if (strcmp(norm
, "ntsc")==0)
583 arg
= DXR2_OUTPUTFORMAT_NTSC
;
584 else if (strcmp(norm
, "pal")==0) {
586 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] you want pal, but we play at 30 fps, selecting pal60 instead\n");
587 arg
= DXR2_OUTPUTFORMAT_PAL_60
;
589 } else arg
= DXR2_OUTPUTFORMAT_PAL_BDGHI
;
590 } else if (strcmp(norm
, "pal60")==0) {
592 arg
= DXR2_OUTPUTFORMAT_PAL_60
;
594 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] you want pal60, but we play at 25 fps, selecting pal instead\n");
595 arg
= DXR2_OUTPUTFORMAT_PAL_BDGHI
;
598 } else if (strcmp(norm
, "palm")==0)
599 arg
= DXR2_OUTPUTFORMAT_PAL_M
;
600 else if (strcmp(norm
, "paln")==0)
601 arg
= DXR2_OUTPUTFORMAT_PAL_N
;
602 else if (strcmp(norm
, "palnc")==0)
603 arg
= DXR2_OUTPUTFORMAT_PAL_Nc
;
605 mp_msg(MSGT_VO
,MSGL_WARN
,"[dxr2] invalid norm %s\n", norm
);
606 mp_msg(MSGT_VO
,MSGL_WARN
,"Valid values are ntsc,pal,pal60,palm,paln,palnc\n");
607 mp_msg(MSGT_VO
,MSGL_WARN
,"Using ntsc\n");
612 arg
= DXR2_OUTPUTFORMAT_NTSC
;
615 arg
= DXR2_OUTPUTFORMAT_PAL_BDGHI
;
619 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] output norm set to %s\n", norm
);
620 ioctl(dxr2_fd
, DXR2_IOC_SET_TV_OUTPUT_FORMAT
, &arg
);
624 arg
= DXR2_SUBPICTURE_ON
;
625 ioctl(dxr2_fd
,DXR2_IOC_ENABLE_SUBPICTURE
,&arg
);
626 arg3
.arg1
= DXR2_STREAM_SUBPICTURE
;
628 ioctl(dxr2_fd
, DXR2_IOC_SELECT_STREAM
, &arg3
);
632 ioctl(dxr2_fd
, DXR2_IOC_IEC958_OUTPUT_MODE
, &arg
);
633 arg
= DXR2_AUDIO_WIDTH_16
;
634 ioctl(dxr2_fd
, DXR2_IOC_SET_AUDIO_DATA_WIDTH
, &arg
);
635 arg
= DXR2_AUDIO_FREQ_48
;
636 ioctl(dxr2_fd
, DXR2_IOC_SET_AUDIO_SAMPLE_FREQUENCY
, &arg
);
637 arg3
.arg1
= DXR2_STREAM_AUDIO_LPCM
;
639 ioctl(dxr2_fd
, DXR2_IOC_SELECT_STREAM
, &arg3
);
641 ioctl(dxr2_fd
, DXR2_IOC_SET_AUDIO_VOLUME
, &arg
);
643 ioctl(dxr2_fd
, DXR2_IOC_AUDIO_MUTE
, &arg
);
647 //vo_fs = flags & VOFLAG_FULLSCREEN ? 1 : 0;
652 int cc
= vo_config_count
;
653 vo_config_count
= sub_config_count
;
654 // Load or detect the overlay stuff
655 if(!dxr2_setup_vga_params()) {
658 vo_config_count
= cc
;
661 // Does the sub vo support the x11 stuff
662 // Fix me : test the other x11 vo's and enable them
663 if(strcmp(sub_info
->short_name
,"x11") == 0)
668 // No window and no osd => we don't need any subdriver
669 if(!sub_vo_win
&& !ol_osd
) {
676 int i
,sub_flags
= VOFLAG_SWSCALE
| (flags
& VOFLAG_FULLSCREEN
);
677 if(sub_vo
->config(width
,height
,width
,height
,sub_flags
,
678 "MPlayer DXR2 render",IMGFMT_BGR24
) != 0) {
679 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] sub vo config failed => No X11 window\n");
686 // Feel free to try some other other color and report your results
693 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_COLOUR
, &oc
);
695 om
.arg
= DXR2_OVERLAY_WINDOW_COLOUR_KEY
;
696 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_MODE
,&om
);
697 sub_img
= malloc(width
*height
*3);
698 for(i
= 0 ; i
< width
*height
*3 ; i
+= 3) {
703 aspect
= ((1<<16)*width
+ height
/2)/height
;
705 dxr2_set_overlay_window();
708 vo_config_count
= cc
;
709 if(!sub_vo
) { // Fallback on non windowed overlay
710 vo_fs
= flags
& VOFLAG_FULLSCREEN
? 1 : 0;
711 om
.arg
= DXR2_OVERLAY_WINDOW_KEY
;
712 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_MODE
,&om
);
713 win
.arg1
= flags
& VOFLAG_FULLSCREEN
? vo_screenwidth
: width
;
714 win
.arg2
= flags
& VOFLAG_FULLSCREEN
? vo_screenheight
: height
;
715 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_DIMENSION
, &win
);
716 win
.arg1
= (vo_screenwidth
- win
.arg1
) / 2;
717 win
.arg2
= (vo_screenheight
- win
.arg2
) / 2;
718 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_POSITION
,&win
);
723 if (vo_ontop
) vo_x11_setlayer(mDisplay
, vo_window
, vo_ontop
);
726 if(ioctl(dxr2_fd
, DXR2_IOC_PLAY
, NULL
) == 0) {
733 static void clear_alpha(int x0
,int y0
, int w
,int h
) {
734 uint8_t* src
[] = { sub_img
, NULL
, NULL
};
735 int stride
[] = { movie_w
* 3, 0, 0 };
737 sub_vo
->draw_slice(src
,stride
,w
,h
,x0
,y0
);
740 static void draw_osd(void)
742 if(sub_vo
&& ol_osd
) {
743 vo_remove_text(movie_w
,movie_h
,clear_alpha
);
748 static int draw_frame(uint8_t * src
[])
750 vo_mpegpes_t
*p
=(vo_mpegpes_t
*)src
[0];
752 if(p
->id
== 0x1E0) {// Video
753 send_mpeg_ps_packet (p
->data
, p
->size
, p
->id
,
754 p
->timestamp
? p
->timestamp
: vo_pts
, 2, write_dxr2
);
755 } else if(p
->id
== 0x20) // Subtitles
756 dxr2_send_sub_packet(p
->data
, p
->size
, p
->id
, p
->timestamp
);
760 static void flip_page (void)
762 if(sub_vo
&& ol_osd
&& vo_osd_changed_flag
)
766 static int draw_slice( uint8_t *srcimg
[], int stride
[], int w
, int h
, int x0
, int y0
)
772 static int query_format(uint32_t format
)
774 if (format
==IMGFMT_MPEGPES
)
775 return VFCAP_CSP_SUPPORTED
|VFCAP_CSP_SUPPORTED_BY_HW
|VFCAP_TIMER
|VFCAP_SPU
;
780 static void uninit(void)
782 mp_msg(MSGT_VO
,MSGL_DBG2
, "VO: [dxr2] Uninitializing\n" );
798 int cc
= vo_config_count
;
799 vo_config_count
= sub_config_count
;
802 vo_config_count
= cc
;
807 static void check_events(void)
809 // I'd like to have this done in an x11 independent way
810 // It's because of this that we are limited to vo_x11 for windowed overlay :-(
811 #ifdef X11_FULLSCREEN
812 if(sub_vo
&& sub_vo_win
) {
813 int e
=vo_x11_check_events(mDisplay
);
814 if ( !(e
&VO_EVENT_RESIZE
) && !(e
&VO_EVENT_EXPOSE
) ) return;
815 XSetBackground(mDisplay
, vo_gc
, 0);
816 XClearWindow(mDisplay
, vo_window
);
817 dxr2_set_overlay_window();
822 static int preinit(const char *arg
) {
830 sub_config_count
= 0;
833 for(n
= 0 ; video_out_drivers
[n
] != NULL
; n
++) {
834 const vo_info_t
* vi
= video_out_drivers
[n
]->info
;
837 if(!video_out_drivers
[n
]->is_new
&& strcasecmp(arg
,vi
->short_name
) == 0)
840 sub_vo
= video_out_drivers
[n
]->old_functions
;
841 sub_info
= video_out_drivers
[n
]->info
;
843 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] We need a sub driver to initialize the overlay\n");
850 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] Sub driver '%s' not found => no overlay\n",arg
);
853 if(sub_vo
->preinit(NULL
) != 0) {
854 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] Sub vo %s preinit failed => no overlay\n",arg
);
858 uint32_t fmt
= IMGFMT_BGR24
;
859 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] Sub vo %s initialized\n",arg
);
860 if(sub_vo
->control(VOCTRL_QUERY_FORMAT
,&fmt
) <= 0) {
861 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] Sub vo %s doesn't support BGR24 => no overlay\n",arg
);
869 dxr2_fd
= open( "/dev/dxr2", O_WRONLY
);
871 mp_msg(MSGT_VO
,MSGL_V
, "VO: [dxr2] Error opening /dev/dxr2 for writing!\n" );
876 uCodeFD
= open(ucode
, O_RDONLY
);
877 else for (n
=0; ucodesearchpath
[n
] != NULL
; n
++) {
878 mp_msg(MSGT_VO
,MSGL_V
,"VO: [dxr2] Looking for microcode in %s... ",
880 if ((uCodeFD
= open(ucodesearchpath
[n
], O_RDONLY
))>0) {
881 mp_msg(MSGT_VO
,MSGL_V
,"ok\n");
884 mp_msg(MSGT_VO
,MSGL_V
,"failed (%s)\n", strerror(errno
));
888 mp_msg(MSGT_VO
,MSGL_ERR
,"VO: [dxr2] Could not open microcode\n");
892 uCodeSize
= lseek(uCodeFD
, 0, SEEK_END
);
893 if ((uCode
= malloc(uCodeSize
+ 4)) == NULL
) {
895 mp_msg(MSGT_VO
,MSGL_FATAL
,"VO: [dxr2] Could not allocate memory for uCode: %s\n", strerror(errno
));
898 lseek(uCodeFD
, 0, SEEK_SET
);
899 if (read(uCodeFD
, uCode
+4, uCodeSize
) != uCodeSize
) {
901 mp_msg(MSGT_VO
,MSGL_ERR
,"VO: [dxr2] Could not read uCode uCode: %s\n", strerror(errno
));
905 uCode
->uCodeLength
= uCodeSize
;
908 ioctl(dxr2_fd
, DXR2_IOC_INIT_ZIVADS
, uCode
);
911 ioctl(dxr2_fd
, DXR2_IOC_RESET
, NULL
);
919 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_CROPPING
, &crop
);
924 static int control(uint32_t request
, void *data
)
927 case VOCTRL_QUERY_FORMAT
:
928 return query_format(*((uint32_t*)data
));
930 ioctl(dxr2_fd
,DXR2_IOC_PAUSE
, NULL
);
933 ioctl(dxr2_fd
, DXR2_IOC_PLAY
, NULL
);
937 ioctl(dxr2_fd
, DXR2_IOC_PLAY
, NULL
);
942 case VOCTRL_FULLSCREEN
:
946 int r
= sub_vo
->control(VOCTRL_FULLSCREEN
,0);
947 if(r
== VO_TRUE
&& !sub_vo_win
)
948 dxr2_set_overlay_window();
953 win
.arg1
= vo_fs
? vo_screenwidth
: movie_w
;
954 win
.arg2
= vo_fs
? vo_screenheight
: movie_h
;
955 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_DIMENSION
, &win
);
956 win
.arg1
= (vo_screenwidth
- win
.arg1
) / 2;
957 win
.arg2
= (vo_screenheight
- win
.arg2
) / 2;
958 ioctl(dxr2_fd
, DXR2_IOC_SET_OVERLAY_POSITION
,&win
);
961 case VOCTRL_SET_SPU_PALETTE
: {
962 if(ioctl(dxr2_fd
,DXR2_IOC_SET_SUBPICTURE_PALETTE
,data
) < 0) {
963 mp_msg(MSGT_VO
,MSGL_WARN
,"VO: [dxr2] SPU palette loading failed\n");