Mercurial > mplayer.hg
annotate libmpdemux/demux_roq.c @ 33273:8c4a81b0bd5f
Update Doxyfile from doxygen 1.3.7 to 1.5.6.
The latter is the version available in Debian oldstable and should thus be a
suitable baseline that can be expected to be available on all systems.
The update makes new Doxygen features available in the configuration file
and avoids several deprecation warnings when using newer doxygen versions.
author | diego |
---|---|
date | Wed, 04 May 2011 14:27:35 +0000 |
parents | 8fa2f43cb760 |
children | 6ff73f13785c |
rev | line source |
---|---|
4451 | 1 /* |
29238
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
26299
diff
changeset
|
2 * RoQ file demuxer |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
26299
diff
changeset
|
3 * copyright (c) 2002 Mike Melanson |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
26299
diff
changeset
|
4 * based on Dr. Tim Ferguson's RoQ document found at: |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
26299
diff
changeset
|
5 * http://www.csse.monash.edu.au/~timf/videocodec.html |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
26299
diff
changeset
|
6 * |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
26299
diff
changeset
|
7 * This file is part of MPlayer. |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
26299
diff
changeset
|
8 * |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
26299
diff
changeset
|
9 * MPlayer is free software; you can redistribute it and/or modify |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
26299
diff
changeset
|
10 * it under the terms of the GNU General Public License as published by |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
26299
diff
changeset
|
11 * the Free Software Foundation; either version 2 of the License, or |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
26299
diff
changeset
|
12 * (at your option) any later version. |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
26299
diff
changeset
|
13 * |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
26299
diff
changeset
|
14 * MPlayer is distributed in the hope that it will be useful, |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
26299
diff
changeset
|
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
26299
diff
changeset
|
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
26299
diff
changeset
|
17 * GNU General Public License for more details. |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
26299
diff
changeset
|
18 * |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
26299
diff
changeset
|
19 * You should have received a copy of the GNU General Public License along |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
26299
diff
changeset
|
20 * with MPlayer; if not, write to the Free Software Foundation, Inc., |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
26299
diff
changeset
|
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
d643e4643313
Add standard license header to all files in libmpdemux.
diego
parents:
26299
diff
changeset
|
22 */ |
4451 | 23 |
24 #include <stdio.h> | |
25 #include <stdlib.h> | |
26 #include <unistd.h> | |
27 | |
28 #include "config.h" | |
29 #include "mp_msg.h" | |
30 #include "help_mp.h" | |
31 | |
22605
4d81dbdf46b9
Add explicit location for headers from the stream/ directory.
diego
parents:
19062
diff
changeset
|
32 #include "stream/stream.h" |
4451 | 33 #include "demuxer.h" |
34 #include "stheader.h" | |
35 | |
36 #define RoQ_INFO 0x1001 | |
37 #define RoQ_QUAD_CODEBOOK 0x1002 | |
38 #define RoQ_QUAD_VQ 0x1011 | |
39 #define RoQ_SOUND_MONO 0x1020 | |
40 #define RoQ_SOUND_STEREO 0x1021 | |
41 | |
42 #define CHUNK_TYPE_AUDIO 0 | |
43 #define CHUNK_TYPE_VIDEO 1 | |
44 | |
45 typedef struct roq_chunk_t | |
46 { | |
47 int chunk_type; | |
48 off_t chunk_offset; | |
49 int chunk_size; | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
50 |
5424
e6d180ceb1ef
changed int -> float for proper PTS calculation (works just as well as the
melanson
parents:
5421
diff
changeset
|
51 float video_chunk_number; // in the case of a video chunk |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
52 int running_audio_sample_count; // for an audio chunk |
4451 | 53 } roq_chunk_t; |
54 | |
55 typedef struct roq_data_t | |
56 { | |
57 int total_chunks; | |
58 int current_chunk; | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
59 int total_video_chunks; |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
60 int total_audio_sample_count; |
4451 | 61 roq_chunk_t *chunks; |
62 } roq_data_t; | |
63 | |
64 // Check if a stream qualifies as a RoQ file based on the magic numbers | |
65 // at the start of the file: | |
4753
f3562b5411f9
fixed RoQ file detection and FPS determination (maybe)
melanson
parents:
4532
diff
changeset
|
66 // 84 10 FF FF FF FF xx xx |
16175 | 67 static int roq_check_file(demuxer_t *demuxer) |
4451 | 68 { |
69 if ((stream_read_dword(demuxer->stream) == 0x8410FFFF) && | |
4753
f3562b5411f9
fixed RoQ file detection and FPS determination (maybe)
melanson
parents:
4532
diff
changeset
|
70 ((stream_read_dword(demuxer->stream) & 0xFFFF0000) == 0xFFFF0000)) |
16175 | 71 return DEMUXER_TYPE_ROQ; |
4451 | 72 else |
73 return 0; | |
74 } | |
75 | |
76 // return value: | |
77 // 0 = EOF or no stream found | |
78 // 1 = successfully read a packet | |
16175 | 79 static int demux_roq_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds) |
4451 | 80 { |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
81 sh_video_t *sh_video = demuxer->video->sh; |
4451 | 82 roq_data_t *roq_data = (roq_data_t *)demuxer->priv; |
83 roq_chunk_t roq_chunk; | |
84 | |
85 if (roq_data->current_chunk >= roq_data->total_chunks) | |
86 return 0; | |
87 | |
88 roq_chunk = roq_data->chunks[roq_data->current_chunk]; | |
89 | |
90 // make sure we're at the right place in the stream and fetch the chunk | |
91 stream_seek(demuxer->stream, roq_chunk.chunk_offset); | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
92 |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
93 if (roq_chunk.chunk_type == CHUNK_TYPE_AUDIO) |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
94 ds_read_packet(demuxer->audio, demuxer->stream, roq_chunk.chunk_size, |
5421
d1ff2c2f74f0
fixed RoQ framerate by multiplying PTS calculation by some absurd constant
melanson
parents:
4753
diff
changeset
|
95 0, |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
96 roq_chunk.chunk_offset, 0); |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
97 else |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
98 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
|
99 roq_chunk.video_chunk_number / sh_video->fps, |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
100 roq_chunk.chunk_offset, 0); |
4451 | 101 |
102 roq_data->current_chunk++; | |
103 return 1; | |
104 } | |
105 | |
16175 | 106 static demuxer_t* demux_open_roq(demuxer_t* demuxer) |
4451 | 107 { |
108 sh_video_t *sh_video = NULL; | |
109 sh_audio_t *sh_audio = NULL; | |
110 | |
19062
83c3afeab35d
drops casts from void * on malloc/calloc from libmpdemux code
reynaldo
parents:
16175
diff
changeset
|
111 roq_data_t *roq_data = malloc(sizeof(roq_data_t)); |
4451 | 112 int chunk_id; |
113 int chunk_size; | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
114 int chunk_arg; |
4451 | 115 int last_chunk_id = 0; |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
116 int largest_audio_chunk = 0; |
4753
f3562b5411f9
fixed RoQ file detection and FPS determination (maybe)
melanson
parents:
4532
diff
changeset
|
117 int fps; |
4451 | 118 |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
119 roq_data->total_chunks = 0; |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
120 roq_data->current_chunk = 0; |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
121 roq_data->total_video_chunks = 0; |
4451 | 122 roq_data->chunks = NULL; |
123 | |
124 // position the stream and start traversing | |
4753
f3562b5411f9
fixed RoQ file detection and FPS determination (maybe)
melanson
parents:
4532
diff
changeset
|
125 stream_seek(demuxer->stream, 6); |
f3562b5411f9
fixed RoQ file detection and FPS determination (maybe)
melanson
parents:
4532
diff
changeset
|
126 fps = stream_read_word_le(demuxer->stream); |
4451 | 127 while (!stream_eof(demuxer->stream)) |
128 { | |
129 chunk_id = stream_read_word_le(demuxer->stream); | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
130 chunk_size = stream_read_dword_le(demuxer->stream); |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
131 chunk_arg = stream_read_word_le(demuxer->stream); |
4451 | 132 |
133 // this is the only useful header info in the file | |
134 if (chunk_id == RoQ_INFO) | |
135 { | |
136 // there should only be one RoQ_INFO chunk per file | |
137 if (sh_video) | |
138 { | |
139 mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Found more than one RoQ_INFO chunk\n"); | |
140 stream_skip(demuxer->stream, 8); | |
141 } | |
142 else | |
143 { | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
144 // this is a good opportunity to create a video stream header |
4451 | 145 sh_video = new_sh_video(demuxer, 0); |
146 // make sure the demuxer knows about the new stream header | |
147 demuxer->video->sh = sh_video; | |
148 // make sure that the video demuxer stream header knows about its | |
149 // parent video demuxer stream | |
150 sh_video->ds = demuxer->video; | |
151 | |
152 sh_video->disp_w = stream_read_word_le(demuxer->stream); | |
153 sh_video->disp_h = stream_read_word_le(demuxer->stream); | |
154 stream_skip(demuxer->stream, 4); | |
155 | |
156 // custom fourcc for internal MPlayer use | |
157 sh_video->format = mmioFOURCC('R', 'o', 'Q', 'V'); | |
158 | |
159 // constant frame rate | |
5424
e6d180ceb1ef
changed int -> float for proper PTS calculation (works just as well as the
melanson
parents:
5421
diff
changeset
|
160 sh_video->fps = fps; |
4532
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
161 sh_video->frametime = 1 / sh_video->fps; |
4451 | 162 } |
163 } | |
164 else if ((chunk_id == RoQ_SOUND_MONO) || | |
165 (chunk_id == RoQ_SOUND_STEREO)) | |
166 { | |
167 // create the audio stream header if it hasn't been created it | |
168 if (sh_audio == NULL) | |
169 { | |
170 // make the header first | |
31609
cd81fce1f010
Make the stream language an argument to the stream creation function
reimar
parents:
30702
diff
changeset
|
171 sh_audio = new_sh_audio(demuxer, 0, NULL); |
4451 | 172 // make sure the demuxer knows about the new stream header |
26299
4d56038ec730
Fix lots and lots of other demuxers broken by r26301
reimar
parents:
25707
diff
changeset
|
173 demuxer->audio->id = 0; |
4451 | 174 demuxer->audio->sh = sh_audio; |
175 // make sure that the audio demuxer stream header knows about its | |
176 // parent audio demuxer stream | |
177 sh_audio->ds = demuxer->audio; | |
178 | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
179 // go through the bother of making a WAVEFORMATEX structure |
32100 | 180 sh_audio->wf = malloc(sizeof(*sh_audio->wf)); |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
181 |
4451 | 182 // custom fourcc for internal MPlayer use |
183 sh_audio->format = mmioFOURCC('R', 'o', 'Q', 'A'); | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
184 if (chunk_id == RoQ_SOUND_STEREO) |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
185 sh_audio->wf->nChannels = 2; |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
186 else |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
187 sh_audio->wf->nChannels = 1; |
4451 | 188 // always 22KHz, 16-bit |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
189 sh_audio->wf->nSamplesPerSec = 22050; |
5421
d1ff2c2f74f0
fixed RoQ framerate by multiplying PTS calculation by some absurd constant
melanson
parents:
4753
diff
changeset
|
190 sh_audio->wf->wBitsPerSample = 16; |
4451 | 191 } |
192 | |
193 // index the chunk | |
30702 | 194 roq_data->chunks = realloc(roq_data->chunks, |
4532
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
195 (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
|
196 roq_data->chunks[roq_data->total_chunks].chunk_type = CHUNK_TYPE_AUDIO; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
197 roq_data->chunks[roq_data->total_chunks].chunk_offset = |
4451 | 198 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
|
199 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
|
200 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
|
201 roq_data->total_audio_sample_count; |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
202 |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
203 // audio housekeeping |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
204 if (chunk_size > largest_audio_chunk) |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
205 largest_audio_chunk = chunk_size; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
206 roq_data->total_audio_sample_count += |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
207 (chunk_size / sh_audio->wf->nChannels); |
4451 | 208 |
209 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
|
210 roq_data->total_chunks++; |
4451 | 211 } |
212 else if ((chunk_id == RoQ_QUAD_CODEBOOK) || | |
213 ((chunk_id == RoQ_QUAD_VQ) && (last_chunk_id != RoQ_QUAD_CODEBOOK))) | |
214 { | |
215 // index a new chunk if it's a codebook or quad VQ not following a | |
216 // codebook | |
30702 | 217 roq_data->chunks = realloc(roq_data->chunks, |
4532
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
218 (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
|
219 roq_data->chunks[roq_data->total_chunks].chunk_type = CHUNK_TYPE_VIDEO; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
220 roq_data->chunks[roq_data->total_chunks].chunk_offset = |
4451 | 221 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
|
222 roq_data->chunks[roq_data->total_chunks].chunk_size = chunk_size + 8; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
223 roq_data->chunks[roq_data->total_chunks].video_chunk_number = |
5424
e6d180ceb1ef
changed int -> float for proper PTS calculation (works just as well as the
melanson
parents:
5421
diff
changeset
|
224 roq_data->total_video_chunks++; |
4451 | 225 |
226 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
|
227 roq_data->total_chunks++; |
4451 | 228 } |
229 else if ((chunk_id == RoQ_QUAD_VQ) && (last_chunk_id == RoQ_QUAD_CODEBOOK)) | |
230 { | |
231 // if it's a quad VQ chunk following a codebook chunk, extend the last | |
232 // chunk | |
4532
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
233 roq_data->chunks[roq_data->total_chunks - 1].chunk_size += (chunk_size + 8); |
4451 | 234 stream_skip(demuxer->stream, chunk_size); |
235 } | |
4532
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
236 else if (!stream_eof(demuxer->stream)) |
4451 | 237 { |
238 mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Unknown RoQ chunk ID: %04X\n", chunk_id); | |
239 } | |
240 | |
241 last_chunk_id = chunk_id; | |
242 } | |
243 | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
244 // 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
|
245 // 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
|
246 // (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
|
247 // step on it anyway) |
4532
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
248 if (sh_audio) |
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
249 sh_audio->wf->nBlockAlign = largest_audio_chunk * 2; |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
250 |
4451 | 251 roq_data->current_chunk = 0; |
252 | |
253 demuxer->priv = roq_data; | |
254 | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
255 stream_reset(demuxer->stream); |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
256 |
4451 | 257 return demuxer; |
258 } | |
5810 | 259 |
16175 | 260 static void demux_close_roq(demuxer_t* demuxer) { |
5810 | 261 roq_data_t *roq_data = demuxer->priv; |
262 | |
263 free(roq_data); | |
264 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
265 |
16175 | 266 |
25707
d4fe6e23283e
Make all demuxer_desc_t const, thus moving them to .rodata
reimar
parents:
22605
diff
changeset
|
267 const demuxer_desc_t demuxer_desc_roq = { |
16175 | 268 "RoQ demuxer", |
269 "roq", | |
270 "ROQ", | |
271 "Mike Melanson", | |
272 "", | |
273 DEMUXER_TYPE_ROQ, | |
274 0, // unsafe autodetect | |
275 roq_check_file, | |
276 demux_roq_fill_buffer, | |
277 demux_open_roq, | |
278 demux_close_roq, | |
279 NULL, | |
280 NULL | |
281 }; |