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>
28 #include "ffmpeg_files/intreadwrite.h"
29 //=================== VideoCD ==========================
30 #if defined(__linux__) || defined(sun) || defined(__bsdi__)
32 typedef struct mp_vcd_priv_st mp_vcd_priv_t
;
34 #if defined(__linux__)
35 #include <linux/cdrom.h>
38 static int sun_vcd_read(mp_vcd_priv_t
*, int*);
39 #elif defined(__bsdi__)
43 struct mp_vcd_priv_st
{
45 struct cdrom_tocentry entry
;
46 char buf
[VCD_SECTOR_SIZE
];
47 struct cdrom_tochdr tochdr
;
50 static inline void vcd_set_msf(mp_vcd_priv_t
* vcd
, unsigned int sect
){
52 vcd
->entry
.cdte_addr
.msf
.frame
=sect
%75;
54 vcd
->entry
.cdte_addr
.msf
.second
=sect
%60;
56 vcd
->entry
.cdte_addr
.msf
.minute
=sect
;
59 static inline unsigned int vcd_get_msf(mp_vcd_priv_t
* vcd
){
60 return vcd
->entry
.cdte_addr
.msf
.frame
+
61 (vcd
->entry
.cdte_addr
.msf
.second
+
62 vcd
->entry
.cdte_addr
.msf
.minute
*60)*75 - 150;
65 int vcd_seek_to_track(mp_vcd_priv_t
* vcd
,int track
){
66 vcd
->entry
.cdte_format
= CDROM_MSF
;
67 vcd
->entry
.cdte_track
= track
;
68 if (ioctl(vcd
->fd
, CDROMREADTOCENTRY
, &vcd
->entry
)) {
69 mp_msg(MSGT_STREAM
,MSGL_ERR
,"ioctl dif1: %s\n",strerror(errno
));
72 return VCD_SECTOR_DATA
*vcd_get_msf(vcd
);
75 static int vcd_get_track_end(mp_vcd_priv_t
* vcd
,int track
){
76 vcd
->entry
.cdte_format
= CDROM_MSF
;
77 vcd
->entry
.cdte_track
= track
<vcd
->tochdr
.cdth_trk1
?(track
+1):CDROM_LEADOUT
;
78 if (ioctl(vcd
->fd
, CDROMREADTOCENTRY
, &vcd
->entry
)) {
79 mp_msg(MSGT_STREAM
,MSGL_ERR
,"ioctl dif2: %s\n",strerror(errno
));
82 return VCD_SECTOR_DATA
*vcd_get_msf(vcd
);
85 static mp_vcd_priv_t
* vcd_read_toc(int fd
){
86 struct cdrom_tochdr tochdr
;
88 int i
, min
= 0, sec
= 0, frame
= 0;
89 if (ioctl(fd
,CDROMREADTOCHDR
,&tochdr
)==-1) {
90 mp_msg(MSGT_OPEN
,MSGL_ERR
,"read CDROM toc header: %s\n",strerror(errno
));
93 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_START_TRACK=%d\n", tochdr
.cdth_trk0
);
94 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_END_TRACK=%d\n", tochdr
.cdth_trk1
);
95 for (i
=tochdr
.cdth_trk0
; i
<=tochdr
.cdth_trk1
+ 1; i
++){
96 struct cdrom_tocentry tocentry
;
98 tocentry
.cdte_track
= i
<=tochdr
.cdth_trk1
? i
: CDROM_LEADOUT
;
99 tocentry
.cdte_format
= CDROM_MSF
;
101 if (ioctl(fd
,CDROMREADTOCENTRY
,&tocentry
)==-1) {
102 mp_msg(MSGT_OPEN
,MSGL_ERR
,"read CDROM toc entry: %s\n",strerror(errno
));
106 if (i
<=tochdr
.cdth_trk1
)
107 mp_msg(MSGT_OPEN
,MSGL_INFO
,"track %02d: adr=%d ctrl=%d format=%d %02d:%02d:%02d mode: %d\n",
108 (int)tocentry
.cdte_track
,
109 (int)tocentry
.cdte_adr
,
110 (int)tocentry
.cdte_ctrl
,
111 (int)tocentry
.cdte_format
,
112 (int)tocentry
.cdte_addr
.msf
.minute
,
113 (int)tocentry
.cdte_addr
.msf
.second
,
114 (int)tocentry
.cdte_addr
.msf
.frame
,
115 (int)tocentry
.cdte_datamode
118 if (mp_msg_test(MSGT_IDENTIFY
, MSGL_INFO
))
120 if (i
> tochdr
.cdth_trk0
)
122 min
= tocentry
.cdte_addr
.msf
.minute
- min
;
123 sec
= tocentry
.cdte_addr
.msf
.second
- sec
;
124 frame
= tocentry
.cdte_addr
.msf
.frame
- frame
;
135 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_TRACK_%d_MSF=%02d:%02d:%02d\n", i
- 1, min
, sec
, frame
);
137 min
= tocentry
.cdte_addr
.msf
.minute
;
138 sec
= tocentry
.cdte_addr
.msf
.second
;
139 frame
= tocentry
.cdte_addr
.msf
.frame
;
142 vcd
= malloc(sizeof(mp_vcd_priv_t
));
144 vcd
->tochdr
= tochdr
;
148 static int vcd_end_track(mp_vcd_priv_t
* vcd
)
150 return vcd
->tochdr
.cdth_trk1
;
153 static int vcd_read(mp_vcd_priv_t
* vcd
,char *mem
){
154 #if defined(__linux__) || defined(__bsdi__)
155 memcpy(vcd
->buf
,&vcd
->entry
.cdte_addr
.msf
,sizeof(struct cdrom_msf
));
156 if(ioctl(vcd
->fd
,CDROMREADRAW
,vcd
->buf
)==-1) return 0; // EOF?
157 memcpy(mem
,&vcd
->buf
[VCD_SECTOR_OFFS
],VCD_SECTOR_DATA
);
161 if (sun_vcd_read(vcd
, &offset
) <= 0) return 0;
162 memcpy(mem
,&vcd
->buf
[offset
],VCD_SECTOR_DATA
);
166 vcd
->entry
.cdte_addr
.msf
.frame
++;
167 if (vcd
->entry
.cdte_addr
.msf
.frame
==75){
168 vcd
->entry
.cdte_addr
.msf
.frame
=0;
169 vcd
->entry
.cdte_addr
.msf
.second
++;
170 if (vcd
->entry
.cdte_addr
.msf
.second
==60){
171 vcd
->entry
.cdte_addr
.msf
.second
=0;
172 vcd
->entry
.cdte_addr
.msf
.minute
++;
176 return VCD_SECTOR_DATA
;
181 #include <sys/scsi/generic/commands.h>
182 #include <sys/scsi/impl/uscsi.h>
184 #define SUN_XAREAD 1 /*fails on atapi drives*/
185 #define SUN_MODE2READ 2 /*fails on atapi drives*/
186 #define SUN_SCSIREAD 3
187 #define SUN_VCDREAD SUN_SCSIREAD
189 static int sun_vcd_read(mp_vcd_priv_t
* vcd
, int *offset
)
191 #if SUN_VCDREAD == SUN_XAREAD
192 struct cdrom_cdxa cdxa
;
193 cdxa
.cdxa_addr
= vcd_get_msf(vcd
);
194 cdxa
.cdxa_length
= 1;
195 cdxa
.cdxa_data
= vcd
->buf
;
196 cdxa
.cdxa_format
= CDROM_XA_SECTOR_DATA
;
198 if(ioctl(vcd
->fd
,CDROMCDXA
,&cdxa
)==-1) {
199 mp_msg(MSGT_STREAM
,MSGL_ERR
,"CDROMCDXA: %s\n",strerror(errno
));
203 #elif SUN_VCDREAD == SUN_MODE2READ
204 struct cdrom_read cdread
;
205 cdread
.cdread_lba
= 4*vcd_get_msf(vcd
);
206 cdread
.cdread_bufaddr
= vcd
->buf
;
207 cdread
.cdread_buflen
= 2336;
209 if(ioctl(vcd
->fd
,CDROMREADMODE2
,&cdread
)==-1) {
210 mp_msg(MSGT_STREAM
,MSGL_ERR
,"CDROMREADMODE2: %s\n",strerror(errno
));
214 #elif SUN_VCDREAD == SUN_SCSIREAD
217 int lba
= vcd_get_msf(vcd
);
220 memset(&cdb
, 0, sizeof(cdb
));
221 memset(&sc
, 0, sizeof(sc
));
223 cdb
.cdb_opaque
[1] = 5 << 2; // mode2 / form2
224 AV_WB32(&cdb
.cdb_opaque
[2], lba
);
225 AV_WB24(&cdb
.cdb_opaque
[6], blocks
);
226 cdb
.cdb_opaque
[9] = 1 << 4; // user data only
227 cdb
.cdb_opaque
[10] = 0; // subchannel
229 sc
.uscsi_cdb
= (caddr_t
)&cdb
;
230 sc
.uscsi_cdblen
= 12;
231 sc
.uscsi_bufaddr
= vcd
->buf
;
232 sc
.uscsi_buflen
= 2336;
233 sc
.uscsi_flags
= USCSI_ISOLATE
| USCSI_READ
;
234 sc
.uscsi_timeout
= 20;
235 if (ioctl(vcd
->fd
, USCSICMD
, &sc
)) {
236 mp_msg(MSGT_STREAM
,MSGL_ERR
,"USCSICMD: READ CD: %s\n",strerror(errno
));
239 if (sc
.uscsi_status
) {
240 mp_msg(MSGT_STREAM
,MSGL_ERR
,"scsi command failed with status %d\n", sc
.uscsi_status
);
251 #else /* __linux__ || sun || __bsdi__ */
253 #error vcd is not yet supported on this arch...
257 #endif /* MPLAYER_VCD_READ_H */