Mercurial > mplayer.hg
annotate libmpdemux/demux_roq.c @ 4965:923605707de6
sorry, 10l:)
author | pontscho |
---|---|
date | Thu, 07 Mar 2002 00:03:51 +0000 |
parents | f3562b5411f9 |
children | d1ff2c2f74f0 |
rev | line source |
---|---|
4451 | 1 /* |
2 RoQ file demuxer for the MPlayer program | |
3 by Mike Melanson | |
4 based on Dr. Tim Ferguson's RoQ document found at: | |
5 http://www.csse.monash.edu.au/~timf/videocodec.html | |
6 */ | |
7 | |
8 #include <stdio.h> | |
9 #include <stdlib.h> | |
10 #include <unistd.h> | |
11 | |
12 #include "config.h" | |
13 #include "mp_msg.h" | |
14 #include "help_mp.h" | |
15 | |
16 #include "stream.h" | |
17 #include "demuxer.h" | |
18 #include "stheader.h" | |
19 | |
20 #define RoQ_INFO 0x1001 | |
21 #define RoQ_QUAD_CODEBOOK 0x1002 | |
22 #define RoQ_QUAD_VQ 0x1011 | |
23 #define RoQ_SOUND_MONO 0x1020 | |
24 #define RoQ_SOUND_STEREO 0x1021 | |
25 | |
26 #define CHUNK_TYPE_AUDIO 0 | |
27 #define CHUNK_TYPE_VIDEO 1 | |
28 | |
29 typedef struct roq_chunk_t | |
30 { | |
31 int chunk_type; | |
32 off_t chunk_offset; | |
33 int chunk_size; | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
34 |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
35 int video_chunk_number; // in the case of a video chunk |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
36 int running_audio_sample_count; // for an audio chunk |
4451 | 37 } roq_chunk_t; |
38 | |
39 typedef struct roq_data_t | |
40 { | |
41 int total_chunks; | |
42 int current_chunk; | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
43 int total_video_chunks; |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
44 int total_audio_sample_count; |
4451 | 45 roq_chunk_t *chunks; |
46 } roq_data_t; | |
47 | |
48 // Check if a stream qualifies as a RoQ file based on the magic numbers | |
49 // at the start of the file: | |
4753
f3562b5411f9
fixed RoQ file detection and FPS determination (maybe)
melanson
parents:
4532
diff
changeset
|
50 // 84 10 FF FF FF FF xx xx |
4451 | 51 int roq_check_file(demuxer_t *demuxer) |
52 { | |
53 stream_reset(demuxer->stream); | |
54 stream_seek(demuxer->stream, 0); | |
55 | |
56 if ((stream_read_dword(demuxer->stream) == 0x8410FFFF) && | |
4753
f3562b5411f9
fixed RoQ file detection and FPS determination (maybe)
melanson
parents:
4532
diff
changeset
|
57 ((stream_read_dword(demuxer->stream) & 0xFFFF0000) == 0xFFFF0000)) |
4451 | 58 return 1; |
59 else | |
60 return 0; | |
61 } | |
62 | |
63 // return value: | |
64 // 0 = EOF or no stream found | |
65 // 1 = successfully read a packet | |
66 int demux_roq_fill_buffer(demuxer_t *demuxer) | |
67 { | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
68 sh_video_t *sh_video = demuxer->video->sh; |
4451 | 69 roq_data_t *roq_data = (roq_data_t *)demuxer->priv; |
70 roq_chunk_t roq_chunk; | |
71 | |
72 if (roq_data->current_chunk >= roq_data->total_chunks) | |
73 return 0; | |
74 | |
75 roq_chunk = roq_data->chunks[roq_data->current_chunk]; | |
76 | |
77 // make sure we're at the right place in the stream and fetch the chunk | |
78 stream_seek(demuxer->stream, roq_chunk.chunk_offset); | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
79 |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
80 if (roq_chunk.chunk_type == CHUNK_TYPE_AUDIO) |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
81 ds_read_packet(demuxer->audio, demuxer->stream, roq_chunk.chunk_size, |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
82 roq_chunk.running_audio_sample_count / 22050, |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
83 roq_chunk.chunk_offset, 0); |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
84 else |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
85 ds_read_packet(demuxer->video, demuxer->stream, roq_chunk.chunk_size, |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
86 roq_chunk.video_chunk_number / sh_video->fps, |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
87 roq_chunk.chunk_offset, 0); |
4451 | 88 |
89 roq_data->current_chunk++; | |
90 return 1; | |
91 } | |
92 | |
93 demuxer_t* demux_open_roq(demuxer_t* demuxer) | |
94 { | |
95 sh_video_t *sh_video = NULL; | |
96 sh_audio_t *sh_audio = NULL; | |
97 | |
98 roq_data_t *roq_data = (roq_data_t *)malloc(sizeof(roq_data_t)); | |
99 int chunk_id; | |
100 int chunk_size; | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
101 int chunk_arg; |
4451 | 102 int last_chunk_id = 0; |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
103 int largest_audio_chunk = 0; |
4753
f3562b5411f9
fixed RoQ file detection and FPS determination (maybe)
melanson
parents:
4532
diff
changeset
|
104 int fps; |
4451 | 105 |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
106 roq_data->total_chunks = 0; |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
107 roq_data->current_chunk = 0; |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
108 roq_data->total_video_chunks = 0; |
4451 | 109 roq_data->chunks = NULL; |
110 | |
111 // position the stream and start traversing | |
4753
f3562b5411f9
fixed RoQ file detection and FPS determination (maybe)
melanson
parents:
4532
diff
changeset
|
112 stream_seek(demuxer->stream, 6); |
f3562b5411f9
fixed RoQ file detection and FPS determination (maybe)
melanson
parents:
4532
diff
changeset
|
113 fps = stream_read_word_le(demuxer->stream); |
4451 | 114 while (!stream_eof(demuxer->stream)) |
115 { | |
116 chunk_id = stream_read_word_le(demuxer->stream); | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
117 chunk_size = stream_read_dword_le(demuxer->stream); |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
118 chunk_arg = stream_read_word_le(demuxer->stream); |
4451 | 119 |
120 // this is the only useful header info in the file | |
121 if (chunk_id == RoQ_INFO) | |
122 { | |
123 // there should only be one RoQ_INFO chunk per file | |
124 if (sh_video) | |
125 { | |
126 mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Found more than one RoQ_INFO chunk\n"); | |
127 stream_skip(demuxer->stream, 8); | |
128 } | |
129 else | |
130 { | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
131 // this is a good opportunity to create a video stream header |
4451 | 132 sh_video = new_sh_video(demuxer, 0); |
133 // make sure the demuxer knows about the new stream header | |
134 demuxer->video->sh = sh_video; | |
135 // make sure that the video demuxer stream header knows about its | |
136 // parent video demuxer stream | |
137 sh_video->ds = demuxer->video; | |
138 | |
139 sh_video->disp_w = stream_read_word_le(demuxer->stream); | |
140 sh_video->disp_h = stream_read_word_le(demuxer->stream); | |
141 stream_skip(demuxer->stream, 4); | |
142 | |
143 // custom fourcc for internal MPlayer use | |
144 sh_video->format = mmioFOURCC('R', 'o', 'Q', 'V'); | |
145 | |
146 // constant frame rate | |
4753
f3562b5411f9
fixed RoQ file detection and FPS determination (maybe)
melanson
parents:
4532
diff
changeset
|
147 sh_video->fps = fps; |
4532
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
148 sh_video->frametime = 1 / sh_video->fps; |
4451 | 149 } |
150 } | |
151 else if ((chunk_id == RoQ_SOUND_MONO) || | |
152 (chunk_id == RoQ_SOUND_STEREO)) | |
153 { | |
154 // create the audio stream header if it hasn't been created it | |
155 if (sh_audio == NULL) | |
156 { | |
157 // make the header first | |
158 sh_audio = new_sh_audio(demuxer, 0); | |
159 // make sure the demuxer knows about the new stream header | |
160 demuxer->audio->sh = sh_audio; | |
161 // make sure that the audio demuxer stream header knows about its | |
162 // parent audio demuxer stream | |
163 sh_audio->ds = demuxer->audio; | |
164 | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
165 // go through the bother of making a WAVEFORMATEX structure |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
166 sh_audio->wf = (WAVEFORMATEX *)malloc(sizeof(WAVEFORMATEX)); |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
167 |
4451 | 168 // custom fourcc for internal MPlayer use |
169 sh_audio->format = mmioFOURCC('R', 'o', 'Q', 'A'); | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
170 if (chunk_id == RoQ_SOUND_STEREO) |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
171 sh_audio->wf->nChannels = 2; |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
172 else |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
173 sh_audio->wf->nChannels = 1; |
4451 | 174 // always 22KHz, 16-bit |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
175 sh_audio->wf->nSamplesPerSec = 22050; |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
176 sh_audio->wf->wBitsPerSample = 2; |
4451 | 177 } |
178 | |
179 // index the chunk | |
180 roq_data->chunks = (roq_chunk_t *)realloc(roq_data->chunks, | |
4532
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
181 (roq_data->total_chunks + 1) * sizeof (roq_chunk_t)); |
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
182 roq_data->chunks[roq_data->total_chunks].chunk_type = CHUNK_TYPE_AUDIO; |
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
183 roq_data->chunks[roq_data->total_chunks].chunk_offset = |
4451 | 184 stream_tell(demuxer->stream) - 8; |
4532
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
185 roq_data->chunks[roq_data->total_chunks].chunk_size = chunk_size + 8; |
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
186 roq_data->chunks[roq_data->total_chunks].running_audio_sample_count = |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
187 roq_data->total_audio_sample_count; |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
188 |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
189 // audio housekeeping |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
190 if (chunk_size > largest_audio_chunk) |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
191 largest_audio_chunk = chunk_size; |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
192 roq_data->total_audio_sample_count += |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
193 (chunk_size / sh_audio->wf->nChannels); |
4451 | 194 |
195 stream_skip(demuxer->stream, chunk_size); | |
4532
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
196 roq_data->total_chunks++; |
4451 | 197 } |
198 else if ((chunk_id == RoQ_QUAD_CODEBOOK) || | |
199 ((chunk_id == RoQ_QUAD_VQ) && (last_chunk_id != RoQ_QUAD_CODEBOOK))) | |
200 { | |
201 // index a new chunk if it's a codebook or quad VQ not following a | |
202 // codebook | |
203 roq_data->chunks = (roq_chunk_t *)realloc(roq_data->chunks, | |
4532
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
204 (roq_data->total_chunks + 1) * sizeof (roq_chunk_t)); |
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
205 roq_data->chunks[roq_data->total_chunks].chunk_type = CHUNK_TYPE_VIDEO; |
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
206 roq_data->chunks[roq_data->total_chunks].chunk_offset = |
4451 | 207 stream_tell(demuxer->stream) - 8; |
4532
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
208 roq_data->chunks[roq_data->total_chunks].chunk_size = chunk_size + 8; |
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
209 roq_data->chunks[roq_data->total_chunks].video_chunk_number = |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
210 roq_data->total_video_chunks++; |
4451 | 211 |
212 stream_skip(demuxer->stream, chunk_size); | |
4532
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
213 roq_data->total_chunks++; |
4451 | 214 } |
215 else if ((chunk_id == RoQ_QUAD_VQ) && (last_chunk_id == RoQ_QUAD_CODEBOOK)) | |
216 { | |
217 // if it's a quad VQ chunk following a codebook chunk, extend the last | |
218 // chunk | |
4532
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
219 roq_data->chunks[roq_data->total_chunks - 1].chunk_size += (chunk_size + 8); |
4451 | 220 stream_skip(demuxer->stream, chunk_size); |
221 } | |
4532
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
222 else if (!stream_eof(demuxer->stream)) |
4451 | 223 { |
224 mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Unknown RoQ chunk ID: %04X\n", chunk_id); | |
225 } | |
226 | |
227 last_chunk_id = chunk_id; | |
228 } | |
229 | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
230 // minimum output buffer size = largest audio chunk * 2, since each byte |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
231 // in the DPCM encoding effectively represents 1 16-bit sample |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
232 // (store it in wf->nBlockAlign for the time being since init_audio() will |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
233 // step on it anyway) |
4532
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
234 if (sh_audio) |
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
235 sh_audio->wf->nBlockAlign = largest_audio_chunk * 2; |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
236 |
4451 | 237 roq_data->current_chunk = 0; |
238 | |
239 demuxer->priv = roq_data; | |
240 | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
241 stream_reset(demuxer->stream); |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
242 |
4451 | 243 return demuxer; |
244 } |