1 #include "libavutil/intreadwrite.h"
2 //=================== VideoCD ==========================
3 #if defined(linux) || defined(sun) || defined(__bsdi__)
5 typedef struct mp_vcd_priv_st mp_vcd_priv_t
;
8 #include <linux/cdrom.h>
11 static int sun_vcd_read(mp_vcd_priv_t
*, int*);
12 #elif defined(__bsdi__)
16 struct mp_vcd_priv_st
{
18 struct cdrom_tocentry entry
;
19 char buf
[VCD_SECTOR_SIZE
];
20 struct cdrom_tochdr tochdr
;
23 static inline void vcd_set_msf(mp_vcd_priv_t
* vcd
, unsigned int sect
){
25 vcd
->entry
.cdte_addr
.msf
.frame
=sect
%75;
27 vcd
->entry
.cdte_addr
.msf
.second
=sect
%60;
29 vcd
->entry
.cdte_addr
.msf
.minute
=sect
;
32 static inline unsigned int vcd_get_msf(mp_vcd_priv_t
* vcd
){
33 return vcd
->entry
.cdte_addr
.msf
.frame
+
34 (vcd
->entry
.cdte_addr
.msf
.second
+
35 vcd
->entry
.cdte_addr
.msf
.minute
*60)*75 - 150;
38 int vcd_seek_to_track(mp_vcd_priv_t
* vcd
,int track
){
39 vcd
->entry
.cdte_format
= CDROM_MSF
;
40 vcd
->entry
.cdte_track
= track
;
41 if (ioctl(vcd
->fd
, CDROMREADTOCENTRY
, &vcd
->entry
)) {
42 mp_msg(MSGT_STREAM
,MSGL_ERR
,"ioctl dif1: %s\n",strerror(errno
));
45 return VCD_SECTOR_DATA
*vcd_get_msf(vcd
);
48 int vcd_get_track_end(mp_vcd_priv_t
* vcd
,int track
){
49 vcd
->entry
.cdte_format
= CDROM_MSF
;
50 vcd
->entry
.cdte_track
= track
<vcd
->tochdr
.cdth_trk1
?(track
+1):CDROM_LEADOUT
;
51 if (ioctl(vcd
->fd
, CDROMREADTOCENTRY
, &vcd
->entry
)) {
52 mp_msg(MSGT_STREAM
,MSGL_ERR
,"ioctl dif2: %s\n",strerror(errno
));
55 return VCD_SECTOR_DATA
*vcd_get_msf(vcd
);
58 mp_vcd_priv_t
* vcd_read_toc(int fd
){
59 struct cdrom_tochdr tochdr
;
61 int i
, min
= 0, sec
= 0, frame
= 0;
62 if (ioctl(fd
,CDROMREADTOCHDR
,&tochdr
)==-1) {
63 mp_msg(MSGT_OPEN
,MSGL_ERR
,"read CDROM toc header: %s\n",strerror(errno
));
66 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_START_TRACK=%d\n", tochdr
.cdth_trk0
);
67 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_END_TRACK=%d\n", tochdr
.cdth_trk1
);
68 for (i
=tochdr
.cdth_trk0
; i
<=tochdr
.cdth_trk1
+ 1; i
++){
69 struct cdrom_tocentry tocentry
;
71 tocentry
.cdte_track
= i
<=tochdr
.cdth_trk1
? i
: CDROM_LEADOUT
;
72 tocentry
.cdte_format
= CDROM_MSF
;
74 if (ioctl(fd
,CDROMREADTOCENTRY
,&tocentry
)==-1) {
75 mp_msg(MSGT_OPEN
,MSGL_ERR
,"read CDROM toc entry: %s\n",strerror(errno
));
79 if (i
<=tochdr
.cdth_trk1
)
80 mp_msg(MSGT_OPEN
,MSGL_INFO
,"track %02d: adr=%d ctrl=%d format=%d %02d:%02d:%02d mode: %d\n",
81 (int)tocentry
.cdte_track
,
82 (int)tocentry
.cdte_adr
,
83 (int)tocentry
.cdte_ctrl
,
84 (int)tocentry
.cdte_format
,
85 (int)tocentry
.cdte_addr
.msf
.minute
,
86 (int)tocentry
.cdte_addr
.msf
.second
,
87 (int)tocentry
.cdte_addr
.msf
.frame
,
88 (int)tocentry
.cdte_datamode
91 if (mp_msg_test(MSGT_IDENTIFY
, MSGL_INFO
))
93 if (i
> tochdr
.cdth_trk0
)
95 min
= tocentry
.cdte_addr
.msf
.minute
- min
;
96 sec
= tocentry
.cdte_addr
.msf
.second
- sec
;
97 frame
= tocentry
.cdte_addr
.msf
.frame
- frame
;
108 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_TRACK_%d_MSF=%02d:%02d:%02d\n", i
- 1, min
, sec
, frame
);
110 min
= tocentry
.cdte_addr
.msf
.minute
;
111 sec
= tocentry
.cdte_addr
.msf
.second
;
112 frame
= tocentry
.cdte_addr
.msf
.frame
;
115 vcd
= malloc(sizeof(mp_vcd_priv_t
));
117 vcd
->tochdr
= tochdr
;
121 static int vcd_read(mp_vcd_priv_t
* vcd
,char *mem
){
122 #if defined(linux) || defined(__bsdi__)
123 memcpy(vcd
->buf
,&vcd
->entry
.cdte_addr
.msf
,sizeof(struct cdrom_msf
));
124 if(ioctl(vcd
->fd
,CDROMREADRAW
,vcd
->buf
)==-1) return 0; // EOF?
125 memcpy(mem
,&vcd
->buf
[VCD_SECTOR_OFFS
],VCD_SECTOR_DATA
);
129 if (sun_vcd_read(vcd
, &offset
) <= 0) return 0;
130 memcpy(mem
,&vcd
->buf
[offset
],VCD_SECTOR_DATA
);
134 vcd
->entry
.cdte_addr
.msf
.frame
++;
135 if (vcd
->entry
.cdte_addr
.msf
.frame
==75){
136 vcd
->entry
.cdte_addr
.msf
.frame
=0;
137 vcd
->entry
.cdte_addr
.msf
.second
++;
138 if (vcd
->entry
.cdte_addr
.msf
.second
==60){
139 vcd
->entry
.cdte_addr
.msf
.second
=0;
140 vcd
->entry
.cdte_addr
.msf
.minute
++;
144 return VCD_SECTOR_DATA
;
149 #include <sys/scsi/generic/commands.h>
150 #include <sys/scsi/impl/uscsi.h>
152 #define SUN_XAREAD 1 /*fails on atapi drives*/
153 #define SUN_MODE2READ 2 /*fails on atapi drives*/
154 #define SUN_SCSIREAD 3
155 #define SUN_VCDREAD SUN_SCSIREAD
157 static int sun_vcd_read(mp_vcd_priv_t
* vcd
, int *offset
)
159 #if SUN_VCDREAD == SUN_XAREAD
160 struct cdrom_cdxa cdxa
;
161 cdxa
.cdxa_addr
= vcd_get_msf(vcd
);
162 cdxa
.cdxa_length
= 1;
163 cdxa
.cdxa_data
= vcd
->buf
;
164 cdxa
.cdxa_format
= CDROM_XA_SECTOR_DATA
;
166 if(ioctl(vcd
->fd
,CDROMCDXA
,&cdxa
)==-1) {
167 mp_msg(MSGT_STREAM
,MSGL_ERR
,"CDROMCDXA: %s\n",strerror(errno
));
171 #elif SUN_VCDREAD == SUN_MODE2READ
172 struct cdrom_read cdread
;
173 cdread
.cdread_lba
= 4*vcd_get_msf(vcd
);
174 cdread
.cdread_bufaddr
= vcd
->buf
;
175 cdread
.cdread_buflen
= 2336;
177 if(ioctl(vcd
->fd
,CDROMREADMODE2
,&cdread
)==-1) {
178 mp_msg(MSGT_STREAM
,MSGL_ERR
,"CDROMREADMODE2: %s\n",strerror(errno
));
182 #elif SUN_VCDREAD == SUN_SCSIREAD
185 int lba
= vcd_get_msf(vcd
);
188 memset(&cdb
, 0, sizeof(cdb
));
189 memset(&sc
, 0, sizeof(sc
));
191 cdb
.cdb_opaque
[1] = 5 << 2; // mode2 / form2
192 AV_WB32(&cdb
.cdb_opaque
[2], lba
);
193 AV_WB24(&cdb
.cdb_opaque
[6], blocks
);
194 cdb
.cdb_opaque
[9] = 1 << 4; // user data only
195 cdb
.cdb_opaque
[10] = 0; // subchannel
197 sc
.uscsi_cdb
= (caddr_t
)&cdb
;
198 sc
.uscsi_cdblen
= 12;
199 sc
.uscsi_bufaddr
= vcd
->buf
;
200 sc
.uscsi_buflen
= 2336;
201 sc
.uscsi_flags
= USCSI_ISOLATE
| USCSI_READ
;
202 sc
.uscsi_timeout
= 20;
203 if (ioctl(vcd
->fd
, USCSICMD
, &sc
)) {
204 mp_msg(MSGT_STREAM
,MSGL_ERR
,"USCSICMD: READ CD: %s\n",strerror(errno
));
207 if (sc
.uscsi_status
) {
208 mp_msg(MSGT_STREAM
,MSGL_ERR
,"scsi command failed with status %d\n", sc
.uscsi_status
);
219 #else /* linux || sun || __bsdi__ */
221 #error vcd is not yet supported on this arch...