1
0
mirror of https://github.com/mpv-player/mpv synced 2025-04-11 04:01:31 +00:00

fixed to be able to handle extra-quirky .film files on Lemmings 3DO

console game


git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@5414 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
melanson 2002-03-31 02:57:53 +00:00
parent 06e95aef16
commit ddf20c18da

View File

@ -2,6 +2,10 @@
FILM file parser for the MPlayer program FILM file parser for the MPlayer program
by Mike Melanson by Mike Melanson
This demuxer handles FILM (a.k.a. CPK) files commonly found on
Sega Saturn CD-ROM games. FILM files have also been found on 3DO
games.
Details of the FILM file format can be found at: Details of the FILM file format can be found at:
http://www.pcisys.net/~melanson/codecs/ http://www.pcisys.net/~melanson/codecs/
*/ */
@ -39,6 +43,7 @@ typedef struct _film_data_t
unsigned int current_chunk; unsigned int current_chunk;
film_chunk_t *chunks; film_chunk_t *chunks;
unsigned int chunks_per_second; unsigned int chunks_per_second;
unsigned int film_version;
} film_data_t; } film_data_t;
void demux_seek_film(demuxer_t *demuxer, float rel_seek_secs, int flags) void demux_seek_film(demuxer_t *demuxer, float rel_seek_secs, int flags)
@ -88,6 +93,8 @@ int demux_film_fill_buffer(demuxer_t *demuxer)
sh_audio_t *sh_audio = demuxer->audio->sh; sh_audio_t *sh_audio = demuxer->audio->sh;
film_data_t *film_data = (film_data_t *)demuxer->priv; film_data_t *film_data = (film_data_t *)demuxer->priv;
film_chunk_t film_chunk; film_chunk_t film_chunk;
int length_fix_bytes;
demux_packet_t* dp;
// see if the end has been reached // see if the end has been reached
if (film_data->current_chunk >= film_data->total_chunks) if (film_data->current_chunk >= film_data->total_chunks)
@ -103,7 +110,7 @@ int demux_film_fill_buffer(demuxer_t *demuxer)
// (all ones in syncinfo1 indicates an audio chunk) // (all ones in syncinfo1 indicates an audio chunk)
if (film_chunk.syncinfo1 == 0xFFFFFFFF) if (film_chunk.syncinfo1 == 0xFFFFFFFF)
{ {
demux_packet_t* dp=new_demux_packet(film_chunk.chunk_size); dp = new_demux_packet(film_chunk.chunk_size);
if (stream_read(demuxer->stream, dp->buffer, film_chunk.chunk_size) != if (stream_read(demuxer->stream, dp->buffer, film_chunk.chunk_size) !=
film_chunk.chunk_size) film_chunk.chunk_size)
return 0; return 0;
@ -134,23 +141,30 @@ int demux_film_fill_buffer(demuxer_t *demuxer)
// if the demuxer is dealing with CVID data, deal with it a special way // if the demuxer is dealing with CVID data, deal with it a special way
if (sh_video->format == mmioFOURCC('c', 'v', 'i', 'd')) if (sh_video->format == mmioFOURCC('c', 'v', 'i', 'd'))
{ {
// account for 2 extra bytes if (film_data->film_version)
demux_packet_t* dp=new_demux_packet(film_chunk.chunk_size - 2); length_fix_bytes = 2;
else
length_fix_bytes = 6;
// these CVID data chunks appear to have 2 extra bytes; skip them // account for the fix bytes when allocating the buffer
dp = new_demux_packet(film_chunk.chunk_size - length_fix_bytes);
// these CVID data chunks have a few extra bytes; skip them
if (stream_read(demuxer->stream, dp->buffer, 10) != 10) if (stream_read(demuxer->stream, dp->buffer, 10) != 10)
return 0; return 0;
stream_skip(demuxer->stream, 2); stream_skip(demuxer->stream, length_fix_bytes);
if (stream_read(demuxer->stream, dp->buffer + 10, if (stream_read(demuxer->stream, dp->buffer + 10,
film_chunk.chunk_size - 12) != (film_chunk.chunk_size - 12)) film_chunk.chunk_size - (10 + length_fix_bytes)) !=
(film_chunk.chunk_size - (10 + length_fix_bytes)))
return 0; return 0;
dp->pts = film_chunk.pts; dp->pts = film_chunk.pts;
dp->pos = film_chunk.chunk_offset; dp->pos = film_chunk.chunk_offset;
dp->flags = (film_chunk.syncinfo1 & 0x80000000) ? 1 : 0; dp->flags = (film_chunk.syncinfo1 & 0x80000000) ? 1 : 0;
// fix the CVID chunk size by adding 6 // fix the CVID chunk size
cvid_size = (dp->buffer[1] << 16) | (dp->buffer[2] << 8) | dp->buffer[3]; cvid_size = film_chunk.chunk_size - length_fix_bytes;
cvid_size += 6;
dp->buffer[1] = (cvid_size >> 16) & 0xFF; dp->buffer[1] = (cvid_size >> 16) & 0xFF;
dp->buffer[2] = (cvid_size >> 8) & 0xFF; dp->buffer[2] = (cvid_size >> 8) & 0xFF;
dp->buffer[3] = (cvid_size >> 0) & 0xFF; dp->buffer[3] = (cvid_size >> 0) & 0xFF;
@ -183,7 +197,6 @@ demuxer_t* demux_open_film(demuxer_t* demuxer)
unsigned int i; unsigned int i;
unsigned int video_format; unsigned int video_format;
int audio_channels; int audio_channels;
unsigned int film_version;
int counting_chunks; int counting_chunks;
unsigned int total_audio_bytes = 0; unsigned int total_audio_bytes = 0;
@ -209,12 +222,13 @@ demuxer_t* demux_open_film(demuxer_t* demuxer)
// get the header size, which implicitly points past the header and // get the header size, which implicitly points past the header and
// to the start of the data // to the start of the data
header_size = stream_read_dword(demuxer->stream); header_size = stream_read_dword(demuxer->stream);
film_version = stream_read_fourcc(demuxer->stream); film_data->film_version = stream_read_fourcc(demuxer->stream);
demuxer->movi_start = header_size; demuxer->movi_start = header_size;
demuxer->movi_end = demuxer->stream->end_pos; demuxer->movi_end = demuxer->stream->end_pos;
header_size -= 16; header_size -= 16;
mp_msg(MSGT_DEMUX, MSGL_HINT, "FILM version %.4s\n", &film_version); mp_msg(MSGT_DEMUX, MSGL_HINT, "FILM version %.4s\n",
&film_data->film_version);
// skip to where the next chunk should be // skip to where the next chunk should be
stream_skip(demuxer->stream, 4); stream_skip(demuxer->stream, 4);
@ -244,15 +258,22 @@ demuxer_t* demux_open_film(demuxer_t* demuxer)
sh_video->format = video_format; sh_video->format = video_format;
sh_video->disp_h = stream_read_dword(demuxer->stream); sh_video->disp_h = stream_read_dword(demuxer->stream);
sh_video->disp_w = stream_read_dword(demuxer->stream); sh_video->disp_w = stream_read_dword(demuxer->stream);
stream_skip(demuxer->stream, 1); // unknown byte
mp_msg(MSGT_DECVIDEO, MSGL_V, mp_msg(MSGT_DECVIDEO, MSGL_V,
" FILM video: %d x %d\n", sh_video->disp_w, " FILM video: %d x %d\n", sh_video->disp_w,
sh_video->disp_h); sh_video->disp_h);
} }
else else
stream_skip(demuxer->stream, 9); // skip height and width if no video
stream_skip(demuxer->stream, 8);
// skip over unknown byte, but only if file had non-NULL version
if (film_data->film_version)
stream_skip(demuxer->stream, 1);
// fetch the audio channels to see if there's any audio // fetch the audio channels to see if there's any audio
// don't do this if the file is a quirky file with NULL version
if (film_data->film_version)
{
audio_channels = stream_read_char(demuxer->stream); audio_channels = stream_read_char(demuxer->stream);
if (audio_channels > 0) if (audio_channels > 0)
{ {
@ -282,6 +303,33 @@ demuxer_t* demux_open_film(demuxer_t* demuxer)
} }
else else
stream_skip(demuxer->stream, 10); stream_skip(demuxer->stream, 10);
}
else
{
// otherwise, make some assumptions about the audio
// create and initialize the audio stream header
sh_audio = new_sh_audio(demuxer, 0);
demuxer->audio->sh = sh_audio;
sh_audio->ds = demuxer->audio;
sh_audio->wf = (WAVEFORMATEX *)malloc(sizeof(WAVEFORMATEX));
// uncompressed PCM format
sh_audio->wf->wFormatTag = 1;
sh_audio->format = 1;
sh_audio->wf->nChannels = 1;
sh_audio->wf->wBitsPerSample = 8;
sh_audio->wf->nSamplesPerSec = 22050;
sh_audio->wf->nAvgBytesPerSec =
sh_audio->wf->nSamplesPerSec * sh_audio->wf->wBitsPerSample
* sh_audio->wf->nChannels / 8;
mp_msg(MSGT_DECVIDEO, MSGL_V,
" FILM audio: %d channels, %d bits, %d Hz\n",
sh_audio->wf->nChannels, sh_audio->wf->wBitsPerSample,
sh_audio->wf->nSamplesPerSec);
}
break; break;
case CHUNK_STAB: case CHUNK_STAB: