mirror of
https://github.com/mpv-player/mpv
synced 2025-01-16 22:37:28 +01:00
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:
parent
766d6928dc
commit
8a77bc1aec
@ -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:
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user