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 #ifndef MPLAYER_VCD_READ_H
20 #define MPLAYER_VCD_READ_H
25 #include <sys/ioctl.h>
27 #include <libavutil/intreadwrite.h>
31 //=================== VideoCD ==========================
32 #if defined(__linux__) || defined(sun) || defined(__bsdi__)
34 typedef struct mp_vcd_priv_st mp_vcd_priv_t
;
36 #if defined(__linux__)
37 #include <linux/cdrom.h>
40 static int sun_vcd_read(mp_vcd_priv_t
*, int*);
41 #elif defined(__bsdi__)
45 struct mp_vcd_priv_st
{
47 struct cdrom_tocentry entry
;
48 char buf
[VCD_SECTOR_SIZE
];
49 struct cdrom_tochdr tochdr
;
52 static inline void vcd_set_msf(mp_vcd_priv_t
* vcd
, unsigned int sect
){
54 vcd
->entry
.cdte_addr
.msf
.frame
=sect
%75;
56 vcd
->entry
.cdte_addr
.msf
.second
=sect
%60;
58 vcd
->entry
.cdte_addr
.msf
.minute
=sect
;
61 static inline unsigned int vcd_get_msf(mp_vcd_priv_t
* vcd
){
62 return vcd
->entry
.cdte_addr
.msf
.frame
+
63 (vcd
->entry
.cdte_addr
.msf
.second
+
64 vcd
->entry
.cdte_addr
.msf
.minute
*60)*75 - 150;
67 static int vcd_seek_to_track(mp_vcd_priv_t
* vcd
, int track
)
69 vcd
->entry
.cdte_format
= CDROM_MSF
;
70 vcd
->entry
.cdte_track
= track
;
71 if (ioctl(vcd
->fd
, CDROMREADTOCENTRY
, &vcd
->entry
)) {
72 mp_msg(MSGT_STREAM
,MSGL_ERR
,"ioctl dif1: %s\n",strerror(errno
));
75 return VCD_SECTOR_DATA
*vcd_get_msf(vcd
);
78 static int vcd_get_track_end(mp_vcd_priv_t
* vcd
,int track
){
79 vcd
->entry
.cdte_format
= CDROM_MSF
;
80 vcd
->entry
.cdte_track
= track
<vcd
->tochdr
.cdth_trk1
?(track
+1):CDROM_LEADOUT
;
81 if (ioctl(vcd
->fd
, CDROMREADTOCENTRY
, &vcd
->entry
)) {
82 mp_msg(MSGT_STREAM
,MSGL_ERR
,"ioctl dif2: %s\n",strerror(errno
));
85 return VCD_SECTOR_DATA
*vcd_get_msf(vcd
);
88 static mp_vcd_priv_t
* vcd_read_toc(int fd
){
89 struct cdrom_tochdr tochdr
;
91 int i
, min
= 0, sec
= 0, frame
= 0;
92 if (ioctl(fd
,CDROMREADTOCHDR
,&tochdr
)==-1) {
93 mp_msg(MSGT_OPEN
,MSGL_ERR
,"read CDROM toc header: %s\n",strerror(errno
));
96 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_START_TRACK=%d\n", tochdr
.cdth_trk0
);
97 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_END_TRACK=%d\n", tochdr
.cdth_trk1
);
98 for (i
=tochdr
.cdth_trk0
; i
<=tochdr
.cdth_trk1
+ 1; i
++){
99 struct cdrom_tocentry tocentry
;
101 tocentry
.cdte_track
= i
<=tochdr
.cdth_trk1
? i
: CDROM_LEADOUT
;
102 tocentry
.cdte_format
= CDROM_MSF
;
104 if (ioctl(fd
,CDROMREADTOCENTRY
,&tocentry
)==-1) {
105 mp_msg(MSGT_OPEN
,MSGL_ERR
,"read CDROM toc entry: %s\n",strerror(errno
));
109 if (i
<=tochdr
.cdth_trk1
)
110 mp_msg(MSGT_OPEN
,MSGL_INFO
,"track %02d: adr=%d ctrl=%d format=%d %02d:%02d:%02d mode: %d\n",
111 (int)tocentry
.cdte_track
,
112 (int)tocentry
.cdte_adr
,
113 (int)tocentry
.cdte_ctrl
,
114 (int)tocentry
.cdte_format
,
115 (int)tocentry
.cdte_addr
.msf
.minute
,
116 (int)tocentry
.cdte_addr
.msf
.second
,
117 (int)tocentry
.cdte_addr
.msf
.frame
,
118 (int)tocentry
.cdte_datamode
121 if (mp_msg_test(MSGT_IDENTIFY
, MSGL_INFO
))
123 if (i
> tochdr
.cdth_trk0
)
125 min
= tocentry
.cdte_addr
.msf
.minute
- min
;
126 sec
= tocentry
.cdte_addr
.msf
.second
- sec
;
127 frame
= tocentry
.cdte_addr
.msf
.frame
- frame
;
138 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_TRACK_%d_MSF=%02d:%02d:%02d\n", i
- 1, min
, sec
, frame
);
140 min
= tocentry
.cdte_addr
.msf
.minute
;
141 sec
= tocentry
.cdte_addr
.msf
.second
;
142 frame
= tocentry
.cdte_addr
.msf
.frame
;
145 vcd
= malloc(sizeof(mp_vcd_priv_t
));
147 vcd
->tochdr
= tochdr
;
151 static int vcd_end_track(mp_vcd_priv_t
* vcd
)
153 return vcd
->tochdr
.cdth_trk1
;
156 static int vcd_read(mp_vcd_priv_t
* vcd
,char *mem
){
157 #if defined(__linux__) || defined(__bsdi__)
158 memcpy(vcd
->buf
,&vcd
->entry
.cdte_addr
.msf
,sizeof(struct cdrom_msf
));
159 if(ioctl(vcd
->fd
,CDROMREADRAW
,vcd
->buf
)==-1) return 0; // EOF?
160 memcpy(mem
,&vcd
->buf
[VCD_SECTOR_OFFS
],VCD_SECTOR_DATA
);
164 if (sun_vcd_read(vcd
, &offset
) <= 0) return 0;
165 memcpy(mem
,&vcd
->buf
[offset
],VCD_SECTOR_DATA
);
169 vcd
->entry
.cdte_addr
.msf
.frame
++;
170 if (vcd
->entry
.cdte_addr
.msf
.frame
==75){
171 vcd
->entry
.cdte_addr
.msf
.frame
=0;
172 vcd
->entry
.cdte_addr
.msf
.second
++;
173 if (vcd
->entry
.cdte_addr
.msf
.second
==60){
174 vcd
->entry
.cdte_addr
.msf
.second
=0;
175 vcd
->entry
.cdte_addr
.msf
.minute
++;
179 return VCD_SECTOR_DATA
;
184 #include <sys/scsi/generic/commands.h>
185 #include <sys/scsi/impl/uscsi.h>
187 #define SUN_XAREAD 1 /*fails on atapi drives*/
188 #define SUN_MODE2READ 2 /*fails on atapi drives*/
189 #define SUN_SCSIREAD 3
190 #define SUN_VCDREAD SUN_SCSIREAD
192 static int sun_vcd_read(mp_vcd_priv_t
* vcd
, int *offset
)
194 #if SUN_VCDREAD == SUN_XAREAD
195 struct cdrom_cdxa cdxa
;
196 cdxa
.cdxa_addr
= vcd_get_msf(vcd
);
197 cdxa
.cdxa_length
= 1;
198 cdxa
.cdxa_data
= vcd
->buf
;
199 cdxa
.cdxa_format
= CDROM_XA_SECTOR_DATA
;
201 if(ioctl(vcd
->fd
,CDROMCDXA
,&cdxa
)==-1) {
202 mp_msg(MSGT_STREAM
,MSGL_ERR
,"CDROMCDXA: %s\n",strerror(errno
));
206 #elif SUN_VCDREAD == SUN_MODE2READ
207 struct cdrom_read cdread
;
208 cdread
.cdread_lba
= 4*vcd_get_msf(vcd
);
209 cdread
.cdread_bufaddr
= vcd
->buf
;
210 cdread
.cdread_buflen
= 2336;
212 if(ioctl(vcd
->fd
,CDROMREADMODE2
,&cdread
)==-1) {
213 mp_msg(MSGT_STREAM
,MSGL_ERR
,"CDROMREADMODE2: %s\n",strerror(errno
));
217 #elif SUN_VCDREAD == SUN_SCSIREAD
220 int lba
= vcd_get_msf(vcd
);
223 memset(&cdb
, 0, sizeof(cdb
));
224 memset(&sc
, 0, sizeof(sc
));
226 cdb
.cdb_opaque
[1] = 5 << 2; // mode2 / form2
227 AV_WB32(&cdb
.cdb_opaque
[2], lba
);
228 AV_WB24(&cdb
.cdb_opaque
[6], blocks
);
229 cdb
.cdb_opaque
[9] = 1 << 4; // user data only
230 cdb
.cdb_opaque
[10] = 0; // subchannel
232 sc
.uscsi_cdb
= (caddr_t
)&cdb
;
233 sc
.uscsi_cdblen
= 12;
234 sc
.uscsi_bufaddr
= vcd
->buf
;
235 sc
.uscsi_buflen
= 2336;
236 sc
.uscsi_flags
= USCSI_ISOLATE
| USCSI_READ
;
237 sc
.uscsi_timeout
= 20;
238 if (ioctl(vcd
->fd
, USCSICMD
, &sc
)) {
239 mp_msg(MSGT_STREAM
,MSGL_ERR
,"USCSICMD: READ CD: %s\n",strerror(errno
));
242 if (sc
.uscsi_status
) {
243 mp_msg(MSGT_STREAM
,MSGL_ERR
,"scsi command failed with status %d\n", sc
.uscsi_status
);
254 #else /* __linux__ || sun || __bsdi__ */
256 #error vcd is not yet supported on this arch...
260 #endif /* MPLAYER_VCD_READ_H */