comparison libmpdemux/demux_film.c @ 5143:3958674b696b

added proper PTS support for FILM demuxer
author melanson
date Sat, 16 Mar 2002 19:58:07 +0000
parents 1504901deed8
children f67b321e1eda
comparison
equal deleted inserted replaced
5142:7fc559dbc607 5143:3958674b696b
21 // chunk types found in a FILM file 21 // chunk types found in a FILM file
22 #define CHUNK_FILM mmioFOURCC('F', 'I', 'L', 'M') 22 #define CHUNK_FILM mmioFOURCC('F', 'I', 'L', 'M')
23 #define CHUNK_FDSC mmioFOURCC('F', 'D', 'S', 'C') 23 #define CHUNK_FDSC mmioFOURCC('F', 'D', 'S', 'C')
24 #define CHUNK_STAB mmioFOURCC('S', 'T', 'A', 'B') 24 #define CHUNK_STAB mmioFOURCC('S', 'T', 'A', 'B')
25 25
26 #define VERSION_1_01 mmioFOURCC('1', '.', '0', '1')
27
28 #define MAGIC_FPS_CONSTANT 27
29
30 typedef struct _film_chunk_t 26 typedef struct _film_chunk_t
31 { 27 {
32 off_t chunk_offset; 28 off_t chunk_offset;
33 int chunk_size; 29 int chunk_size;
34 30
35 unsigned int flags1; 31 unsigned int syncinfo1;
36 unsigned int flags2; 32 unsigned int syncinfo2;
37 33
38 unsigned int video_chunk_number; // in the case of a video chunk 34 unsigned int video_chunk_number; // in the case of a video chunk
39 unsigned int running_audio_sample_count; // for an audio chunk 35 unsigned int running_audio_sample_count; // for an audio chunk
40 } film_chunk_t; 36 } film_chunk_t;
41 37
91 // position stream and fetch chunk 87 // position stream and fetch chunk
92 stream_seek(demuxer->stream, film_chunk.chunk_offset); 88 stream_seek(demuxer->stream, film_chunk.chunk_offset);
93 89
94 // load the chunks manually (instead of using ds_read_packet()), since 90 // load the chunks manually (instead of using ds_read_packet()), since
95 // they require some adjustment 91 // they require some adjustment
96 // (all ones in flags1 indicates an audio chunk) 92 // (all ones in syncinfo1 indicates an audio chunk)
97 if (film_chunk.flags1 == 0xFFFFFFFF) 93 if (film_chunk.syncinfo1 == 0xFFFFFFFF)
98 { 94 {
99 demux_packet_t* dp=new_demux_packet(film_chunk.chunk_size); 95 demux_packet_t* dp=new_demux_packet(film_chunk.chunk_size);
100 stream_read(demuxer->stream, dp->buffer, film_chunk.chunk_size); 96 stream_read(demuxer->stream, dp->buffer, film_chunk.chunk_size);
101 dp->pts = 0; 97 dp->pts = 0;
102 dp->pos = film_chunk.chunk_offset; 98 dp->pos = film_chunk.chunk_offset;
120 ds_add_packet(demuxer->audio, dp); 116 ds_add_packet(demuxer->audio, dp);
121 film_data->current_chunk++; 117 film_data->current_chunk++;
122 } 118 }
123 else 119 else
124 { 120 {
125 // check the tick to see if it's time to dispatch a new frame
126 if ((film_data->film_version == VERSION_1_01) &&
127 ((film_chunk.flags1 & 0x7FFFFFFF) != film_data->ticks++))
128 {
129 demux_packet_t* dp=new_demux_packet(0);
130 dp->pts = 0;
131 dp->pos = 0;
132 dp->flags = 0;
133 ds_add_packet(demuxer->video, dp);
134 }
135 // if the demuxer is dealing with CVID data, deal with it a special way 121 // if the demuxer is dealing with CVID data, deal with it a special way
136 else if (sh_video->format == mmioFOURCC('c', 'v', 'i', 'd')) 122 if (sh_video->format == mmioFOURCC('c', 'v', 'i', 'd'))
137 { 123 {
138 // account for 2 extra bytes 124 // account for 2 extra bytes
139 demux_packet_t* dp=new_demux_packet(film_chunk.chunk_size - 2); 125 demux_packet_t* dp=new_demux_packet(film_chunk.chunk_size - 2);
140 126
141 // these CVID data chunks appear to have 2 extra bytes; skip them 127 // these CVID data chunks appear to have 2 extra bytes; skip them
142 stream_read(demuxer->stream, dp->buffer, 10); 128 stream_read(demuxer->stream, dp->buffer, 10);
143 stream_skip(demuxer->stream, 2); 129 stream_skip(demuxer->stream, 2);
144 stream_read(demuxer->stream, dp->buffer + 10, film_chunk.chunk_size - 12); 130 stream_read(demuxer->stream, dp->buffer + 10, film_chunk.chunk_size - 12);
145 dp->pts = film_chunk.video_chunk_number / sh_video->fps; 131 dp->pts = (film_chunk.syncinfo1 & 0x7FFFFFFF) / sh_video->fps;
146 dp->pos = film_chunk.chunk_offset; 132 dp->pos = film_chunk.chunk_offset;
147 dp->flags = (film_chunk.flags1 & 0x80000000) ? 1 : 0; 133 dp->flags = (film_chunk.syncinfo1 & 0x80000000) ? 1 : 0;
148 134
149 // fix the CVID chunk size by adding 6 135 // fix the CVID chunk size by adding 6
150 cvid_size = (dp->buffer[1] << 16) | (dp->buffer[2] << 8) | dp->buffer[3]; 136 cvid_size = (dp->buffer[1] << 16) | (dp->buffer[2] << 8) | dp->buffer[3];
151 cvid_size += 6; 137 cvid_size += 6;
152 dp->buffer[1] = (cvid_size >> 16) & 0xFF; 138 dp->buffer[1] = (cvid_size >> 16) & 0xFF;
158 film_data->current_chunk++; 144 film_data->current_chunk++;
159 } 145 }
160 else 146 else
161 { 147 {
162 ds_read_packet(demuxer->video, demuxer->stream, film_chunk.chunk_size, 148 ds_read_packet(demuxer->video, demuxer->stream, film_chunk.chunk_size,
163 film_chunk.video_chunk_number / sh_video->fps, /* pts */ 149 (film_chunk.syncinfo1 & 0x7FFFFFFF) / sh_video->fps,
164 film_chunk.chunk_offset, (film_chunk.flags1 & 0x80000000) ? 1 : 0); 150 film_chunk.chunk_offset, (film_chunk.syncinfo1 & 0x80000000) ? 1 : 0);
165 film_data->current_chunk++; 151 film_data->current_chunk++;
166 } 152 }
167 } 153 }
168 154
169 return 1; 155 return 1;
284 270
285 // FPS hack based on empirical observation 271 // FPS hack based on empirical observation
286 if (sh_video) 272 if (sh_video)
287 { 273 {
288 sh_video->fps = stream_read_dword(demuxer->stream); 274 sh_video->fps = stream_read_dword(demuxer->stream);
289 if (film_data->film_version != VERSION_1_01) 275 // if (film_data->film_version != VERSION_1_01)
290 sh_video->fps = MAGIC_FPS_CONSTANT; 276 // sh_video->fps = MAGIC_FPS_CONSTANT;
291 sh_video->frametime = 1 / sh_video->fps; 277 sh_video->frametime = 1.0 / sh_video->fps;
292 } 278 }
293 279
294 // fetch the number of chunks 280 // fetch the number of chunks
295 film_data->total_chunks = stream_read_dword(demuxer->stream); 281 film_data->total_chunks = stream_read_dword(demuxer->stream);
296 film_data->current_chunk = 0; 282 film_data->current_chunk = 0;
306 { 292 {
307 film_chunk = film_data->chunks[i]; 293 film_chunk = film_data->chunks[i];
308 film_chunk.chunk_offset = 294 film_chunk.chunk_offset =
309 demuxer->movi_start + stream_read_dword(demuxer->stream); 295 demuxer->movi_start + stream_read_dword(demuxer->stream);
310 film_chunk.chunk_size = stream_read_dword(demuxer->stream); 296 film_chunk.chunk_size = stream_read_dword(demuxer->stream);
311 film_chunk.flags1 = stream_read_dword(demuxer->stream); 297 film_chunk.syncinfo1 = stream_read_dword(demuxer->stream);
312 film_chunk.flags2 = stream_read_dword(demuxer->stream); 298 film_chunk.syncinfo2 = stream_read_dword(demuxer->stream);
313 film_data->chunks[i] = film_chunk; 299 film_data->chunks[i] = film_chunk;
314 300
315 // audio housekeeping 301 // audio housekeeping
316 if (sh_audio) 302 if (sh_audio)
317 { 303 {
318 if ((film_chunk.flags1 == 0xFFFFFFFF) && 304 if ((film_chunk.syncinfo1 == 0xFFFFFFFF) &&
319 (film_chunk.chunk_size > largest_audio_chunk)) 305 (film_chunk.chunk_size > largest_audio_chunk))
320 largest_audio_chunk = film_chunk.chunk_size; 306 largest_audio_chunk = film_chunk.chunk_size;
321 film_data->total_audio_sample_count += 307 film_data->total_audio_sample_count +=
322 (chunk_size / sh_audio->wf->nChannels); 308 (chunk_size / sh_audio->wf->nChannels);
323 } 309 }
324 310
325 // video housekeeping 311 // video housekeeping
326 if (sh_video) 312 if (sh_video)
327 { 313 {
328 if (film_chunk.flags1 != 0xFFFFFFFF) 314 if (film_chunk.syncinfo1 != 0xFFFFFFFF)
329 film_chunk.video_chunk_number = 315 film_chunk.video_chunk_number =
330 film_data->total_video_chunks++; 316 film_data->total_video_chunks++;
331 } 317 }
332 } 318 }
333 break; 319 break;