1 //=================== VideoCD ==========================
2 #if defined(linux) || defined(sun) || defined(__bsdi__)
4 typedef struct mp_vcd_priv_st mp_vcd_priv_t
;
7 #include <linux/cdrom.h>
10 static int sun_vcd_read(mp_vcd_priv_t
*, int*);
11 #elif defined(__bsdi__)
15 struct mp_vcd_priv_st
{
17 struct cdrom_tocentry entry
;
18 char buf
[VCD_SECTOR_SIZE
];
21 static inline void vcd_set_msf(mp_vcd_priv_t
* vcd
, unsigned int sect
){
22 vcd
->entry
.cdte_addr
.msf
.frame
=sect
%75;
24 vcd
->entry
.cdte_addr
.msf
.second
=sect
%60;
26 vcd
->entry
.cdte_addr
.msf
.minute
=sect
;
29 static inline unsigned int vcd_get_msf(mp_vcd_priv_t
* vcd
){
30 return vcd
->entry
.cdte_addr
.msf
.frame
+
31 (vcd
->entry
.cdte_addr
.msf
.second
+
32 vcd
->entry
.cdte_addr
.msf
.minute
*60)*75;
35 int vcd_seek_to_track(mp_vcd_priv_t
* vcd
,int track
){
36 vcd
->entry
.cdte_format
= CDROM_MSF
;
37 vcd
->entry
.cdte_track
= track
;
38 if (ioctl(vcd
->fd
, CDROMREADTOCENTRY
, &vcd
->entry
)) {
39 mp_msg(MSGT_STREAM
,MSGL_ERR
,"ioctl dif1: %s\n",strerror(errno
));
42 return VCD_SECTOR_DATA
*vcd_get_msf(vcd
);
45 int vcd_get_track_end(mp_vcd_priv_t
* vcd
,int track
){
46 struct cdrom_tochdr tochdr
;
47 if (ioctl(vcd
->fd
,CDROMREADTOCHDR
,&tochdr
)==-1) {
48 mp_msg(MSGT_STREAM
,MSGL_ERR
,"read CDROM toc header: %s\n",strerror(errno
));
51 vcd
->entry
.cdte_format
= CDROM_MSF
;
52 vcd
->entry
.cdte_track
= track
<tochdr
.cdth_trk1
?(track
+1):CDROM_LEADOUT
;
53 if (ioctl(vcd
->fd
, CDROMREADTOCENTRY
, &vcd
->entry
)) {
54 mp_msg(MSGT_STREAM
,MSGL_ERR
,"ioctl dif2: %s\n",strerror(errno
));
57 return VCD_SECTOR_DATA
*vcd_get_msf(vcd
);
60 mp_vcd_priv_t
* vcd_read_toc(int fd
){
61 struct cdrom_tochdr tochdr
;
63 int i
, min
= 0, sec
= 0, frame
= 0;
64 if (ioctl(fd
,CDROMREADTOCHDR
,&tochdr
)==-1) {
65 mp_msg(MSGT_OPEN
,MSGL_ERR
,"read CDROM toc header: %s\n",strerror(errno
));
68 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_START_TRACK=%d\n", tochdr
.cdth_trk0
);
69 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_END_TRACK=%d\n", tochdr
.cdth_trk1
);
70 for (i
=tochdr
.cdth_trk0
; i
<=tochdr
.cdth_trk1
+ 1; i
++){
71 struct cdrom_tocentry tocentry
;
73 tocentry
.cdte_track
= i
<=tochdr
.cdth_trk1
? i
: CDROM_LEADOUT
;
74 tocentry
.cdte_format
= CDROM_MSF
;
76 if (ioctl(fd
,CDROMREADTOCENTRY
,&tocentry
)==-1) {
77 mp_msg(MSGT_OPEN
,MSGL_ERR
,"read CDROM toc entry: %s\n",strerror(errno
));
81 if (i
<=tochdr
.cdth_trk1
)
82 mp_msg(MSGT_OPEN
,MSGL_INFO
,"track %02d: adr=%d ctrl=%d format=%d %02d:%02d:%02d mode: %d\n",
83 (int)tocentry
.cdte_track
,
84 (int)tocentry
.cdte_adr
,
85 (int)tocentry
.cdte_ctrl
,
86 (int)tocentry
.cdte_format
,
87 (int)tocentry
.cdte_addr
.msf
.minute
,
88 (int)tocentry
.cdte_addr
.msf
.second
,
89 (int)tocentry
.cdte_addr
.msf
.frame
,
90 (int)tocentry
.cdte_datamode
93 if (mp_msg_test(MSGT_IDENTIFY
, MSGL_INFO
))
95 if (i
> tochdr
.cdth_trk0
)
97 min
= tocentry
.cdte_addr
.msf
.minute
- min
;
98 sec
= tocentry
.cdte_addr
.msf
.second
- sec
;
99 frame
= tocentry
.cdte_addr
.msf
.frame
- frame
;
110 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_TRACK_%d_MSF=%02d:%02d:%02d\n", i
- 1, min
, sec
, frame
);
112 min
= tocentry
.cdte_addr
.msf
.minute
;
113 sec
= tocentry
.cdte_addr
.msf
.second
;
114 frame
= tocentry
.cdte_addr
.msf
.frame
;
117 vcd
= malloc(sizeof(mp_vcd_priv_t
));
122 static int vcd_read(mp_vcd_priv_t
* vcd
,char *mem
){
123 #if defined(linux) || defined(__bsdi__)
124 memcpy(vcd
->buf
,&vcd
->entry
.cdte_addr
.msf
,sizeof(struct cdrom_msf
));
125 if(ioctl(vcd
->fd
,CDROMREADRAW
,vcd
->buf
)==-1) return 0; // EOF?
126 memcpy(mem
,&vcd
->buf
[VCD_SECTOR_OFFS
],VCD_SECTOR_DATA
);
130 if (sun_vcd_read(vcd
->fd
, &offset
) <= 0) return 0;
131 memcpy(mem
,&vcd
->buf
[offset
],VCD_SECTOR_DATA
);
135 vcd
->entry
.cdte_addr
.msf
.frame
++;
136 if (vcd
->entry
.cdte_addr
.msf
.frame
==75){
137 vcd
->entry
.cdte_addr
.msf
.frame
=0;
138 vcd
->entry
.cdte_addr
.msf
.second
++;
139 if (vcd
->entry
.cdte_addr
.msf
.second
==60){
140 vcd
->entry
.cdte_addr
.msf
.second
=0;
141 vcd
->entry
.cdte_addr
.msf
.minute
++;
145 return VCD_SECTOR_DATA
;
150 #include <sys/scsi/generic/commands.h>
151 #include <sys/scsi/impl/uscsi.h>
153 #define SUN_XAREAD 1 /*fails on atapi drives*/
154 #define SUN_MODE2READ 2 /*fails on atapi drives*/
155 #define SUN_SCSIREAD 3
156 #define SUN_VCDREAD SUN_SCSIREAD
158 static int sun_vcd_read(mp_vcd_priv_t
* vcd
, int *offset
)
160 #if SUN_VCDREAD == SUN_XAREAD
161 struct cdrom_cdxa cdxa
;
162 cdxa
.cdxa_addr
= vcd_get_msf(vcd
);
163 cdxa
.cdxa_length
= 1;
164 cdxa
.cdxa_data
= vcd
->buf
;
165 cdxa
.cdxa_format
= CDROM_XA_SECTOR_DATA
;
167 if(ioctl(vcd
->fd
,CDROMCDXA
,&cdxa
)==-1) {
168 mp_msg(MSGT_STREAM
,MSGL_ERR
,"CDROMCDXA: %s\n",strerror(errno
));
172 #elif SUN_VCDREAD == SUN_MODE2READ
173 struct cdrom_read cdread
;
174 cdread
.cdread_lba
= 4*vcd_get_msf(vcd
);
175 cdread
.cdread_bufaddr
= vcd
->buf
;
176 cdread
.cdread_buflen
= 2336;
178 if(ioctl(vcd
->fd
,CDROMREADMODE2
,&cdread
)==-1) {
179 mp_msg(MSGT_STREAM
,MSGL_ERR
,"CDROMREADMODE2: %s\n",strerror(errno
));
183 #elif SUN_VCDREAD == SUN_SCSIREAD
186 int lba
= vcd_get_msf(vcd
);
189 int sync
, header_code
, user_data
, edc_ecc
, error_field
;
192 /* sector_type = 3; *//* mode2 */
193 sector_type
= 5; /* mode2/form2 */
201 memset(&cdb
, 0, sizeof(cdb
));
202 memset(&sc
, 0, sizeof(sc
));
204 cdb
.cdb_opaque
[1] = (sector_type
) << 2;
205 cdb
.cdb_opaque
[2] = (lba
>> 24) & 0xff;
206 cdb
.cdb_opaque
[3] = (lba
>> 16) & 0xff;
207 cdb
.cdb_opaque
[4] = (lba
>> 8) & 0xff;
208 cdb
.cdb_opaque
[5] = lba
& 0xff;
209 cdb
.cdb_opaque
[6] = (blocks
>> 16) & 0xff;
210 cdb
.cdb_opaque
[7] = (blocks
>> 8) & 0xff;
211 cdb
.cdb_opaque
[8] = blocks
& 0xff;
212 cdb
.cdb_opaque
[9] = (sync
<< 7) |
217 cdb
.cdb_opaque
[10] = sub_channel
;
219 sc
.uscsi_cdb
= (caddr_t
)&cdb
;
220 sc
.uscsi_cdblen
= 12;
221 sc
.uscsi_bufaddr
= vcd
->buf
;
222 sc
.uscsi_buflen
= 2336;
223 sc
.uscsi_flags
= USCSI_ISOLATE
| USCSI_READ
;
224 sc
.uscsi_timeout
= 20;
225 if (ioctl(vcd
->fd
, USCSICMD
, &sc
)) {
226 mp_msg(MSGT_STREAM
,MSGL_ERR
,"USCSICMD: READ CD: %s\n",strerror(errno
));
229 if (sc
.uscsi_status
) {
230 mp_msg(MSGT_STREAM
,MSGL_ERR
,"scsi command failed with status %d\n", sc
.uscsi_status
);
241 #else /* linux || sun || __bsdi__ */
243 #error vcd is not yet supported on this arch...