1 #ifndef MPLAYER_VCD_READ_H
2 #define MPLAYER_VCD_READ_H
10 #include "libavutil/intreadwrite.h"
11 //=================== VideoCD ==========================
12 #if defined(__linux__) || defined(sun) || defined(__bsdi__)
14 typedef struct mp_vcd_priv_st mp_vcd_priv_t
;
16 #if defined(__linux__)
17 #include <linux/cdrom.h>
20 static int sun_vcd_read(mp_vcd_priv_t
*, int*);
21 #elif defined(__bsdi__)
25 struct mp_vcd_priv_st
{
27 struct cdrom_tocentry entry
;
28 char buf
[VCD_SECTOR_SIZE
];
29 struct cdrom_tochdr tochdr
;
32 static inline void vcd_set_msf(mp_vcd_priv_t
* vcd
, unsigned int sect
){
34 vcd
->entry
.cdte_addr
.msf
.frame
=sect
%75;
36 vcd
->entry
.cdte_addr
.msf
.second
=sect
%60;
38 vcd
->entry
.cdte_addr
.msf
.minute
=sect
;
41 static inline unsigned int vcd_get_msf(mp_vcd_priv_t
* vcd
){
42 return vcd
->entry
.cdte_addr
.msf
.frame
+
43 (vcd
->entry
.cdte_addr
.msf
.second
+
44 vcd
->entry
.cdte_addr
.msf
.minute
*60)*75 - 150;
47 int vcd_seek_to_track(mp_vcd_priv_t
* vcd
,int track
){
48 vcd
->entry
.cdte_format
= CDROM_MSF
;
49 vcd
->entry
.cdte_track
= track
;
50 if (ioctl(vcd
->fd
, CDROMREADTOCENTRY
, &vcd
->entry
)) {
51 mp_msg(MSGT_STREAM
,MSGL_ERR
,"ioctl dif1: %s\n",strerror(errno
));
54 return VCD_SECTOR_DATA
*vcd_get_msf(vcd
);
57 int vcd_get_track_end(mp_vcd_priv_t
* vcd
,int track
){
58 vcd
->entry
.cdte_format
= CDROM_MSF
;
59 vcd
->entry
.cdte_track
= track
<vcd
->tochdr
.cdth_trk1
?(track
+1):CDROM_LEADOUT
;
60 if (ioctl(vcd
->fd
, CDROMREADTOCENTRY
, &vcd
->entry
)) {
61 mp_msg(MSGT_STREAM
,MSGL_ERR
,"ioctl dif2: %s\n",strerror(errno
));
64 return VCD_SECTOR_DATA
*vcd_get_msf(vcd
);
67 mp_vcd_priv_t
* vcd_read_toc(int fd
){
68 struct cdrom_tochdr tochdr
;
70 int i
, min
= 0, sec
= 0, frame
= 0;
71 if (ioctl(fd
,CDROMREADTOCHDR
,&tochdr
)==-1) {
72 mp_msg(MSGT_OPEN
,MSGL_ERR
,"read CDROM toc header: %s\n",strerror(errno
));
75 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_START_TRACK=%d\n", tochdr
.cdth_trk0
);
76 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_END_TRACK=%d\n", tochdr
.cdth_trk1
);
77 for (i
=tochdr
.cdth_trk0
; i
<=tochdr
.cdth_trk1
+ 1; i
++){
78 struct cdrom_tocentry tocentry
;
80 tocentry
.cdte_track
= i
<=tochdr
.cdth_trk1
? i
: CDROM_LEADOUT
;
81 tocentry
.cdte_format
= CDROM_MSF
;
83 if (ioctl(fd
,CDROMREADTOCENTRY
,&tocentry
)==-1) {
84 mp_msg(MSGT_OPEN
,MSGL_ERR
,"read CDROM toc entry: %s\n",strerror(errno
));
88 if (i
<=tochdr
.cdth_trk1
)
89 mp_msg(MSGT_OPEN
,MSGL_INFO
,"track %02d: adr=%d ctrl=%d format=%d %02d:%02d:%02d mode: %d\n",
90 (int)tocentry
.cdte_track
,
91 (int)tocentry
.cdte_adr
,
92 (int)tocentry
.cdte_ctrl
,
93 (int)tocentry
.cdte_format
,
94 (int)tocentry
.cdte_addr
.msf
.minute
,
95 (int)tocentry
.cdte_addr
.msf
.second
,
96 (int)tocentry
.cdte_addr
.msf
.frame
,
97 (int)tocentry
.cdte_datamode
100 if (mp_msg_test(MSGT_IDENTIFY
, MSGL_INFO
))
102 if (i
> tochdr
.cdth_trk0
)
104 min
= tocentry
.cdte_addr
.msf
.minute
- min
;
105 sec
= tocentry
.cdte_addr
.msf
.second
- sec
;
106 frame
= tocentry
.cdte_addr
.msf
.frame
- frame
;
117 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_TRACK_%d_MSF=%02d:%02d:%02d\n", i
- 1, min
, sec
, frame
);
119 min
= tocentry
.cdte_addr
.msf
.minute
;
120 sec
= tocentry
.cdte_addr
.msf
.second
;
121 frame
= tocentry
.cdte_addr
.msf
.frame
;
124 vcd
= malloc(sizeof(mp_vcd_priv_t
));
126 vcd
->tochdr
= tochdr
;
130 static int vcd_read(mp_vcd_priv_t
* vcd
,char *mem
){
131 #if defined(__linux__) || defined(__bsdi__)
132 memcpy(vcd
->buf
,&vcd
->entry
.cdte_addr
.msf
,sizeof(struct cdrom_msf
));
133 if(ioctl(vcd
->fd
,CDROMREADRAW
,vcd
->buf
)==-1) return 0; // EOF?
134 memcpy(mem
,&vcd
->buf
[VCD_SECTOR_OFFS
],VCD_SECTOR_DATA
);
138 if (sun_vcd_read(vcd
, &offset
) <= 0) return 0;
139 memcpy(mem
,&vcd
->buf
[offset
],VCD_SECTOR_DATA
);
143 vcd
->entry
.cdte_addr
.msf
.frame
++;
144 if (vcd
->entry
.cdte_addr
.msf
.frame
==75){
145 vcd
->entry
.cdte_addr
.msf
.frame
=0;
146 vcd
->entry
.cdte_addr
.msf
.second
++;
147 if (vcd
->entry
.cdte_addr
.msf
.second
==60){
148 vcd
->entry
.cdte_addr
.msf
.second
=0;
149 vcd
->entry
.cdte_addr
.msf
.minute
++;
153 return VCD_SECTOR_DATA
;
158 #include <sys/scsi/generic/commands.h>
159 #include <sys/scsi/impl/uscsi.h>
161 #define SUN_XAREAD 1 /*fails on atapi drives*/
162 #define SUN_MODE2READ 2 /*fails on atapi drives*/
163 #define SUN_SCSIREAD 3
164 #define SUN_VCDREAD SUN_SCSIREAD
166 static int sun_vcd_read(mp_vcd_priv_t
* vcd
, int *offset
)
168 #if SUN_VCDREAD == SUN_XAREAD
169 struct cdrom_cdxa cdxa
;
170 cdxa
.cdxa_addr
= vcd_get_msf(vcd
);
171 cdxa
.cdxa_length
= 1;
172 cdxa
.cdxa_data
= vcd
->buf
;
173 cdxa
.cdxa_format
= CDROM_XA_SECTOR_DATA
;
175 if(ioctl(vcd
->fd
,CDROMCDXA
,&cdxa
)==-1) {
176 mp_msg(MSGT_STREAM
,MSGL_ERR
,"CDROMCDXA: %s\n",strerror(errno
));
180 #elif SUN_VCDREAD == SUN_MODE2READ
181 struct cdrom_read cdread
;
182 cdread
.cdread_lba
= 4*vcd_get_msf(vcd
);
183 cdread
.cdread_bufaddr
= vcd
->buf
;
184 cdread
.cdread_buflen
= 2336;
186 if(ioctl(vcd
->fd
,CDROMREADMODE2
,&cdread
)==-1) {
187 mp_msg(MSGT_STREAM
,MSGL_ERR
,"CDROMREADMODE2: %s\n",strerror(errno
));
191 #elif SUN_VCDREAD == SUN_SCSIREAD
194 int lba
= vcd_get_msf(vcd
);
197 memset(&cdb
, 0, sizeof(cdb
));
198 memset(&sc
, 0, sizeof(sc
));
200 cdb
.cdb_opaque
[1] = 5 << 2; // mode2 / form2
201 AV_WB32(&cdb
.cdb_opaque
[2], lba
);
202 AV_WB24(&cdb
.cdb_opaque
[6], blocks
);
203 cdb
.cdb_opaque
[9] = 1 << 4; // user data only
204 cdb
.cdb_opaque
[10] = 0; // subchannel
206 sc
.uscsi_cdb
= (caddr_t
)&cdb
;
207 sc
.uscsi_cdblen
= 12;
208 sc
.uscsi_bufaddr
= vcd
->buf
;
209 sc
.uscsi_buflen
= 2336;
210 sc
.uscsi_flags
= USCSI_ISOLATE
| USCSI_READ
;
211 sc
.uscsi_timeout
= 20;
212 if (ioctl(vcd
->fd
, USCSICMD
, &sc
)) {
213 mp_msg(MSGT_STREAM
,MSGL_ERR
,"USCSICMD: READ CD: %s\n",strerror(errno
));
216 if (sc
.uscsi_status
) {
217 mp_msg(MSGT_STREAM
,MSGL_ERR
,"scsi command failed with status %d\n", sc
.uscsi_status
);
228 #else /* __linux__ || sun || __bsdi__ */
230 #error vcd is not yet supported on this arch...
234 #endif /* MPLAYER_VCD_READ_H */