1 #ifndef MPLAYER_VCD_READ_FBSD_H
2 #define MPLAYER_VCD_READ_FBSD_H
6 #include "libavutil/intreadwrite.h"
8 #if defined(__NetBSD__) || defined(__OpenBSD__)
12 #include <sys/scsiio.h>
13 #define TOCADDR(te) ((te).data->addr)
14 #define READ_TOC CDIOREADTOCENTRYS
16 #include <sys/cdrio.h>
17 #define TOCADDR(te) ((te).entry.addr)
18 #define READ_TOC CDIOREADTOCENTRY
22 //=================== VideoCD ==========================
23 #define CDROM_LEADOUT 0xAA
28 uint8_t subheader
[8];
34 typedef struct ioc_read_toc_entry vcd_tocentry
;
36 typedef struct ioc_read_toc_single_entry vcd_tocentry
;
39 typedef struct mp_vcd_priv_st
{
43 struct cd_toc_entry entry_data
;
47 struct ioc_toc_header tochdr
;
51 vcd_set_msf(mp_vcd_priv_t
* vcd
, unsigned int sect
)
54 vcd
->entry
.data
= &vcd
->entry_data
;
57 TOCADDR(vcd
->entry
).msf
.frame
= sect
% 75;
59 TOCADDR(vcd
->entry
).msf
.second
= sect
% 60;
61 TOCADDR(vcd
->entry
).msf
.minute
= sect
;
65 vcd_inc_msf(mp_vcd_priv_t
* vcd
)
68 vcd
->entry
.data
= &vcd
->entry_data
;
70 TOCADDR(vcd
->entry
).msf
.frame
++;
71 if (TOCADDR(vcd
->entry
).msf
.frame
==75){
72 TOCADDR(vcd
->entry
).msf
.frame
=0;
73 TOCADDR(vcd
->entry
).msf
.second
++;
74 if (TOCADDR(vcd
->entry
).msf
.second
==60){
75 TOCADDR(vcd
->entry
).msf
.second
=0;
76 TOCADDR(vcd
->entry
).msf
.minute
++;
81 static inline unsigned int
82 vcd_get_msf(mp_vcd_priv_t
* vcd
)
85 vcd
->entry
.data
= &vcd
->entry_data
;
87 return TOCADDR(vcd
->entry
).msf
.frame
+
88 (TOCADDR(vcd
->entry
).msf
.second
+
89 TOCADDR(vcd
->entry
).msf
.minute
* 60) * 75 - 150;
93 * \brief read a TOC entry
94 * \param fd device to read from
95 * \param dst buffer to read data into
96 * \param nr track number to read info for
97 * \return 1 on success, 0 on failure
100 read_toc_entry(mp_vcd_priv_t
*vcd
, int nr
)
102 vcd
->entry
.address_format
= CD_MSF_FORMAT
;
104 vcd
->entry
.data_len
= sizeof(struct cd_toc_entry
);
105 vcd
->entry
.data
= &vcd
->entry_data
;
106 vcd
->entry
.starting_track
= nr
;
108 vcd
->entry
.track
= nr
;
110 if (ioctl(vcd
->fd
, READ_TOC
, &vcd
->entry
) == -1) {
111 mp_msg(MSGT_OPEN
,MSGL_ERR
,"read CDROM toc entry: %s\n",strerror(errno
));
118 vcd_seek_to_track(mp_vcd_priv_t
* vcd
, int track
)
120 if (!read_toc_entry(vcd
, track
))
122 return VCD_SECTOR_DATA
* vcd_get_msf(vcd
);
126 vcd_get_track_end(mp_vcd_priv_t
* vcd
, int track
)
128 if (!read_toc_entry(vcd
,
129 track
< vcd
->tochdr
.ending_track
? track
+ 1 : CDROM_LEADOUT
))
131 return VCD_SECTOR_DATA
* vcd_get_msf(vcd
);
137 struct ioc_toc_header tochdr
;
139 int i
, last_startsect
;
140 if (ioctl(fd
, CDIOREADTOCHEADER
, &tochdr
) == -1) {
141 mp_msg(MSGT_OPEN
,MSGL_ERR
,"read CDROM toc header: %s\n",strerror(errno
));
144 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_START_TRACK=%d\n", tochdr
.starting_track
);
145 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_END_TRACK=%d\n", tochdr
.ending_track
);
146 vcd
= malloc(sizeof(mp_vcd_priv_t
));
148 vcd
->tochdr
= tochdr
;
149 for (i
= tochdr
.starting_track
; i
<= tochdr
.ending_track
+ 1; i
++) {
150 if (!read_toc_entry(vcd
,
151 i
<= tochdr
.ending_track
? i
: CDROM_LEADOUT
)) {
156 if (i
<= tochdr
.ending_track
)
157 mp_msg(MSGT_OPEN
,MSGL_INFO
,"track %02d: adr=%d ctrl=%d format=%d %02d:%02d:%02d\n",
159 (int)vcd
->entry
.starting_track
,
160 (int)vcd
->entry
.data
->addr_type
,
161 (int)vcd
->entry
.data
->control
,
163 (int)vcd
->entry
.track
,
164 (int)vcd
->entry
.entry
.addr_type
,
165 (int)vcd
->entry
.entry
.control
,
167 (int)vcd
->entry
.address_format
,
168 (int)TOCADDR(vcd
->entry
).msf
.minute
,
169 (int)TOCADDR(vcd
->entry
).msf
.second
,
170 (int)TOCADDR(vcd
->entry
).msf
.frame
173 if (mp_msg_test(MSGT_IDENTIFY
, MSGL_INFO
))
175 int startsect
= vcd_get_msf(vcd
);
176 if (i
> tochdr
.starting_track
)
178 // convert duraion to MSF
179 vcd_set_msf(vcd
, startsect
- last_startsect
);
180 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
,
181 "ID_VCD_TRACK_%d_MSF=%02d:%02d:%02d\n",
183 TOCADDR(vcd
->entry
).msf
.minute
,
184 TOCADDR(vcd
->entry
).msf
.second
,
185 TOCADDR(vcd
->entry
).msf
.frame
);
187 last_startsect
= startsect
;
194 vcd_read(mp_vcd_priv_t
* vcd
, char *mem
)
198 int lba
= vcd_get_msf(vcd
);
204 memset(&sc
, 0, sizeof(sc
));
206 sc
.cmd
[1] = 5 << 2; // mode2/form2
207 AV_WB32(&sc
.cmd
[2], lba
);
208 AV_WB24(&sc
.cmd
[6], blocks
);
209 sc
.cmd
[9] = 1 << 4; // user data only
210 sc
.cmd
[10] = 0; // no subchannel
212 sc
.databuf
= (caddr_t
) mem
;
213 sc
.datalen
= VCD_SECTOR_DATA
;
214 sc
.senselen
= sizeof(sc
.sense
);
215 sc
.flags
= SCCMD_READ
;
217 rc
= ioctl(vcd
->fd
, SCIOCCOMMAND
, &sc
);
219 mp_msg(MSGT_STREAM
,MSGL_ERR
,"SCIOCCOMMAND: %s\n",strerror(errno
));
222 if (sc
.retsts
|| sc
.error
) {
223 mp_msg(MSGT_STREAM
,MSGL_ERR
,"scsi command failed: status %d error %d\n",
228 if (pread(vcd
->fd
,&vcd
->buf
,VCD_SECTOR_SIZE
,vcd_get_msf(vcd
)*VCD_SECTOR_SIZE
)
229 != VCD_SECTOR_SIZE
) return 0; // EOF?
231 memcpy(mem
,vcd
->buf
.data
,VCD_SECTOR_DATA
);
234 return VCD_SECTOR_DATA
;
237 #endif /* MPLAYER_VCD_READ_FBSD_H */