3 * Copyright (C) 2002 Mike Melanson
5 * This demuxer handles FILM (a.k.a. CPK) files commonly found on Sega
6 * Saturn CD-ROM games. FILM files have also been found on 3DO games.
8 * details of the FILM file format can be found at:
9 * http://www.pcisys.net/~melanson/codecs/
11 * This file is part of MPlayer.
13 * MPlayer is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * MPlayer is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License along
24 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
25 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
36 #include "stream/stream.h"
40 // chunk types found in a FILM file
41 #define CHUNK_FILM mmioFOURCC('F', 'I', 'L', 'M')
42 #define CHUNK_FDSC mmioFOURCC('F', 'D', 'S', 'C')
43 #define CHUNK_STAB mmioFOURCC('S', 'T', 'A', 'B')
45 typedef struct film_chunk_t
49 unsigned int syncinfo1
;
50 unsigned int syncinfo2
;
55 typedef struct film_data_t
57 unsigned int total_chunks
;
58 unsigned int current_chunk
;
60 unsigned int chunks_per_second
;
61 unsigned int film_version
;
64 static void demux_seek_film(demuxer_t
*demuxer
, float rel_seek_secs
, float audio_delay
, int flags
)
66 film_data_t
*film_data
= (film_data_t
*)demuxer
->priv
;
67 int new_current_chunk
=(flags
&SEEK_ABSOLUTE
)?0:film_data
->current_chunk
;
70 new_current_chunk
+= rel_seek_secs
* film_data
->total_chunks
; // 0..1
72 new_current_chunk
+= rel_seek_secs
* film_data
->chunks_per_second
; // secs
75 mp_msg(MSGT_DECVIDEO
, MSGL_INFO
,"current, total chunks = %d, %d; seek %5.3f sec, new chunk guess = %d\n",
76 film_data
->current_chunk
, film_data
->total_chunks
,
77 rel_seek_secs
, new_current_chunk
);
79 // check if the new chunk number is valid
80 if (new_current_chunk
< 0)
81 new_current_chunk
= 0;
82 if ((unsigned int)new_current_chunk
> film_data
->total_chunks
)
83 new_current_chunk
= film_data
->total_chunks
- 1;
85 while (((film_data
->chunks
[new_current_chunk
].syncinfo1
== 0xFFFFFFFF) ||
86 (film_data
->chunks
[new_current_chunk
].syncinfo1
& 0x80000000)) &&
87 (new_current_chunk
> 0))
90 film_data
->current_chunk
= new_current_chunk
;
92 mp_msg(MSGT_DECVIDEO
, MSGL_INFO
," (flags = %X) actual new chunk = %d (syncinfo1 = %08X)\n",
93 flags
, film_data
->current_chunk
, film_data
->chunks
[film_data
->current_chunk
].syncinfo1
);
94 demuxer
->video
->pts
=film_data
->chunks
[film_data
->current_chunk
].pts
;
99 // 0 = EOF or no stream found
100 // 1 = successfully read a packet
101 static int demux_film_fill_buffer(demuxer_t
*demuxer
, demux_stream_t
*ds
)
104 unsigned char byte_swap
;
106 sh_video_t
*sh_video
= demuxer
->video
->sh
;
107 sh_audio_t
*sh_audio
= demuxer
->audio
->sh
;
108 film_data_t
*film_data
= (film_data_t
*)demuxer
->priv
;
109 film_chunk_t film_chunk
;
110 int length_fix_bytes
;
113 // see if the end has been reached
114 if (film_data
->current_chunk
>= film_data
->total_chunks
)
117 film_chunk
= film_data
->chunks
[film_data
->current_chunk
];
119 // position stream and fetch chunk
120 stream_seek(demuxer
->stream
, film_chunk
.chunk_offset
);
122 // load the chunks manually (instead of using ds_read_packet()), since
123 // they require some adjustment
124 // (all ones in syncinfo1 indicates an audio chunk)
125 if (film_chunk
.syncinfo1
== 0xFFFFFFFF)
127 if(demuxer
->audio
->id
>=-1){ // audio not disabled
128 dp
= new_demux_packet(film_chunk
.chunk_size
);
129 if (stream_read(demuxer
->stream
, dp
->buffer
, film_chunk
.chunk_size
) !=
130 film_chunk
.chunk_size
)
132 dp
->pts
= film_chunk
.pts
;
133 dp
->pos
= film_chunk
.chunk_offset
;
136 // adjust the data before queuing it:
137 // 8-bit: signed -> unsigned
138 // 16-bit: big-endian -> little-endian
139 if (sh_audio
->wf
->wBitsPerSample
== 8)
140 for (i
= 0; i
< film_chunk
.chunk_size
; i
++)
141 dp
->buffer
[i
] += 128;
143 for (i
= 0; i
< film_chunk
.chunk_size
; i
+= 2)
145 byte_swap
= dp
->buffer
[i
];
146 dp
->buffer
[i
] = dp
->buffer
[i
+ 1];
147 dp
->buffer
[i
+ 1] = byte_swap
;
150 /* for SegaSaturn .cpk file, translate audio data if stereo */
151 if (sh_audio
->wf
->nChannels
== 2) {
152 if (sh_audio
->wf
->wBitsPerSample
== 8) {
153 unsigned char* tmp
= dp
->buffer
;
154 unsigned char buf
[film_chunk
.chunk_size
];
155 for(i
= 0; i
< film_chunk
.chunk_size
/2; i
++) {
157 buf
[i
*2+1] = tmp
[film_chunk
.chunk_size
/2+i
];
159 memcpy( tmp
, buf
, film_chunk
.chunk_size
);
161 else {/* for 16bit */
162 unsigned short* tmp
= dp
->buffer
;
163 unsigned short buf
[film_chunk
.chunk_size
/2];
164 for(i
= 0; i
< film_chunk
.chunk_size
/4; i
++) {
166 buf
[i
*2+1] = tmp
[film_chunk
.chunk_size
/4+i
];
168 memcpy( tmp
, buf
, film_chunk
.chunk_size
);
172 // append packet to DS stream
173 ds_add_packet(demuxer
->audio
, dp
);
178 // if the demuxer is dealing with CVID data, deal with it a special way
179 if (sh_video
->format
== mmioFOURCC('c', 'v', 'i', 'd'))
181 if (film_data
->film_version
)
182 length_fix_bytes
= 2;
184 length_fix_bytes
= 6;
186 // account for the fix bytes when allocating the buffer
187 dp
= new_demux_packet(film_chunk
.chunk_size
- length_fix_bytes
);
189 // these CVID data chunks have a few extra bytes; skip them
190 if (stream_read(demuxer
->stream
, dp
->buffer
, 10) != 10)
192 stream_skip(demuxer
->stream
, length_fix_bytes
);
194 if (stream_read(demuxer
->stream
, dp
->buffer
+ 10,
195 film_chunk
.chunk_size
- (10 + length_fix_bytes
)) !=
196 (film_chunk
.chunk_size
- (10 + length_fix_bytes
)))
199 dp
->pts
= film_chunk
.pts
;
200 dp
->pos
= film_chunk
.chunk_offset
;
201 dp
->flags
= (film_chunk
.syncinfo1
& 0x80000000) ? 1 : 0;
203 // fix the CVID chunk size
204 cvid_size
= film_chunk
.chunk_size
- length_fix_bytes
;
205 dp
->buffer
[1] = (cvid_size
>> 16) & 0xFF;
206 dp
->buffer
[2] = (cvid_size
>> 8) & 0xFF;
207 dp
->buffer
[3] = (cvid_size
>> 0) & 0xFF;
209 // append packet to DS stream
210 ds_add_packet(demuxer
->video
, dp
);
214 ds_read_packet(demuxer
->video
, demuxer
->stream
, film_chunk
.chunk_size
,
216 film_chunk
.chunk_offset
, (film_chunk
.syncinfo1
& 0x80000000) ? 1 : 0);
219 film_data
->current_chunk
++;
224 static demuxer_t
* demux_open_film(demuxer_t
* demuxer
)
226 sh_video_t
*sh_video
= NULL
;
227 sh_audio_t
*sh_audio
= NULL
;
228 film_data_t
*film_data
;
229 film_chunk_t film_chunk
;
231 unsigned int chunk_type
;
232 unsigned int chunk_size
;
234 unsigned int video_format
;
237 unsigned int total_audio_bytes
= 0;
239 film_data
= malloc(sizeof(film_data_t
));
240 film_data
->total_chunks
= 0;
241 film_data
->current_chunk
= 0;
242 film_data
->chunks
= NULL
;
243 film_data
->chunks_per_second
= 0;
245 // go back to the beginning
246 stream_reset(demuxer
->stream
);
247 stream_seek(demuxer
->stream
, 0);
249 // read the master chunk type
250 chunk_type
= stream_read_fourcc(demuxer
->stream
);
251 // validate the chunk type
252 if (chunk_type
!= CHUNK_FILM
)
254 mp_msg(MSGT_DEMUX
, MSGL_ERR
, "Not a FILM file\n");
259 // get the header size, which implicitly points past the header and
260 // to the start of the data
261 header_size
= stream_read_dword(demuxer
->stream
);
262 film_data
->film_version
= stream_read_fourcc(demuxer
->stream
);
263 demuxer
->movi_start
= header_size
;
264 demuxer
->movi_end
= demuxer
->stream
->end_pos
;
267 mp_msg(MSGT_DEMUX
, MSGL_HINT
, "FILM version %.4s\n",
268 (char *)&film_data
->film_version
);
270 // skip to where the next chunk should be
271 stream_skip(demuxer
->stream
, 4);
273 // traverse through the header
274 while (header_size
> 0)
276 // fetch the chunk type and size
277 chunk_type
= stream_read_fourcc(demuxer
->stream
);
278 chunk_size
= stream_read_dword(demuxer
->stream
);
279 header_size
-= chunk_size
;
284 mp_msg(MSGT_DECVIDEO
, MSGL_V
, "parsing FDSC chunk\n");
286 // fetch the video codec fourcc to see if there's any video
287 video_format
= stream_read_fourcc(demuxer
->stream
);
290 // create and initialize the video stream header
291 sh_video
= new_sh_video(demuxer
, 0);
292 demuxer
->video
->sh
= sh_video
;
293 sh_video
->ds
= demuxer
->video
;
295 sh_video
->format
= video_format
;
296 sh_video
->disp_h
= stream_read_dword(demuxer
->stream
);
297 sh_video
->disp_w
= stream_read_dword(demuxer
->stream
);
298 mp_msg(MSGT_DECVIDEO
, MSGL_V
,
299 " FILM video: %d x %d\n", sh_video
->disp_w
,
303 // skip height and width if no video
304 stream_skip(demuxer
->stream
, 8);
306 if(demuxer
->audio
->id
<-1){
307 mp_msg(MSGT_DECVIDEO
, MSGL_INFO
,"chunk size = 0x%X \n",chunk_size
);
308 stream_skip(demuxer
->stream
, chunk_size
-12-8);
309 break; // audio disabled (or no soundcard)
312 // skip over unknown byte, but only if file had non-NULL version
313 if (film_data
->film_version
)
314 stream_skip(demuxer
->stream
, 1);
316 // fetch the audio channels to see if there's any audio
317 // don't do this if the file is a quirky file with NULL version
318 if (film_data
->film_version
)
320 audio_channels
= stream_read_char(demuxer
->stream
);
321 if (audio_channels
> 0)
323 // create and initialize the audio stream header
324 sh_audio
= new_sh_audio(demuxer
, 0);
325 demuxer
->audio
->id
= 0;
326 demuxer
->audio
->sh
= sh_audio
;
327 sh_audio
->ds
= demuxer
->audio
;
329 sh_audio
->wf
= malloc(sizeof(WAVEFORMATEX
));
331 // uncompressed PCM format
332 sh_audio
->wf
->wFormatTag
= 1;
333 sh_audio
->format
= 1;
334 sh_audio
->wf
->nChannels
= audio_channels
;
335 sh_audio
->wf
->wBitsPerSample
= stream_read_char(demuxer
->stream
);
336 stream_skip(demuxer
->stream
, 1); // skip unknown byte
337 sh_audio
->wf
->nSamplesPerSec
= stream_read_word(demuxer
->stream
);
338 sh_audio
->wf
->nAvgBytesPerSec
=
339 sh_audio
->wf
->nSamplesPerSec
* sh_audio
->wf
->wBitsPerSample
340 * sh_audio
->wf
->nChannels
/ 8;
341 stream_skip(demuxer
->stream
, 6); // skip the rest of the unknown
343 mp_msg(MSGT_DECVIDEO
, MSGL_V
,
344 " FILM audio: %d channels, %d bits, %d Hz\n",
345 sh_audio
->wf
->nChannels
, 8 * sh_audio
->wf
->wBitsPerSample
,
346 sh_audio
->wf
->nSamplesPerSec
);
349 stream_skip(demuxer
->stream
, 10);
353 // otherwise, make some assumptions about the audio
355 // create and initialize the audio stream header
356 sh_audio
= new_sh_audio(demuxer
, 0);
357 demuxer
->audio
->sh
= sh_audio
;
358 sh_audio
->ds
= demuxer
->audio
;
360 sh_audio
->wf
= malloc(sizeof(WAVEFORMATEX
));
362 // uncompressed PCM format
363 sh_audio
->wf
->wFormatTag
= 1;
364 sh_audio
->format
= 1;
365 sh_audio
->wf
->nChannels
= 1;
366 sh_audio
->wf
->wBitsPerSample
= 8;
367 sh_audio
->wf
->nSamplesPerSec
= 22050;
368 sh_audio
->wf
->nAvgBytesPerSec
=
369 sh_audio
->wf
->nSamplesPerSec
* sh_audio
->wf
->wBitsPerSample
370 * sh_audio
->wf
->nChannels
/ 8;
372 mp_msg(MSGT_DECVIDEO
, MSGL_V
,
373 " FILM audio: %d channels, %d bits, %d Hz\n",
374 sh_audio
->wf
->nChannels
, sh_audio
->wf
->wBitsPerSample
,
375 sh_audio
->wf
->nSamplesPerSec
);
380 mp_msg(MSGT_DECVIDEO
, MSGL_V
, "parsing STAB chunk\n");
384 sh_video
->fps
= stream_read_dword(demuxer
->stream
);
385 sh_video
->frametime
= 1.0 / sh_video
->fps
;
388 // fetch the number of chunks
389 film_data
->total_chunks
= stream_read_dword(demuxer
->stream
);
390 film_data
->current_chunk
= 0;
391 mp_msg(MSGT_DECVIDEO
, MSGL_V
,
392 " STAB chunk contains %d chunks\n", film_data
->total_chunks
);
394 // allocate enough entries for the chunk
396 calloc(film_data
->total_chunks
, sizeof(film_chunk_t
));
398 // build the chunk index
400 for (i
= 0; i
< film_data
->total_chunks
; i
++)
402 film_chunk
= film_data
->chunks
[i
];
403 film_chunk
.chunk_offset
=
404 demuxer
->movi_start
+ stream_read_dword(demuxer
->stream
);
405 film_chunk
.chunk_size
= stream_read_dword(demuxer
->stream
);
406 film_chunk
.syncinfo1
= stream_read_dword(demuxer
->stream
);
407 film_chunk
.syncinfo2
= stream_read_dword(demuxer
->stream
);
409 // count chunks for the purposes of seeking
412 // if we're counting chunks, always count an audio chunk
413 if (film_chunk
.syncinfo1
== 0xFFFFFFFF)
414 film_data
->chunks_per_second
++;
415 // if it's a video chunk, check if it's time to stop counting
416 else if ((film_chunk
.syncinfo1
& 0x7FFFFFFF) >= sh_video
->fps
)
419 film_data
->chunks_per_second
++;
423 if (film_chunk
.syncinfo1
== 0xFFFFFFFF)
425 if(demuxer
->audio
->id
>=-1)
427 (float)total_audio_bytes
/ (float)sh_audio
->wf
->nAvgBytesPerSec
;
428 total_audio_bytes
+= film_chunk
.chunk_size
;
432 (film_chunk
.syncinfo1
& 0x7FFFFFFF) / sh_video
->fps
;
434 film_data
->chunks
[i
] = film_chunk
;
437 // in some FILM files (notably '1.09'), the length of the FDSC chunk
438 // follows different rules
439 if (chunk_size
== (film_data
->total_chunks
* 16))
444 mp_msg(MSGT_DEMUX
, MSGL_ERR
, "Unrecognized FILM header chunk: %08X\n",
451 demuxer
->priv
= film_data
;
456 static void demux_close_film(demuxer_t
* demuxer
) {
457 film_data_t
*film_data
= demuxer
->priv
;
461 if(film_data
->chunks
)
462 free(film_data
->chunks
);
467 static int film_check_file(demuxer_t
* demuxer
)
469 int signature
=stream_read_fourcc(demuxer
->stream
);
471 // check for the FILM file magic number
472 if(signature
==mmioFOURCC('F', 'I', 'L', 'M'))
473 return DEMUXER_TYPE_FILM
;
479 const demuxer_desc_t demuxer_desc_film
= {
480 "FILM/CPK demuxer for Sega Saturn CD-ROM games",
486 0, // unsafe autodetect (short signature)
488 demux_film_fill_buffer
,