FILM demuxer is leaner, meaner, and cleaner, also with proper bailout on

EOF and preliminary seeking support (not perfect yet)


git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@5158 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
melanson 2002-03-17 02:59:04 +00:00
parent 766d6928dc
commit 8a77bc1aec
2 changed files with 69 additions and 53 deletions

View File

@ -27,43 +27,51 @@ typedef struct _film_chunk_t
{
off_t chunk_offset;
int chunk_size;
unsigned int syncinfo1;
unsigned int syncinfo2;
unsigned int video_chunk_number; // in the case of a video chunk
unsigned int running_audio_sample_count; // for an audio chunk
} film_chunk_t;
typedef struct _film_data_t
{
int total_chunks;
int current_chunk;
int total_video_chunks;
int total_audio_sample_count;
unsigned int total_chunks;
unsigned int current_chunk;
film_chunk_t *chunks;
unsigned int ticks;
unsigned int film_version;
unsigned int chunks_per_second;
} film_data_t;
#if 0
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)
{
film_frames_t *frames = (film_frames_t *)demuxer->priv;
sh_video_t *sh_video = demuxer->video->sh;
int newpos=(flags&1)?0:frames->current_frame;
if(flags&2){
// float 0..1
newpos+=rel_seek_secs*frames->num_frames;
} else {
// secs
newpos+=rel_seek_secs*sh_video->fps;
}
if(newpos<0) newpos=0; else
if(newpos>frames->num_frames) newpos=frames->num_frames;
frames->current_frame=newpos;
film_data_t *film_data = (film_data_t *)demuxer->priv;
int new_current_chunk;
// bit 2 of the flags apparently means that the seek is relative to
// the beginning of the file
if (flags & 1)
new_current_chunk =
rel_seek_secs * film_data->chunks_per_second;
else
new_current_chunk = film_data->current_chunk +
rel_seek_secs * film_data->chunks_per_second;
printf ("current, total chunks = %d, %d; seek %5.3f sec, new chunk guess = %d\n",
film_data->current_chunk, film_data->total_chunks,
rel_seek_secs, new_current_chunk);
// check if the new chunk number is valid
if (new_current_chunk < 0)
new_current_chunk = 0;
if ((unsigned int)new_current_chunk > film_data->total_chunks)
new_current_chunk = film_data->total_chunks;
while (((film_data->chunks[new_current_chunk].syncinfo1 == 0xFFFFFFFF) ||
(film_data->chunks[new_current_chunk].syncinfo1 & 0x80000000)) &&
(new_current_chunk > 0))
new_current_chunk--;
printf (" actual new chunk = %d (syncinfo1 = %08X)\n",
new_current_chunk, film_data->chunks[new_current_chunk].syncinfo1);
film_data->current_chunk = new_current_chunk;
}
#endif
// return value:
// 0 = EOF or no stream found
@ -93,7 +101,9 @@ int demux_film_fill_buffer(demuxer_t *demuxer)
if (film_chunk.syncinfo1 == 0xFFFFFFFF)
{
demux_packet_t* dp=new_demux_packet(film_chunk.chunk_size);
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)
return 0;
dp->pts = 0;
dp->pos = film_chunk.chunk_offset;
dp->flags = 0;
@ -125,9 +135,12 @@ int demux_film_fill_buffer(demuxer_t *demuxer)
demux_packet_t* dp=new_demux_packet(film_chunk.chunk_size - 2);
// these CVID data chunks appear to have 2 extra bytes; skip them
stream_read(demuxer->stream, dp->buffer, 10);
if (stream_read(demuxer->stream, dp->buffer, 10) != 10)
return 0;
stream_skip(demuxer->stream, 2);
stream_read(demuxer->stream, dp->buffer + 10, film_chunk.chunk_size - 12);
if (stream_read(demuxer->stream, dp->buffer + 10,
film_chunk.chunk_size - 12) != (film_chunk.chunk_size - 12))
return 0;
dp->pts = (film_chunk.syncinfo1 & 0x7FFFFFFF) / sh_video->fps;
dp->pos = film_chunk.chunk_offset;
dp->flags = (film_chunk.syncinfo1 & 0x80000000) ? 1 : 0;
@ -164,18 +177,17 @@ demuxer_t* demux_open_film(demuxer_t* demuxer)
int header_size;
unsigned int chunk_type;
unsigned int chunk_size;
int i;
unsigned int i;
unsigned int video_format;
int largest_audio_chunk = 0;
int audio_channels;
unsigned int film_version;
int counting_chunks;
film_data = (film_data_t *)malloc(sizeof(film_data_t));
film_data->total_chunks = 0;
film_data->current_chunk = 0;
film_data->total_video_chunks = 0;
film_data->chunks = NULL;
film_data->ticks = 0;
film_data->chunks_per_second = 0;
// go back to the beginning
stream_reset(demuxer->stream);
@ -193,11 +205,13 @@ demuxer_t* demux_open_film(demuxer_t* demuxer)
// get the header size, which implicitly points past the header and
// to the start of the data
header_size = stream_read_dword(demuxer->stream);
film_data->film_version = stream_read_fourcc(demuxer->stream);
film_version = stream_read_fourcc(demuxer->stream);
demuxer->movi_start = header_size;
demuxer->movi_end = demuxer->stream->end_pos;
header_size -= 16;
mp_msg(MSGT_DEMUX, MSGL_HINT, "FILM version %.4s\n", &film_version);
// skip to where the next chunk should be
stream_skip(demuxer->stream, 4);
@ -213,6 +227,7 @@ demuxer_t* demux_open_film(demuxer_t* demuxer)
{
case CHUNK_FDSC:
mp_msg(MSGT_DECVIDEO, MSGL_V, "parsing FDSC chunk\n");
// fetch the video codec fourcc to see if there's any video
video_format = stream_read_fourcc(demuxer->stream);
if (video_format)
@ -268,12 +283,9 @@ demuxer_t* demux_open_film(demuxer_t* demuxer)
case CHUNK_STAB:
mp_msg(MSGT_DECVIDEO, MSGL_V, "parsing STAB chunk\n");
// FPS hack based on empirical observation
if (sh_video)
{
sh_video->fps = stream_read_dword(demuxer->stream);
// if (film_data->film_version != VERSION_1_01)
// sh_video->fps = MAGIC_FPS_CONSTANT;
sh_video->frametime = 1.0 / sh_video->fps;
}
@ -288,6 +300,7 @@ demuxer_t* demux_open_film(demuxer_t* demuxer)
(film_chunk_t *)malloc(film_data->total_chunks * sizeof(film_chunk_t));
// build the chunk index
counting_chunks = 1;
for (i = 0; i < film_data->total_chunks; i++)
{
film_chunk = film_data->chunks[i];
@ -298,24 +311,24 @@ demuxer_t* demux_open_film(demuxer_t* demuxer)
film_chunk.syncinfo2 = stream_read_dword(demuxer->stream);
film_data->chunks[i] = film_chunk;
// audio housekeeping
if (sh_audio)
// count chunks for the purposes of seeking
if (counting_chunks)
{
if ((film_chunk.syncinfo1 == 0xFFFFFFFF) &&
(film_chunk.chunk_size > largest_audio_chunk))
largest_audio_chunk = film_chunk.chunk_size;
film_data->total_audio_sample_count +=
(chunk_size / sh_audio->wf->nChannels);
}
// video housekeeping
if (sh_video)
{
if (film_chunk.syncinfo1 != 0xFFFFFFFF)
film_chunk.video_chunk_number =
film_data->total_video_chunks++;
// if we're counting chunks, always count an audio chunk
if (film_chunk.syncinfo1 == 0xFFFFFFFF)
film_data->chunks_per_second++;
// if it's a video chunk, check if it's time to stop counting
else if ((film_chunk.syncinfo1 & 0x7FFFFFFF) >= sh_video->fps)
counting_chunks = 0;
else
film_data->chunks_per_second++;
}
}
// in some FILM files (notable '1.09'), the length of the FDSC chunk
// follows different rules
if (chunk_size == (film_data->total_chunks * 16))
header_size -= 16;
break;
default:

View File

@ -893,6 +893,7 @@ int demux_seek_asf(demuxer_t *demuxer,float rel_seek_secs,int flags);
int demux_seek_mpg(demuxer_t *demuxer,float rel_seek_secs,int flags);
int demux_seek_y4m(demuxer_t *demuxer,float rel_seek_secs,int flags);
int demux_seek_fli(demuxer_t *demuxer,float rel_seek_secs,int flags);
int demux_seek_film(demuxer_t *demuxer,float rel_seek_secs,int flags);
int demux_seek_mf(demuxer_t *demuxer,float rel_seek_secs,int flags);
int demux_seek_nuv(demuxer_t *demuxer,float rel_seek_secs,int flags);
void demux_seek_mov(demuxer_t *demuxer,float pts,int flags);
@ -959,6 +960,8 @@ switch(demuxer->file_format){
case DEMUXER_TYPE_FLI:
demux_seek_fli(demuxer,rel_seek_secs,flags); break;
case DEMUXER_TYPE_FILM:
demux_seek_film(demuxer,rel_seek_secs,flags); break;
case DEMUXER_TYPE_NUV:
demux_seek_nuv(demuxer,rel_seek_secs,flags); break;
case DEMUXER_TYPE_AUDIO: