4 //=================== VideoCD ==========================
5 #define CDROM_LEADOUT 0xAA
10 uint8_t subheader
[8];
15 typedef struct mp_vcd_priv_st
{
17 struct ioc_read_toc_single_entry entry
;
21 static inline void vcd_set_msf(mp_vcd_priv_t
* vcd
, unsigned int sect
){
22 vcd
->entry
.entry
.addr
.msf
.frame
=sect
%75;
24 vcd
->entry
.entry
.addr
.msf
.second
=sect
%60;
26 vcd
->entry
.entry
.addr
.msf
.minute
=sect
;
29 static inline unsigned int vcd_get_msf(mp_vcd_priv_t
* vcd
){
30 return vcd
->entry
.entry
.addr
.msf
.frame
+
31 (vcd
->entry
.entry
.addr
.msf
.second
+
32 vcd
->entry
.entry
.addr
.msf
.minute
*60)*75;
35 int vcd_seek_to_track(mp_vcd_priv_t
* vcd
, int track
){
36 vcd
->entry
.address_format
= CD_MSF_FORMAT
;
37 vcd
->entry
.track
= track
;
38 if (ioctl(vcd
->fd
, CDIOREADTOCENTRY
, &vcd
->entry
)) {
39 mp_msg(MSGT_STREAM
,MSGL_ERR
,"ioctl dif1: %s\n",strerror(errno
));
42 return VCD_SECTOR_DATA
*vcd_get_msf(vcd
);
45 int vcd_get_track_end(mp_vcd_priv_t
* vcd
, int track
){
46 struct ioc_toc_header tochdr
;
47 if (ioctl(vcd
->fd
,CDIOREADTOCHEADER
,&tochdr
)==-1) {
48 mp_msg(MSGT_STREAM
,MSGL_ERR
,"read CDROM toc header: %s\n",strerror(errno
));
51 vcd
->entry
.address_format
= CD_MSF_FORMAT
;
52 vcd
->entry
.track
= track
<tochdr
.ending_track
?(track
+1):CDROM_LEADOUT
;
53 if (ioctl(vcd
->fd
, CDIOREADTOCENTRY
, &vcd
->entry
)) {
54 mp_msg(MSGT_STREAM
,MSGL_ERR
,"ioctl dif2: %s\n",strerror(errno
));
57 return VCD_SECTOR_DATA
*vcd_get_msf(vcd
);
60 mp_vcd_priv_t
* vcd_read_toc(int fd
){
61 struct ioc_toc_header tochdr
;
63 int i
, min
= 0, sec
= 0, frame
= 0;
64 if (ioctl(fd
,CDIOREADTOCHEADER
,&tochdr
)==-1) {
65 mp_msg(MSGT_OPEN
,MSGL_ERR
,"read CDROM toc header: %s\n",strerror(errno
));
68 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_START_TRACK=%d\n", tochdr
.starting_track
);
69 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_END_TRACK=%d\n", tochdr
.ending_track
);
70 for (i
=tochdr
.starting_track
; i
<=tochdr
.ending_track
+ 1; i
++){
71 struct ioc_read_toc_single_entry tocentry
;
73 tocentry
.track
= i
<=tochdr
.ending_track
? i
: CDROM_LEADOUT
;
74 tocentry
.address_format
= CD_MSF_FORMAT
;
76 if (ioctl(fd
,CDIOREADTOCENTRY
,&tocentry
)==-1) {
77 mp_msg(MSGT_OPEN
,MSGL_ERR
,"read CDROM toc entry: %s\n",strerror(errno
));
81 if (i
<=tochdr
.ending_track
)
82 mp_msg(MSGT_OPEN
,MSGL_INFO
,"track %02d: adr=%d ctrl=%d format=%d %02d:%02d:%02d\n",
84 (int)tocentry
.entry
.addr_type
,
85 (int)tocentry
.entry
.control
,
86 (int)tocentry
.address_format
,
87 (int)tocentry
.entry
.addr
.msf
.minute
,
88 (int)tocentry
.entry
.addr
.msf
.second
,
89 (int)tocentry
.entry
.addr
.msf
.frame
92 if (mp_msg_test(MSGT_IDENTIFY
, MSGL_INFO
))
94 if (i
> tochdr
.starting_track
)
96 min
= tocentry
.entry
.addr
.msf
.minute
- min
;
97 sec
= tocentry
.entry
.addr
.msf
.second
- sec
;
98 frame
= tocentry
.entry
.addr
.msf
.frame
- frame
;
109 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_VCD_TRACK_%d_MSF=%02d:%02d:%02d\n", i
- 1, min
, sec
, frame
);
111 min
= tocentry
.entry
.addr
.msf
.minute
;
112 sec
= tocentry
.entry
.addr
.msf
.second
;
113 frame
= tocentry
.entry
.addr
.msf
.frame
;
116 vcd
= malloc(sizeof(mp_vcd_priv_t
));
121 static int vcd_read(mp_vcd_priv_t
* vcd
,char *mem
){
123 if (pread(vcd
->fd
,&vcd
->buf
,VCD_SECTOR_SIZE
,vcd_get_msf(vcd
)*VCD_SECTOR_SIZE
)
124 != VCD_SECTOR_SIZE
) return 0; // EOF?
126 vcd
->entry
.entry
.addr
.msf
.frame
++;
127 if (vcd
->entry
.entry
.addr
.msf
.frame
==75){
128 vcd
->entry
.entry
.addr
.msf
.frame
=0;
129 vcd
->entry
.entry
.addr
.msf
.second
++;
130 if (vcd
->entry
.entry
.addr
.msf
.second
==60){
131 vcd
->entry
.entry
.addr
.msf
.second
=0;
132 vcd
->entry
.entry
.addr
.msf
.minute
++;
135 memcpy(mem
,vcd
->buf
.data
,VCD_SECTOR_DATA
);
136 return VCD_SECTOR_DATA
;