1 #ifndef MPLAYER_VCD_READ_FBSD_H
2 #define MPLAYER_VCD_READ_FBSD_H
4 #define _XOPEN_SOURCE 500
9 #include "ffmpeg_files/intreadwrite.h"
11 #include <sys/ioctl.h>
12 #if defined(__NetBSD__) || defined(__OpenBSD__)
16 #include <sys/scsiio.h>
17 #define TOCADDR(te) ((te).data->addr)
18 #define READ_TOC CDIOREADTOCENTRYS
20 #include <sys/cdrio.h>
21 #define TOCADDR(te) ((te).entry.addr)
22 #define READ_TOC CDIOREADTOCENTRY
26 //=================== VideoCD ==========================
27 #define CDROM_LEADOUT 0xAA
32 uint8_t subheader
[8];
38 typedef struct ioc_read_toc_entry vcd_tocentry
;
40 typedef struct ioc_read_toc_single_entry vcd_tocentry
;
43 typedef struct mp_vcd_priv_st
{
47 struct cd_toc_entry entry_data
;
51 struct ioc_toc_header tochdr
;
55 vcd_set_msf(mp_vcd_priv_t
* vcd
, unsigned int sect
)
58 vcd
->entry
.data
= &vcd
->entry_data
;
61 TOCADDR(vcd
->entry
).msf
.frame
= sect
% 75;
63 TOCADDR(vcd
->entry
).msf
.second
= sect
% 60;
65 TOCADDR(vcd
->entry
).msf
.minute
= sect
;
69 vcd_inc_msf(mp_vcd_priv_t
* vcd
)
72 vcd
->entry
.data
= &vcd
->entry_data
;
74 TOCADDR(vcd
->entry
).msf
.frame
++;
75 if (TOCADDR(vcd
->entry
).msf
.frame
==75){
76 TOCADDR(vcd
->entry
).msf
.frame
=0;
77 TOCADDR(vcd
->entry
).msf
.second
++;
78 if (TOCADDR(vcd
->entry
).msf
.second
==60){
79 TOCADDR(vcd
->entry
).msf
.second
=0;
80 TOCADDR(vcd
->entry
).msf
.minute
++;
85 static inline unsigned int
86 vcd_get_msf(mp_vcd_priv_t
* vcd
)
89 vcd
->entry
.data
= &vcd
->entry_data
;
91 return TOCADDR(vcd
->entry
).msf
.frame
+
92 (TOCADDR(vcd
->entry
).msf
.second
+
93 TOCADDR(vcd
->entry
).msf
.minute
* 60) * 75 - 150;
97 * \brief read a TOC entry
98 * \param fd device to read from
99 * \param dst buffer to read data into
100 * \param nr track number to read info for
101 * \return 1 on success, 0 on failure
104 read_toc_entry(mp_vcd_priv_t
*vcd
, int nr
)
106 vcd
->entry
.address_format
= CD_MSF_FORMAT
;
108 vcd
->entry
.data_len
= sizeof(struct cd_toc_entry
);
109 vcd
->entry
.data
= &vcd
->entry_data
;
110 vcd
->entry
.starting_track
= nr
;
112 vcd
->entry
.track
= nr
;
114 if (ioctl(vcd
->fd
, READ_TOC
, &vcd
->entry
) == -1) {
115 mp_msg(MSGT_OPEN
,MSGL_ERR
,"read CDROM toc entry: %s\n",strerror(errno
));
122 vcd_seek_to_track(mp_vcd_priv_t
* vcd
, int track
)
124 if (!read_toc_entry(vcd
, track
))
126 return VCD_SECTOR_DATA
* vcd_get_msf(vcd
);
130 vcd_get_track_end(mp_vcd_priv_t
* vcd
, int track
)
132 if (!read_toc_entry(vcd
,
133 track
< vcd
->tochdr
.ending_track
? track
+ 1 : CDROM_LEADOUT
))
135 return VCD_SECTOR_DATA
* vcd_get_msf(vcd
);
141 struct ioc_toc_header tochdr
;
143 int i
, last_startsect
;
144 if (ioctl(fd
, CDIOREADTOCHEADER
, &tochdr
) == -1) {
145 mp_msg(MSGT_OPEN
,MSGL_ERR
,"read CDROM toc header: %s\n",strerror(errno
));
148 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_START_TRACK=%d\n", tochdr
.starting_track
);
149 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_END_TRACK=%d\n", tochdr
.ending_track
);
150 vcd
= malloc(sizeof(mp_vcd_priv_t
));
152 vcd
->tochdr
= tochdr
;
153 for (i
= tochdr
.starting_track
; i
<= tochdr
.ending_track
+ 1; i
++) {
154 if (!read_toc_entry(vcd
,
155 i
<= tochdr
.ending_track
? i
: CDROM_LEADOUT
)) {
160 if (i
<= tochdr
.ending_track
)
161 mp_msg(MSGT_OPEN
,MSGL_INFO
,"track %02d: adr=%d ctrl=%d format=%d %02d:%02d:%02d\n",
163 (int)vcd
->entry
.starting_track
,
164 (int)vcd
->entry
.data
->addr_type
,
165 (int)vcd
->entry
.data
->control
,
167 (int)vcd
->entry
.track
,
168 (int)vcd
->entry
.entry
.addr_type
,
169 (int)vcd
->entry
.entry
.control
,
171 (int)vcd
->entry
.address_format
,
172 (int)TOCADDR(vcd
->entry
).msf
.minute
,
173 (int)TOCADDR(vcd
->entry
).msf
.second
,
174 (int)TOCADDR(vcd
->entry
).msf
.frame
177 if (mp_msg_test(MSGT_IDENTIFY
, MSGL_INFO
))
179 int startsect
= vcd_get_msf(vcd
);
180 if (i
> tochdr
.starting_track
)
182 // convert duraion to MSF
183 vcd_set_msf(vcd
, startsect
- last_startsect
);
184 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
,
185 "ID_VCD_TRACK_%d_MSF=%02d:%02d:%02d\n",
187 TOCADDR(vcd
->entry
).msf
.minute
,
188 TOCADDR(vcd
->entry
).msf
.second
,
189 TOCADDR(vcd
->entry
).msf
.frame
);
191 last_startsect
= startsect
;
198 vcd_read(mp_vcd_priv_t
* vcd
, char *mem
)
202 int lba
= vcd_get_msf(vcd
);
208 memset(&sc
, 0, sizeof(sc
));
210 sc
.cmd
[1] = 5 << 2; // mode2/form2
211 AV_WB32(&sc
.cmd
[2], lba
);
212 AV_WB24(&sc
.cmd
[6], blocks
);
213 sc
.cmd
[9] = 1 << 4; // user data only
214 sc
.cmd
[10] = 0; // no subchannel
216 sc
.databuf
= (caddr_t
) mem
;
217 sc
.datalen
= VCD_SECTOR_DATA
;
218 sc
.senselen
= sizeof(sc
.sense
);
219 sc
.flags
= SCCMD_READ
;
221 rc
= ioctl(vcd
->fd
, SCIOCCOMMAND
, &sc
);
223 mp_msg(MSGT_STREAM
,MSGL_ERR
,"SCIOCCOMMAND: %s\n",strerror(errno
));
226 if (sc
.retsts
|| sc
.error
) {
227 mp_msg(MSGT_STREAM
,MSGL_ERR
,"scsi command failed: status %d error %d\n",
232 if (pread(vcd
->fd
,&vcd
->buf
,VCD_SECTOR_SIZE
,vcd_get_msf(vcd
)*VCD_SECTOR_SIZE
)
233 != VCD_SECTOR_SIZE
) return 0; // EOF?
235 memcpy(mem
,vcd
->buf
.data
,VCD_SECTOR_DATA
);
238 return VCD_SECTOR_DATA
;
241 #endif /* MPLAYER_VCD_READ_FBSD_H */