Mercurial > mplayer.hg
comparison libmpdemux/demux_film.c @ 4189:6871d97e4261
initial support for FILM file demuxing
author | melanson |
---|---|
date | Wed, 16 Jan 2002 03:25:07 +0000 |
parents | |
children | 63baf6de03e1 |
comparison
equal
deleted
inserted
replaced
4188:cfd1eed5961d | 4189:6871d97e4261 |
---|---|
1 /* | |
2 FILM file parser for the MPlayer program | |
3 by Mike Melanson | |
4 */ | |
5 | |
6 #include <stdio.h> | |
7 #include <stdlib.h> | |
8 #include <unistd.h> | |
9 | |
10 #include "config.h" | |
11 #include "mp_msg.h" | |
12 #include "help_mp.h" | |
13 | |
14 #include "stream.h" | |
15 #include "demuxer.h" | |
16 #include "stheader.h" | |
17 | |
18 // chunk types found in a FILM file | |
19 #define CHUNK_FILM mmioFOURCC('F', 'I', 'L', 'M') | |
20 #define CHUNK_FDSC mmioFOURCC('F', 'D', 'S', 'C') | |
21 #define CHUNK_STAB mmioFOURCC('S', 'T', 'A', 'B') | |
22 | |
23 typedef struct _film_frames_t { | |
24 int num_frames; | |
25 int current_frame; | |
26 off_t *filepos; | |
27 unsigned int *frame_size; | |
28 unsigned int *flags1; | |
29 unsigned int *flags2; | |
30 } film_frames_t; | |
31 | |
32 void demux_seek_film(demuxer_t *demuxer,float rel_seek_secs,int flags){ | |
33 film_frames_t *frames = (film_frames_t *)demuxer->priv; | |
34 sh_video_t *sh_video = demuxer->video->sh; | |
35 int newpos=(flags&1)?0:frames->current_frame; | |
36 if(flags&2){ | |
37 // float 0..1 | |
38 newpos+=rel_seek_secs*frames->num_frames; | |
39 } else { | |
40 // secs | |
41 newpos+=rel_seek_secs*sh_video->fps; | |
42 } | |
43 if(newpos<0) newpos=0; else | |
44 if(newpos>frames->num_frames) newpos=frames->num_frames; | |
45 frames->current_frame=newpos; | |
46 } | |
47 | |
48 // return value: | |
49 // 0 = EOF or no stream found | |
50 // 1 = successfully read a packet | |
51 int demux_film_fill_buffer(demuxer_t *demuxer){ | |
52 film_frames_t *frames = (film_frames_t *)demuxer->priv; | |
53 sh_video_t *sh_video = demuxer->video->sh; | |
54 | |
55 // see if the end has been reached | |
56 if (frames->current_frame >= frames->num_frames) | |
57 return 0; | |
58 | |
59 // fetch the frame from the file | |
60 // first, position the file properly since ds_read_packet() doesn't | |
61 // seem to do it, even though it takes a file offset as a parameter | |
62 stream_seek(demuxer->stream, frames->filepos[frames->current_frame]); | |
63 ds_read_packet(demuxer->video, | |
64 demuxer->stream, | |
65 frames->frame_size[frames->current_frame], | |
66 frames->current_frame/sh_video->fps, | |
67 frames->filepos[frames->current_frame], | |
68 0 /* what flags? -> demuxer.h (alex) */ | |
69 ); | |
70 | |
71 // get the next frame ready | |
72 frames->current_frame++; | |
73 | |
74 return 1; | |
75 } | |
76 | |
77 demuxer_t* demux_open_film(demuxer_t* demuxer){ | |
78 sh_video_t *sh_video = NULL; | |
79 film_frames_t *frames = (film_frames_t *)malloc(sizeof(film_frames_t)); | |
80 int header_size; | |
81 unsigned int chunk_type; | |
82 unsigned int chunk_size; | |
83 int i; | |
84 | |
85 // go back to the beginning | |
86 stream_reset(demuxer->stream); | |
87 stream_seek(demuxer->stream, 0); | |
88 | |
89 // read the master chunk type | |
90 chunk_type = stream_read_fourcc(demuxer->stream); | |
91 // validate the chunk type | |
92 if (chunk_type != CHUNK_FILM) | |
93 { | |
94 mp_msg(MSGT_DEMUX, MSGL_ERR, "Not a FILM file\n"); | |
95 return(NULL); | |
96 } | |
97 | |
98 // get the header size, which implicitly points past the header and | |
99 // to the start of the data | |
100 header_size = stream_read_dword(demuxer->stream); | |
101 demuxer->movi_start = header_size; | |
102 demuxer->movi_end = demuxer->stream->end_pos; | |
103 header_size -= 16; | |
104 | |
105 // skip to where the next chunk should be | |
106 stream_skip(demuxer->stream, 8); | |
107 | |
108 // create a new video stream header | |
109 sh_video = new_sh_video(demuxer, 0); | |
110 | |
111 // make sure the demuxer knows about the new video stream header | |
112 demuxer->video->sh = sh_video; | |
113 | |
114 // make sure that the video demuxer stream header knows about its | |
115 // parent video demuxer stream, or else | |
116 // video_read_properties() will choke | |
117 sh_video->ds = demuxer->video; | |
118 | |
119 // traverse through the header | |
120 while (header_size > 0) | |
121 { | |
122 // fetch the chunk type and size | |
123 chunk_type = stream_read_fourcc(demuxer->stream); | |
124 chunk_size = stream_read_dword(demuxer->stream); | |
125 header_size -= chunk_size; | |
126 | |
127 switch (chunk_type) | |
128 { | |
129 case CHUNK_FDSC: | |
130 printf ("parsing FDSC chunk\n"); | |
131 // fetch the video codec fourcc, height, then width | |
132 sh_video->format = stream_read_fourcc(demuxer->stream); | |
133 sh_video->disp_h = stream_read_dword(demuxer->stream); | |
134 sh_video->disp_w = stream_read_dword(demuxer->stream); | |
135 // temporary; one of these fields has to specify FPS | |
136 stream_skip(demuxer->stream, 12); | |
137 break; | |
138 | |
139 case CHUNK_STAB: | |
140 printf ("parsing STAB chunk\n"); | |
141 // skip unknown dword | |
142 stream_skip(demuxer->stream, 4); | |
143 | |
144 // fetch the number of frames | |
145 frames->num_frames = stream_read_dword(demuxer->stream); | |
146 frames->current_frame = 1; | |
147 // frames->current_frame = 0; | |
148 | |
149 // allocate enough entries for the indices | |
150 frames->filepos = (off_t *)malloc(frames->num_frames * sizeof(off_t)); | |
151 frames->frame_size = (int *)malloc(frames->num_frames * sizeof(int)); | |
152 frames->flags1 = (int *)malloc(frames->num_frames * sizeof(int)); | |
153 frames->flags2 = (int *)malloc(frames->num_frames * sizeof(int)); | |
154 | |
155 // build the frame index | |
156 for (i = 0; i < frames->num_frames; i++) | |
157 { | |
158 frames->filepos[i] = demuxer->movi_start + stream_read_dword(demuxer->stream); | |
159 frames->frame_size[i] = stream_read_dword(demuxer->stream); | |
160 frames->flags1[i] = stream_read_dword(demuxer->stream); | |
161 frames->flags2[i] = stream_read_dword(demuxer->stream); | |
162 } | |
163 break; | |
164 | |
165 default: | |
166 mp_msg(MSGT_DEMUX, MSGL_ERR, "Unrecognized FILM header chunk: %08X\n", | |
167 chunk_type); | |
168 return(NULL); | |
169 break; | |
170 } | |
171 } | |
172 | |
173 // hard code the speed for now | |
174 sh_video->fps = 1; | |
175 sh_video->frametime = 1; | |
176 | |
177 demuxer->priv = frames; | |
178 | |
179 return demuxer; | |
180 } |