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 static int vcd_seek_to_track(mp_vcd_priv_t
* vcd
, int track
)
67 vcd
->entry
.cdte_format
= CDROM_MSF
;
68 vcd
->entry
.cdte_track
= track
;
69 if (ioctl(vcd
->fd
, CDROMREADTOCENTRY
, &vcd
->entry
)) {
70 mp_msg(MSGT_STREAM
,MSGL_ERR
,"ioctl dif1: %s\n",strerror(errno
));
73 return VCD_SECTOR_DATA
*vcd_get_msf(vcd
);
76 static int vcd_get_track_end(mp_vcd_priv_t
* vcd
,int track
){
77 vcd
->entry
.cdte_format
= CDROM_MSF
;
78 vcd
->entry
.cdte_track
= track
<vcd
->tochdr
.cdth_trk1
?(track
+1):CDROM_LEADOUT
;
79 if (ioctl(vcd
->fd
, CDROMREADTOCENTRY
, &vcd
->entry
)) {
80 mp_msg(MSGT_STREAM
,MSGL_ERR
,"ioctl dif2: %s\n",strerror(errno
));
83 return VCD_SECTOR_DATA
*vcd_get_msf(vcd
);
86 static mp_vcd_priv_t
* vcd_read_toc(int fd
){
87 struct cdrom_tochdr tochdr
;
89 int i
, min
= 0, sec
= 0, frame
= 0;
90 if (ioctl(fd
,CDROMREADTOCHDR
,&tochdr
)==-1) {
91 mp_msg(MSGT_OPEN
,MSGL_ERR
,"read CDROM toc header: %s\n",strerror(errno
));
94 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_START_TRACK=%d\n", tochdr
.cdth_trk0
);
95 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_END_TRACK=%d\n", tochdr
.cdth_trk1
);
96 for (i
=tochdr
.cdth_trk0
; i
<=tochdr
.cdth_trk1
+ 1; i
++){
97 struct cdrom_tocentry tocentry
;
99 tocentry
.cdte_track
= i
<=tochdr
.cdth_trk1
? i
: CDROM_LEADOUT
;
100 tocentry
.cdte_format
= CDROM_MSF
;
102 if (ioctl(fd
,CDROMREADTOCENTRY
,&tocentry
)==-1) {
103 mp_msg(MSGT_OPEN
,MSGL_ERR
,"read CDROM toc entry: %s\n",strerror(errno
));
107 if (i
<=tochdr
.cdth_trk1
)
108 mp_msg(MSGT_OPEN
,MSGL_INFO
,"track %02d: adr=%d ctrl=%d format=%d %02d:%02d:%02d mode: %d\n",
109 (int)tocentry
.cdte_track
,
110 (int)tocentry
.cdte_adr
,
111 (int)tocentry
.cdte_ctrl
,
112 (int)tocentry
.cdte_format
,
113 (int)tocentry
.cdte_addr
.msf
.minute
,
114 (int)tocentry
.cdte_addr
.msf
.second
,
115 (int)tocentry
.cdte_addr
.msf
.frame
,
116 (int)tocentry
.cdte_datamode
119 if (mp_msg_test(MSGT_IDENTIFY
, MSGL_INFO
))
121 if (i
> tochdr
.cdth_trk0
)
123 min
= tocentry
.cdte_addr
.msf
.minute
- min
;
124 sec
= tocentry
.cdte_addr
.msf
.second
- sec
;
125 frame
= tocentry
.cdte_addr
.msf
.frame
- frame
;
136 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_TRACK_%d_MSF=%02d:%02d:%02d\n", i
- 1, min
, sec
, frame
);
138 min
= tocentry
.cdte_addr
.msf
.minute
;
139 sec
= tocentry
.cdte_addr
.msf
.second
;
140 frame
= tocentry
.cdte_addr
.msf
.frame
;
143 vcd
= malloc(sizeof(mp_vcd_priv_t
));
145 vcd
->tochdr
= tochdr
;
149 static int vcd_end_track(mp_vcd_priv_t
* vcd
)
151 return vcd
->tochdr
.cdth_trk1
;
154 static int vcd_read(mp_vcd_priv_t
* vcd
,char *mem
){
155 #if defined(__linux__) || defined(__bsdi__)
156 memcpy(vcd
->buf
,&vcd
->entry
.cdte_addr
.msf
,sizeof(struct cdrom_msf
));
157 if(ioctl(vcd
->fd
,CDROMREADRAW
,vcd
->buf
)==-1) return 0; // EOF?
158 memcpy(mem
,&vcd
->buf
[VCD_SECTOR_OFFS
],VCD_SECTOR_DATA
);
162 if (sun_vcd_read(vcd
, &offset
) <= 0) return 0;
163 memcpy(mem
,&vcd
->buf
[offset
],VCD_SECTOR_DATA
);
167 vcd
->entry
.cdte_addr
.msf
.frame
++;
168 if (vcd
->entry
.cdte_addr
.msf
.frame
==75){
169 vcd
->entry
.cdte_addr
.msf
.frame
=0;
170 vcd
->entry
.cdte_addr
.msf
.second
++;
171 if (vcd
->entry
.cdte_addr
.msf
.second
==60){
172 vcd
->entry
.cdte_addr
.msf
.second
=0;
173 vcd
->entry
.cdte_addr
.msf
.minute
++;
177 return VCD_SECTOR_DATA
;
182 #include <sys/scsi/generic/commands.h>
183 #include <sys/scsi/impl/uscsi.h>
185 #define SUN_XAREAD 1 /*fails on atapi drives*/
186 #define SUN_MODE2READ 2 /*fails on atapi drives*/
187 #define SUN_SCSIREAD 3
188 #define SUN_VCDREAD SUN_SCSIREAD
190 static int sun_vcd_read(mp_vcd_priv_t
* vcd
, int *offset
)
192 #if SUN_VCDREAD == SUN_XAREAD
193 struct cdrom_cdxa cdxa
;
194 cdxa
.cdxa_addr
= vcd_get_msf(vcd
);
195 cdxa
.cdxa_length
= 1;
196 cdxa
.cdxa_data
= vcd
->buf
;
197 cdxa
.cdxa_format
= CDROM_XA_SECTOR_DATA
;
199 if(ioctl(vcd
->fd
,CDROMCDXA
,&cdxa
)==-1) {
200 mp_msg(MSGT_STREAM
,MSGL_ERR
,"CDROMCDXA: %s\n",strerror(errno
));
204 #elif SUN_VCDREAD == SUN_MODE2READ
205 struct cdrom_read cdread
;
206 cdread
.cdread_lba
= 4*vcd_get_msf(vcd
);
207 cdread
.cdread_bufaddr
= vcd
->buf
;
208 cdread
.cdread_buflen
= 2336;
210 if(ioctl(vcd
->fd
,CDROMREADMODE2
,&cdread
)==-1) {
211 mp_msg(MSGT_STREAM
,MSGL_ERR
,"CDROMREADMODE2: %s\n",strerror(errno
));
215 #elif SUN_VCDREAD == SUN_SCSIREAD
218 int lba
= vcd_get_msf(vcd
);
221 memset(&cdb
, 0, sizeof(cdb
));
222 memset(&sc
, 0, sizeof(sc
));
224 cdb
.cdb_opaque
[1] = 5 << 2; // mode2 / form2
225 AV_WB32(&cdb
.cdb_opaque
[2], lba
);
226 AV_WB24(&cdb
.cdb_opaque
[6], blocks
);
227 cdb
.cdb_opaque
[9] = 1 << 4; // user data only
228 cdb
.cdb_opaque
[10] = 0; // subchannel
230 sc
.uscsi_cdb
= (caddr_t
)&cdb
;
231 sc
.uscsi_cdblen
= 12;
232 sc
.uscsi_bufaddr
= vcd
->buf
;
233 sc
.uscsi_buflen
= 2336;
234 sc
.uscsi_flags
= USCSI_ISOLATE
| USCSI_READ
;
235 sc
.uscsi_timeout
= 20;
236 if (ioctl(vcd
->fd
, USCSICMD
, &sc
)) {
237 mp_msg(MSGT_STREAM
,MSGL_ERR
,"USCSICMD: READ CD: %s\n",strerror(errno
));
240 if (sc
.uscsi_status
) {
241 mp_msg(MSGT_STREAM
,MSGL_ERR
,"scsi command failed with status %d\n", sc
.uscsi_status
);
252 #else /* __linux__ || sun || __bsdi__ */
254 #error vcd is not yet supported on this arch...
258 #endif /* MPLAYER_VCD_READ_H */