Mercurial > mplayer.hg
annotate libmpdemux/demux_roq.c @ 7280:d77c243f0456
Added CDDA credits to Alban.
Added CDDB credits to Bertrand.
Why is my last name all upper case, and only for me?
Sorry for the cosmetic, but it looks wierd :/
author | bertrand |
---|---|
date | Thu, 05 Sep 2002 05:08:55 +0000 |
parents | 8a357300d0ec |
children | 1a26db279e50 |
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 |
5424
e6d180ceb1ef
changed int -> float for proper PTS calculation (works just as well as the
melanson
parents:
5421
diff
changeset
|
35 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
|
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, |
5421
d1ff2c2f74f0
fixed RoQ framerate by multiplying PTS calculation by some absurd constant
melanson
parents:
4753
diff
changeset
|
82 0, |
4485
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 | |
5424
e6d180ceb1ef
changed int -> float for proper PTS calculation (works just as well as the
melanson
parents:
5421
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; |
5421
d1ff2c2f74f0
fixed RoQ framerate by multiplying PTS calculation by some absurd constant
melanson
parents:
4753
diff
changeset
|
176 sh_audio->wf->wBitsPerSample = 16; |
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 = |
5424
e6d180ceb1ef
changed int -> float for proper PTS calculation (works just as well as the
melanson
parents:
5421
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 } | |
5810 | 245 |
246 void demux_close_roq(demuxer_t* demuxer) { | |
247 roq_data_t *roq_data = demuxer->priv; | |
248 | |
249 if(!roq_data) | |
250 return; | |
251 free(roq_data); | |
252 } | |
253 |