Mercurial > mplayer.hg
annotate libmpdemux/demux_roq.c @ 36607:6b17e4932555
Improve the dialog for font encodings.
In case iconv is available, add only available encodings from the
full list to avoid possible confusion.
In any case (and especially if iconv isn't available) add UNICODE,
since this is internally provided by MPlayer.
author | ib |
---|---|
date | Thu, 23 Jan 2014 12:09:37 +0000 |
parents | e789b4c9007b |
children | f3c835ddce85 |
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 | |
36569 | 111 roq_data_t *roq_data = calloc(1, sizeof(*roq_data)); |
4451 | 112 int last_chunk_id = 0; |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
113 int largest_audio_chunk = 0; |
4753
f3562b5411f9
fixed RoQ file detection and FPS determination (maybe)
melanson
parents:
4532
diff
changeset
|
114 int fps; |
4451 | 115 |
116 // position the stream and start traversing | |
4753
f3562b5411f9
fixed RoQ file detection and FPS determination (maybe)
melanson
parents:
4532
diff
changeset
|
117 stream_seek(demuxer->stream, 6); |
f3562b5411f9
fixed RoQ file detection and FPS determination (maybe)
melanson
parents:
4532
diff
changeset
|
118 fps = stream_read_word_le(demuxer->stream); |
4451 | 119 while (!stream_eof(demuxer->stream)) |
120 { | |
36570 | 121 int chunk_id = stream_read_word_le(demuxer->stream); |
122 int chunk_size = stream_read_dword_le(demuxer->stream); | |
123 int chunk_arg = stream_read_word_le(demuxer->stream); | |
4451 | 124 |
125 // this is the only useful header info in the file | |
126 if (chunk_id == RoQ_INFO) | |
127 { | |
128 // there should only be one RoQ_INFO chunk per file | |
129 if (sh_video) | |
130 { | |
131 mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Found more than one RoQ_INFO chunk\n"); | |
132 stream_skip(demuxer->stream, 8); | |
133 } | |
134 else | |
135 { | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
136 // this is a good opportunity to create a video stream header |
4451 | 137 sh_video = new_sh_video(demuxer, 0); |
138 // make sure the demuxer knows about the new stream header | |
139 demuxer->video->sh = sh_video; | |
140 // make sure that the video demuxer stream header knows about its | |
141 // parent video demuxer stream | |
142 sh_video->ds = demuxer->video; | |
143 | |
144 sh_video->disp_w = stream_read_word_le(demuxer->stream); | |
145 sh_video->disp_h = stream_read_word_le(demuxer->stream); | |
146 stream_skip(demuxer->stream, 4); | |
147 | |
148 // custom fourcc for internal MPlayer use | |
149 sh_video->format = mmioFOURCC('R', 'o', 'Q', 'V'); | |
150 | |
151 // constant frame rate | |
5424
e6d180ceb1ef
changed int -> float for proper PTS calculation (works just as well as the
melanson
parents:
5421
diff
changeset
|
152 sh_video->fps = fps; |
4532
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
153 sh_video->frametime = 1 / sh_video->fps; |
4451 | 154 } |
155 } | |
156 else if ((chunk_id == RoQ_SOUND_MONO) || | |
157 (chunk_id == RoQ_SOUND_STEREO)) | |
158 { | |
159 // create the audio stream header if it hasn't been created it | |
160 if (sh_audio == NULL) | |
161 { | |
162 // make the header first | |
31609
cd81fce1f010
Make the stream language an argument to the stream creation function
reimar
parents:
30702
diff
changeset
|
163 sh_audio = new_sh_audio(demuxer, 0, NULL); |
4451 | 164 // 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
|
165 demuxer->audio->id = 0; |
4451 | 166 demuxer->audio->sh = sh_audio; |
167 // make sure that the audio demuxer stream header knows about its | |
168 // parent audio demuxer stream | |
169 sh_audio->ds = demuxer->audio; | |
170 | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
171 // go through the bother of making a WAVEFORMATEX structure |
32100 | 172 sh_audio->wf = malloc(sizeof(*sh_audio->wf)); |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
173 |
4451 | 174 // custom fourcc for internal MPlayer use |
175 sh_audio->format = mmioFOURCC('R', 'o', 'Q', 'A'); | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
176 if (chunk_id == RoQ_SOUND_STEREO) |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
177 sh_audio->wf->nChannels = 2; |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
178 else |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
179 sh_audio->wf->nChannels = 1; |
4451 | 180 // always 22KHz, 16-bit |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
181 sh_audio->wf->nSamplesPerSec = 22050; |
5421
d1ff2c2f74f0
fixed RoQ framerate by multiplying PTS calculation by some absurd constant
melanson
parents:
4753
diff
changeset
|
182 sh_audio->wf->wBitsPerSample = 16; |
4451 | 183 } |
184 | |
185 // index the chunk | |
30702 | 186 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
|
187 (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
|
188 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
|
189 roq_data->chunks[roq_data->total_chunks].chunk_offset = |
4451 | 190 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
|
191 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
|
192 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
|
193 roq_data->total_audio_sample_count; |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
194 |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
195 // audio housekeeping |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
196 if (chunk_size > largest_audio_chunk) |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
197 largest_audio_chunk = chunk_size; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
198 roq_data->total_audio_sample_count += |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
199 (chunk_size / sh_audio->wf->nChannels); |
4451 | 200 |
201 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
|
202 roq_data->total_chunks++; |
4451 | 203 } |
204 else if ((chunk_id == RoQ_QUAD_CODEBOOK) || | |
205 ((chunk_id == RoQ_QUAD_VQ) && (last_chunk_id != RoQ_QUAD_CODEBOOK))) | |
206 { | |
207 // index a new chunk if it's a codebook or quad VQ not following a | |
208 // codebook | |
30702 | 209 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
|
210 (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
|
211 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
|
212 roq_data->chunks[roq_data->total_chunks].chunk_offset = |
4451 | 213 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
|
214 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
|
215 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
|
216 roq_data->total_video_chunks++; |
4451 | 217 |
218 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
|
219 roq_data->total_chunks++; |
4451 | 220 } |
221 else if ((chunk_id == RoQ_QUAD_VQ) && (last_chunk_id == RoQ_QUAD_CODEBOOK)) | |
222 { | |
223 // if it's a quad VQ chunk following a codebook chunk, extend the last | |
224 // chunk | |
4532
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
225 roq_data->chunks[roq_data->total_chunks - 1].chunk_size += (chunk_size + 8); |
4451 | 226 stream_skip(demuxer->stream, chunk_size); |
227 } | |
4532
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
228 else if (!stream_eof(demuxer->stream)) |
4451 | 229 { |
230 mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Unknown RoQ chunk ID: %04X\n", chunk_id); | |
231 } | |
232 | |
233 last_chunk_id = chunk_id; | |
234 } | |
235 | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
236 // 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
|
237 // 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
|
238 // (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
|
239 // step on it anyway) |
4532
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
240 if (sh_audio) |
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
241 sh_audio->wf->nBlockAlign = largest_audio_chunk * 2; |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
242 |
4451 | 243 roq_data->current_chunk = 0; |
244 | |
245 demuxer->priv = roq_data; | |
246 | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
247 stream_reset(demuxer->stream); |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
248 |
4451 | 249 return demuxer; |
250 } | |
5810 | 251 |
16175 | 252 static void demux_close_roq(demuxer_t* demuxer) { |
5810 | 253 roq_data_t *roq_data = demuxer->priv; |
254 | |
255 free(roq_data); | |
256 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29238
diff
changeset
|
257 |
16175 | 258 |
25707
d4fe6e23283e
Make all demuxer_desc_t const, thus moving them to .rodata
reimar
parents:
22605
diff
changeset
|
259 const demuxer_desc_t demuxer_desc_roq = { |
16175 | 260 "RoQ demuxer", |
261 "roq", | |
262 "ROQ", | |
263 "Mike Melanson", | |
264 "", | |
265 DEMUXER_TYPE_ROQ, | |
266 0, // unsafe autodetect | |
267 roq_check_file, | |
268 demux_roq_fill_buffer, | |
269 demux_open_roq, | |
270 demux_close_roq, | |
271 NULL, | |
272 NULL | |
273 }; |