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