Mercurial > mplayer.hg
annotate libmpdemux/demux_roq.c @ 28511:db19e31a2c7c
Add a calc_src_dst_rects that calculates from window size, panscan etc.
which part of the video source must be scaled onto which part of the window.
Direct3D and (future) VDPAU need this, for XvMC it makes it easier to add
cropping support and Xv is changed to keep the diff to XvMC small.
author | reimar |
---|---|
date | Thu, 12 Feb 2009 17:40:53 +0000 |
parents | 4d56038ec730 |
children | d643e4643313 |
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 | |
22605
4d81dbdf46b9
Add explicit location for headers from the stream/ directory.
diego
parents:
19062
diff
changeset
|
16 #include "stream/stream.h" |
4451 | 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 |
16175 | 51 static int roq_check_file(demuxer_t *demuxer) |
4451 | 52 { |
53 if ((stream_read_dword(demuxer->stream) == 0x8410FFFF) && | |
4753
f3562b5411f9
fixed RoQ file detection and FPS determination (maybe)
melanson
parents:
4532
diff
changeset
|
54 ((stream_read_dword(demuxer->stream) & 0xFFFF0000) == 0xFFFF0000)) |
16175 | 55 return DEMUXER_TYPE_ROQ; |
4451 | 56 else |
57 return 0; | |
58 } | |
59 | |
60 // return value: | |
61 // 0 = EOF or no stream found | |
62 // 1 = successfully read a packet | |
16175 | 63 static int demux_roq_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds) |
4451 | 64 { |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
65 sh_video_t *sh_video = demuxer->video->sh; |
4451 | 66 roq_data_t *roq_data = (roq_data_t *)demuxer->priv; |
67 roq_chunk_t roq_chunk; | |
68 | |
69 if (roq_data->current_chunk >= roq_data->total_chunks) | |
70 return 0; | |
71 | |
72 roq_chunk = roq_data->chunks[roq_data->current_chunk]; | |
73 | |
74 // make sure we're at the right place in the stream and fetch the chunk | |
75 stream_seek(demuxer->stream, roq_chunk.chunk_offset); | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
76 |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
77 if (roq_chunk.chunk_type == CHUNK_TYPE_AUDIO) |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
78 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
|
79 0, |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
80 roq_chunk.chunk_offset, 0); |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
81 else |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
82 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
|
83 roq_chunk.video_chunk_number / sh_video->fps, |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
84 roq_chunk.chunk_offset, 0); |
4451 | 85 |
86 roq_data->current_chunk++; | |
87 return 1; | |
88 } | |
89 | |
16175 | 90 static demuxer_t* demux_open_roq(demuxer_t* demuxer) |
4451 | 91 { |
92 sh_video_t *sh_video = NULL; | |
93 sh_audio_t *sh_audio = NULL; | |
94 | |
19062
83c3afeab35d
drops casts from void * on malloc/calloc from libmpdemux code
reynaldo
parents:
16175
diff
changeset
|
95 roq_data_t *roq_data = malloc(sizeof(roq_data_t)); |
4451 | 96 int chunk_id; |
97 int chunk_size; | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
98 int chunk_arg; |
4451 | 99 int last_chunk_id = 0; |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
100 int largest_audio_chunk = 0; |
4753
f3562b5411f9
fixed RoQ file detection and FPS determination (maybe)
melanson
parents:
4532
diff
changeset
|
101 int fps; |
4451 | 102 |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
103 roq_data->total_chunks = 0; |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
104 roq_data->current_chunk = 0; |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
105 roq_data->total_video_chunks = 0; |
4451 | 106 roq_data->chunks = NULL; |
107 | |
108 // position the stream and start traversing | |
4753
f3562b5411f9
fixed RoQ file detection and FPS determination (maybe)
melanson
parents:
4532
diff
changeset
|
109 stream_seek(demuxer->stream, 6); |
f3562b5411f9
fixed RoQ file detection and FPS determination (maybe)
melanson
parents:
4532
diff
changeset
|
110 fps = stream_read_word_le(demuxer->stream); |
4451 | 111 while (!stream_eof(demuxer->stream)) |
112 { | |
113 chunk_id = stream_read_word_le(demuxer->stream); | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
114 chunk_size = stream_read_dword_le(demuxer->stream); |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
115 chunk_arg = stream_read_word_le(demuxer->stream); |
4451 | 116 |
117 // this is the only useful header info in the file | |
118 if (chunk_id == RoQ_INFO) | |
119 { | |
120 // there should only be one RoQ_INFO chunk per file | |
121 if (sh_video) | |
122 { | |
123 mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Found more than one RoQ_INFO chunk\n"); | |
124 stream_skip(demuxer->stream, 8); | |
125 } | |
126 else | |
127 { | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
128 // this is a good opportunity to create a video stream header |
4451 | 129 sh_video = new_sh_video(demuxer, 0); |
130 // make sure the demuxer knows about the new stream header | |
131 demuxer->video->sh = sh_video; | |
132 // make sure that the video demuxer stream header knows about its | |
133 // parent video demuxer stream | |
134 sh_video->ds = demuxer->video; | |
135 | |
136 sh_video->disp_w = stream_read_word_le(demuxer->stream); | |
137 sh_video->disp_h = stream_read_word_le(demuxer->stream); | |
138 stream_skip(demuxer->stream, 4); | |
139 | |
140 // custom fourcc for internal MPlayer use | |
141 sh_video->format = mmioFOURCC('R', 'o', 'Q', 'V'); | |
142 | |
143 // constant frame rate | |
5424
e6d180ceb1ef
changed int -> float for proper PTS calculation (works just as well as the
melanson
parents:
5421
diff
changeset
|
144 sh_video->fps = fps; |
4532
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
145 sh_video->frametime = 1 / sh_video->fps; |
4451 | 146 } |
147 } | |
148 else if ((chunk_id == RoQ_SOUND_MONO) || | |
149 (chunk_id == RoQ_SOUND_STEREO)) | |
150 { | |
151 // create the audio stream header if it hasn't been created it | |
152 if (sh_audio == NULL) | |
153 { | |
154 // make the header first | |
155 sh_audio = new_sh_audio(demuxer, 0); | |
156 // 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
|
157 demuxer->audio->id = 0; |
4451 | 158 demuxer->audio->sh = sh_audio; |
159 // make sure that the audio demuxer stream header knows about its | |
160 // parent audio demuxer stream | |
161 sh_audio->ds = demuxer->audio; | |
162 | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
163 // go through the bother of making a WAVEFORMATEX structure |
19062
83c3afeab35d
drops casts from void * on malloc/calloc from libmpdemux code
reynaldo
parents:
16175
diff
changeset
|
164 sh_audio->wf = malloc(sizeof(WAVEFORMATEX)); |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
165 |
4451 | 166 // custom fourcc for internal MPlayer use |
167 sh_audio->format = mmioFOURCC('R', 'o', 'Q', 'A'); | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
168 if (chunk_id == RoQ_SOUND_STEREO) |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
169 sh_audio->wf->nChannels = 2; |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
170 else |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
171 sh_audio->wf->nChannels = 1; |
4451 | 172 // always 22KHz, 16-bit |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
173 sh_audio->wf->nSamplesPerSec = 22050; |
5421
d1ff2c2f74f0
fixed RoQ framerate by multiplying PTS calculation by some absurd constant
melanson
parents:
4753
diff
changeset
|
174 sh_audio->wf->wBitsPerSample = 16; |
4451 | 175 } |
176 | |
177 // index the chunk | |
178 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
|
179 (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
|
180 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
|
181 roq_data->chunks[roq_data->total_chunks].chunk_offset = |
4451 | 182 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
|
183 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
|
184 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
|
185 roq_data->total_audio_sample_count; |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
186 |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
187 // audio housekeeping |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
188 if (chunk_size > largest_audio_chunk) |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
189 largest_audio_chunk = chunk_size; |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
190 roq_data->total_audio_sample_count += |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
191 (chunk_size / sh_audio->wf->nChannels); |
4451 | 192 |
193 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
|
194 roq_data->total_chunks++; |
4451 | 195 } |
196 else if ((chunk_id == RoQ_QUAD_CODEBOOK) || | |
197 ((chunk_id == RoQ_QUAD_VQ) && (last_chunk_id != RoQ_QUAD_CODEBOOK))) | |
198 { | |
199 // index a new chunk if it's a codebook or quad VQ not following a | |
200 // codebook | |
201 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
|
202 (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
|
203 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
|
204 roq_data->chunks[roq_data->total_chunks].chunk_offset = |
4451 | 205 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
|
206 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
|
207 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
|
208 roq_data->total_video_chunks++; |
4451 | 209 |
210 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
|
211 roq_data->total_chunks++; |
4451 | 212 } |
213 else if ((chunk_id == RoQ_QUAD_VQ) && (last_chunk_id == RoQ_QUAD_CODEBOOK)) | |
214 { | |
215 // if it's a quad VQ chunk following a codebook chunk, extend the last | |
216 // chunk | |
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 - 1].chunk_size += (chunk_size + 8); |
4451 | 218 stream_skip(demuxer->stream, chunk_size); |
219 } | |
4532
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
220 else if (!stream_eof(demuxer->stream)) |
4451 | 221 { |
222 mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Unknown RoQ chunk ID: %04X\n", chunk_id); | |
223 } | |
224 | |
225 last_chunk_id = chunk_id; | |
226 } | |
227 | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
228 // 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
|
229 // 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
|
230 // (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
|
231 // step on it anyway) |
4532
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
232 if (sh_audio) |
f86c1915ca79
fixed FPS as well as crash bug when no audio chunks are present
melanson
parents:
4485
diff
changeset
|
233 sh_audio->wf->nBlockAlign = largest_audio_chunk * 2; |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
234 |
4451 | 235 roq_data->current_chunk = 0; |
236 | |
237 demuxer->priv = roq_data; | |
238 | |
4485
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
239 stream_reset(demuxer->stream); |
eaa4a2242552
demuxer is now more complete, though still not perfect
melanson
parents:
4451
diff
changeset
|
240 |
4451 | 241 return demuxer; |
242 } | |
5810 | 243 |
16175 | 244 static void demux_close_roq(demuxer_t* demuxer) { |
5810 | 245 roq_data_t *roq_data = demuxer->priv; |
246 | |
247 if(!roq_data) | |
248 return; | |
249 free(roq_data); | |
250 } | |
251 | |
16175 | 252 |
25707
d4fe6e23283e
Make all demuxer_desc_t const, thus moving them to .rodata
reimar
parents:
22605
diff
changeset
|
253 const demuxer_desc_t demuxer_desc_roq = { |
16175 | 254 "RoQ demuxer", |
255 "roq", | |
256 "ROQ", | |
257 "Mike Melanson", | |
258 "", | |
259 DEMUXER_TYPE_ROQ, | |
260 0, // unsafe autodetect | |
261 roq_check_file, | |
262 demux_roq_fill_buffer, | |
263 demux_open_roq, | |
264 demux_close_roq, | |
265 NULL, | |
266 NULL | |
267 }; |