Mercurial > mplayer.hg
annotate libmpdemux/demux_realaud.c @ 26730:41794a5fb100
Add a new suboption to -vo xv and -vo xvmc that allows selection
of XVideo adaptor to be used (instead of default one, which is #0).
This is useful for example if you'd rather like to use the original
Overlay renderer of your GPU instead of the texture blitting engine
(which is usually default), which is number one cause of nasty
video tearing effects.
author | ben |
---|---|
date | Tue, 13 May 2008 17:52:25 +0000 |
parents | d4fe6e23283e |
children | 9e739bdb049c |
rev | line source |
---|---|
10034 | 1 /* |
2 Realaudio demuxer for MPlayer | |
14908 | 3 (c) 2003, 2005 Roberto Togni |
10034 | 4 */ |
5 | |
6 #include <stdio.h> | |
7 #include <stdlib.h> | |
8 #include <unistd.h> | |
9 | |
10 #include "config.h" | |
11 #include "mp_msg.h" | |
12 #include "help_mp.h" | |
13 | |
22605
4d81dbdf46b9
Add explicit location for headers from the stream/ directory.
diego
parents:
21987
diff
changeset
|
14 #include "stream/stream.h" |
10034 | 15 #include "demuxer.h" |
16 #include "stheader.h" | |
17 | |
18 | |
19 #define FOURCC_DOTRA mmioFOURCC('.','r','a', 0xfd) | |
20 #define FOURCC_144 mmioFOURCC('1','4','_','4') | |
21 #define FOURCC_288 mmioFOURCC('2','8','_','8') | |
22 #define FOURCC_DNET mmioFOURCC('d','n','e','t') | |
23 #define FOURCC_LPCJ mmioFOURCC('l','p','c','J') | |
17400 | 24 #define FOURCC_SIPR mmioFOURCC('s','i','p','r') |
21987
fed73db9ddb1
Use interleaver id to select the correct interleaver instead of guessing
rtogni
parents:
21421
diff
changeset
|
25 #define INTLID_INT4 mmioFOURCC('I','n','t','4') |
fed73db9ddb1
Use interleaver id to select the correct interleaver instead of guessing
rtogni
parents:
21421
diff
changeset
|
26 #define INTLID_SIPR mmioFOURCC('s','i','p','r') |
17400 | 27 |
28 | |
29 static unsigned char sipr_swaps[38][2]={ | |
30 {0,63},{1,22},{2,44},{3,90},{5,81},{7,31},{8,86},{9,58},{10,36},{12,68}, | |
31 {13,39},{14,73},{15,53},{16,69},{17,57},{19,88},{20,34},{21,71},{24,46}, | |
32 {25,94},{26,54},{28,75},{29,50},{32,70},{33,92},{35,74},{38,85},{40,56}, | |
33 {42,87},{43,65},{45,59},{48,79},{49,93},{51,89},{55,95},{61,76},{67,83}, | |
34 {77,80} }; | |
35 | |
36 // Map flavour to bytes per second | |
37 static int sipr_fl2bps[4] = {813, 1062, 625, 2000}; // 6.5, 8.5, 5, 16 kbit per second | |
10034 | 38 |
39 | |
40 typedef struct { | |
41 unsigned short version; | |
42 unsigned int dotranum; | |
43 unsigned int data_size; | |
44 unsigned short version2; | |
45 unsigned int hdr_size; | |
46 unsigned short codec_flavor; | |
47 unsigned int coded_framesize; | |
48 unsigned short sub_packet_h; | |
49 unsigned short frame_size; | |
50 unsigned short sub_packet_size; | |
21987
fed73db9ddb1
Use interleaver id to select the correct interleaver instead of guessing
rtogni
parents:
21421
diff
changeset
|
51 unsigned intl_id; |
17400 | 52 unsigned char *audio_buf; |
10034 | 53 } ra_priv_t; |
54 | |
55 | |
56 | |
16175 | 57 static int ra_check_file(demuxer_t* demuxer) |
10034 | 58 { |
59 unsigned int chunk_id; | |
60 | |
61 chunk_id = stream_read_dword_le(demuxer->stream); | |
62 if (chunk_id == FOURCC_DOTRA) | |
16175 | 63 return DEMUXER_TYPE_REALAUDIO; |
10034 | 64 else |
65 return 0; | |
66 } | |
67 | |
68 | |
69 | |
70 // return value: | |
71 // 0 = EOF or no stream found | |
72 // 1 = successfully read a packet | |
16175 | 73 static int demux_ra_fill_buffer(demuxer_t *demuxer, demux_stream_t *dsds) |
10034 | 74 { |
75 ra_priv_t *ra_priv = demuxer->priv; | |
76 int len; | |
77 demux_stream_t *ds = demuxer->audio; | |
78 sh_audio_t *sh = ds->sh; | |
79 WAVEFORMATEX *wf = sh->wf; | |
80 demux_packet_t *dp; | |
17149
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
81 int x, y; |
10034 | 82 |
83 if (demuxer->stream->eof) | |
84 return 0; | |
85 | |
86 len = wf->nBlockAlign; | |
87 demuxer->filepos = stream_tell(demuxer->stream); | |
88 | |
21987
fed73db9ddb1
Use interleaver id to select the correct interleaver instead of guessing
rtogni
parents:
21421
diff
changeset
|
89 if ((ra_priv->intl_id == INTLID_INT4) || (ra_priv->intl_id == INTLID_SIPR)) { |
fed73db9ddb1
Use interleaver id to select the correct interleaver instead of guessing
rtogni
parents:
21421
diff
changeset
|
90 if (ra_priv->intl_id == INTLID_SIPR) { |
17400 | 91 int n; |
92 int bs = ra_priv->sub_packet_h * ra_priv->frame_size * 2 / 96; // nibbles per subpacket | |
93 stream_read(demuxer->stream, ra_priv->audio_buf, ra_priv->sub_packet_h * ra_priv->frame_size); | |
94 // Perform reordering | |
95 for(n = 0; n < 38; n++) { | |
96 int j; | |
97 int i = bs * sipr_swaps[n][0]; | |
98 int o = bs * sipr_swaps[n][1]; | |
99 // swap nibbles of block 'i' with 'o' TODO: optimize | |
100 for(j = 0; j < bs; j++) { | |
101 int x = (i & 1) ? (ra_priv->audio_buf[i >> 1] >> 4) : (ra_priv->audio_buf[i >> 1] & 0x0F); | |
102 int y = (o & 1) ? (ra_priv->audio_buf[o >> 1] >> 4) : (ra_priv->audio_buf[o >> 1] & 0x0F); | |
103 if(o & 1) | |
104 ra_priv->audio_buf[o >> 1] = (ra_priv->audio_buf[o >> 1] & 0x0F) | (x << 4); | |
105 else | |
106 ra_priv->audio_buf[o >> 1] = (ra_priv->audio_buf[o >> 1] & 0xF0) | x; | |
107 if(i & 1) | |
108 ra_priv->audio_buf[i >> 1] = (ra_priv->audio_buf[i >> 1] & 0x0F) | (y << 4); | |
109 else | |
110 ra_priv->audio_buf[i >> 1] = (ra_priv->audio_buf[i >> 1] & 0xF0) | y; | |
111 ++i; ++o; | |
112 } | |
113 } | |
114 } else { | |
17149
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
115 for (y = 0; y < ra_priv->sub_packet_h; y++) |
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
116 for (x = 0; x < ra_priv->sub_packet_h / 2; x++) |
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
117 stream_read(demuxer->stream, ra_priv->audio_buf + x * 2 *ra_priv->frame_size + |
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
118 y * ra_priv->coded_framesize, ra_priv->coded_framesize); |
17400 | 119 } |
17149
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
120 // Release all the audio packets |
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
121 for (x = 0; x < ra_priv->sub_packet_h * ra_priv->frame_size / len; x++) { |
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
122 dp = new_demux_packet(len); |
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
123 memcpy(dp->buffer, ra_priv->audio_buf + x * len, len); |
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
124 dp->pts = x ? 0 : demuxer->filepos / ra_priv->data_size; |
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
125 dp->pos = demuxer->filepos; // all equal |
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
126 dp->flags = x ? 0 : 0x10; // Mark first packet as keyframe |
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
127 ds_add_packet(ds, dp); |
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
128 } |
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
129 } else { |
10034 | 130 dp = new_demux_packet(len); |
131 stream_read(demuxer->stream, dp->buffer, len); | |
132 | |
10035 | 133 dp->pts = demuxer->filepos / ra_priv->data_size; |
10034 | 134 dp->pos = demuxer->filepos; |
135 dp->flags = 0; | |
136 ds_add_packet(ds, dp); | |
17149
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
137 } |
10034 | 138 |
139 return 1; | |
140 } | |
141 | |
142 | |
143 | |
17977
f70772d02eaa
Convert printfs in aviprint.c to mp_msg and give the information printing
diego
parents:
17636
diff
changeset
|
144 extern void print_wave_header(WAVEFORMATEX *h, int verbose_level); |
10034 | 145 |
146 | |
147 | |
16175 | 148 static demuxer_t* demux_open_ra(demuxer_t* demuxer) |
10034 | 149 { |
150 ra_priv_t* ra_priv = demuxer->priv; | |
151 sh_audio_t *sh; | |
152 int i; | |
153 char *buf; | |
154 | |
19062
83c3afeab35d
drops casts from void * on malloc/calloc from libmpdemux code
reynaldo
parents:
18958
diff
changeset
|
155 if ((ra_priv = malloc(sizeof(ra_priv_t))) == NULL) { |
10034 | 156 mp_msg(MSGT_DEMUX, MSGL_ERR, "[RealAudio] Can't allocate memory for private data.\n"); |
10232 | 157 return 0; |
10034 | 158 } |
159 memset(ra_priv, 0, sizeof(ra_priv_t)); | |
160 | |
161 demuxer->priv = ra_priv; | |
162 sh = new_sh_audio(demuxer, 0); | |
163 demuxer->audio->id = 0; | |
164 sh->ds=demuxer->audio; | |
165 demuxer->audio->sh = sh; | |
166 | |
167 ra_priv->version = stream_read_word(demuxer->stream); | |
168 mp_msg(MSGT_DEMUX,MSGL_V,"[RealAudio] File version: %d\n", ra_priv->version); | |
169 if ((ra_priv->version < 3) || (ra_priv->version > 4)) { | |
170 mp_msg(MSGT_DEMUX,MSGL_WARN,"[RealAudio] ra version %d is not supported yet, please " | |
171 "contact MPlayer developers\n", ra_priv->version); | |
10232 | 172 return 0; |
10034 | 173 } |
174 if (ra_priv->version == 3) { | |
175 ra_priv->hdr_size = stream_read_word(demuxer->stream); | |
176 stream_skip(demuxer->stream, 10); | |
177 ra_priv->data_size = stream_read_dword(demuxer->stream); | |
178 } else { | |
179 stream_skip(demuxer->stream, 2); | |
180 ra_priv->dotranum = stream_read_dword(demuxer->stream); | |
181 ra_priv->data_size = stream_read_dword(demuxer->stream); | |
182 ra_priv->version2 = stream_read_word(demuxer->stream); | |
183 ra_priv->hdr_size = stream_read_dword(demuxer->stream); | |
184 ra_priv->codec_flavor = stream_read_word(demuxer->stream); | |
17400 | 185 mp_msg(MSGT_DEMUX,MSGL_V,"[RealAudio] Flavor: %d\n", ra_priv->codec_flavor); |
10034 | 186 ra_priv->coded_framesize = stream_read_dword(demuxer->stream); |
17400 | 187 mp_msg(MSGT_DEMUX,MSGL_V,"[RealAudio] Coded frame size: %d\n", ra_priv->coded_framesize); |
10034 | 188 stream_skip(demuxer->stream, 4); // data size? |
189 stream_skip(demuxer->stream, 8); | |
190 ra_priv->sub_packet_h = stream_read_word(demuxer->stream); | |
17400 | 191 mp_msg(MSGT_DEMUX,MSGL_V,"[RealAudio] Sub packet h: %d\n", ra_priv->sub_packet_h); |
10034 | 192 ra_priv->frame_size = stream_read_word(demuxer->stream); |
193 mp_msg(MSGT_DEMUX,MSGL_V,"[RealAudio] Frame size: %d\n", ra_priv->frame_size); | |
194 ra_priv->sub_packet_size = stream_read_word(demuxer->stream); | |
195 mp_msg(MSGT_DEMUX,MSGL_V,"[RealAudio] Sub packet size: %d\n", ra_priv->sub_packet_size); | |
196 stream_skip(demuxer->stream, 2); | |
197 sh->samplerate = stream_read_word(demuxer->stream); | |
198 stream_skip(demuxer->stream, 2); | |
199 sh->samplesize = stream_read_word(demuxer->stream); | |
200 sh->channels = stream_read_word(demuxer->stream); | |
201 mp_msg(MSGT_DEMUX,MSGL_V,"[RealAudio] %d channel, %d bit, %dHz\n", sh->channels, | |
202 sh->samplesize, sh->samplerate); | |
203 i = stream_read_char(demuxer->stream); | |
21987
fed73db9ddb1
Use interleaver id to select the correct interleaver instead of guessing
rtogni
parents:
21421
diff
changeset
|
204 ra_priv->intl_id = stream_read_dword_le(demuxer->stream); |
10034 | 205 if (i != 4) { |
21987
fed73db9ddb1
Use interleaver id to select the correct interleaver instead of guessing
rtogni
parents:
21421
diff
changeset
|
206 mp_msg(MSGT_DEMUX,MSGL_WARN,"[RealAudio] Interleaver Id size is not 4 (%d), please report to " |
10034 | 207 "MPlayer developers\n", i); |
208 stream_skip(demuxer->stream, i - 4); | |
209 } | |
210 i = stream_read_char(demuxer->stream); | |
211 sh->format = stream_read_dword_le(demuxer->stream); | |
212 if (i != 4) { | |
213 mp_msg(MSGT_DEMUX,MSGL_WARN,"[RealAudio] FourCC size is not 4 (%d), please report to " | |
214 "MPlayer developers\n", i); | |
215 stream_skip(demuxer->stream, i - 4); | |
216 } | |
217 stream_skip(demuxer->stream, 3); | |
218 } | |
219 | |
220 if ((i = stream_read_char(demuxer->stream)) != 0) { | |
221 buf = malloc(i+1); | |
222 stream_read(demuxer->stream, buf, i); | |
223 buf[i] = 0; | |
224 demux_info_add(demuxer, "Title", buf); | |
225 free(buf); | |
226 } | |
227 if ((i = stream_read_char(demuxer->stream)) != 0) { | |
228 buf = malloc(i+1); | |
229 stream_read(demuxer->stream, buf, i); | |
230 buf[i] = 0; | |
231 demux_info_add(demuxer, "Author", buf); | |
232 free(buf); | |
233 } | |
234 if ((i = stream_read_char(demuxer->stream)) != 0) { | |
235 buf = malloc(i+1); | |
236 stream_read(demuxer->stream, buf, i); | |
237 buf[i] = 0; | |
238 demux_info_add(demuxer, "Copyright", buf); | |
239 free(buf); | |
240 } | |
241 | |
14908 | 242 if ((i = stream_read_char(demuxer->stream)) != 0) { |
243 buf = malloc(i+1); | |
244 stream_read(demuxer->stream, buf, i); | |
245 buf[i] = 0; | |
246 demux_info_add(demuxer, "Comment", buf); | |
247 free(buf); | |
248 } | |
10034 | 249 |
250 if (ra_priv->version == 3) { | |
14909 | 251 if(ra_priv->hdr_size + 8 > stream_tell(demuxer->stream)) { |
10034 | 252 stream_skip(demuxer->stream, 1); |
253 i = stream_read_char(demuxer->stream); | |
254 sh->format = stream_read_dword_le(demuxer->stream); | |
255 if (i != 4) { | |
256 mp_msg(MSGT_DEMUX,MSGL_WARN,"[RealAudio] FourCC size is not 4 (%d), please report to " | |
257 "MPlayer developers\n", i); | |
258 stream_skip(demuxer->stream, i - 4); | |
259 } | |
260 | |
261 if (sh->format != FOURCC_LPCJ) { | |
262 mp_msg(MSGT_DEMUX,MSGL_WARN,"[RealAudio] Version 3 with FourCC %8x, please report to " | |
263 "MPlayer developers\n", sh->format); | |
264 } | |
14909 | 265 } else |
266 // If a stream does not have fourcc, let's assume it's 14.4 | |
267 sh->format = FOURCC_LPCJ; | |
10034 | 268 |
269 sh->channels = 1; | |
270 sh->samplesize = 16; | |
271 sh->samplerate = 8000; | |
272 ra_priv->frame_size = 240; | |
273 sh->format = FOURCC_144; | |
274 } | |
275 | |
276 /* Fill WAVEFORMATEX */ | |
277 sh->wf = malloc(sizeof(WAVEFORMATEX)); | |
278 memset(sh->wf, 0, sizeof(WAVEFORMATEX)); | |
279 sh->wf->nChannels = sh->channels; | |
280 sh->wf->wBitsPerSample = sh->samplesize; | |
281 sh->wf->nSamplesPerSec = sh->samplerate; | |
282 sh->wf->nAvgBytesPerSec = sh->samplerate*sh->samplesize/8; | |
283 sh->wf->nBlockAlign = ra_priv->frame_size; | |
284 sh->wf->cbSize = 0; | |
285 sh->wf->wFormatTag = sh->format; | |
286 | |
287 switch (sh->format) { | |
288 case FOURCC_144: | |
289 mp_msg(MSGT_DEMUX,MSGL_V,"Audio: 14_4\n"); | |
17149
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
290 sh->wf->nBlockAlign = 0x14; |
10034 | 291 break; |
292 case FOURCC_288: | |
293 mp_msg(MSGT_DEMUX,MSGL_V,"Audio: 28_8\n"); | |
17149
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
294 sh->wf->nBlockAlign = ra_priv->coded_framesize; |
18505
01b9f29c2fb5
Fix some potential integer overflow in memory allocation (mot of these
rtognimp
parents:
17977
diff
changeset
|
295 ra_priv->audio_buf = calloc(ra_priv->sub_packet_h, ra_priv->frame_size); |
10034 | 296 break; |
297 case FOURCC_DNET: | |
298 mp_msg(MSGT_DEMUX,MSGL_V,"Audio: DNET -> AC3\n"); | |
299 break; | |
17400 | 300 case FOURCC_SIPR: |
301 mp_msg(MSGT_DEMUX,MSGL_V,"Audio: SIPR\n"); | |
302 sh->wf->nBlockAlign = ra_priv->coded_framesize; | |
303 sh->wf->nAvgBytesPerSec = sipr_fl2bps[ra_priv->codec_flavor]; | |
18505
01b9f29c2fb5
Fix some potential integer overflow in memory allocation (mot of these
rtognimp
parents:
17977
diff
changeset
|
304 ra_priv->audio_buf = calloc(ra_priv->sub_packet_h, ra_priv->frame_size); |
17400 | 305 break; |
10034 | 306 default: |
307 mp_msg(MSGT_DEMUX,MSGL_V,"Audio: Unknown (%d)\n", sh->format); | |
308 } | |
309 | |
17977
f70772d02eaa
Convert printfs in aviprint.c to mp_msg and give the information printing
diego
parents:
17636
diff
changeset
|
310 print_wave_header(sh->wf, MSGL_V); |
10034 | 311 |
312 /* disable seeking */ | |
313 demuxer->seekable = 0; | |
314 | |
315 if(!ds_fill_buffer(demuxer->audio)) | |
316 mp_msg(MSGT_DEMUXER,MSGL_INFO,"[RealAudio] No data.\n"); | |
10232 | 317 |
16175 | 318 return demuxer; |
10034 | 319 } |
320 | |
321 | |
322 | |
16175 | 323 static void demux_close_ra(demuxer_t *demuxer) |
10034 | 324 { |
325 ra_priv_t* ra_priv = demuxer->priv; | |
326 | |
17149
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
327 if (ra_priv) { |
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
328 if (ra_priv->audio_buf) |
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
329 free (ra_priv->audio_buf); |
10034 | 330 free(ra_priv); |
17149
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
331 } |
10034 | 332 return; |
333 } | |
334 | |
335 | |
336 #if 0 | |
337 /* please upload RV10 samples WITH INDEX CHUNK */ | |
17636 | 338 int demux_seek_ra(demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int flags) |
10034 | 339 { |
340 real_priv_t *priv = demuxer->priv; | |
341 demux_stream_t *d_audio = demuxer->audio; | |
342 sh_audio_t *sh_audio = d_audio->sh; | |
343 int aid = d_audio->id; | |
344 int next_offset = 0; | |
345 int rel_seek_frames = 0; | |
346 int streams = 0; | |
347 | |
348 return stream_seek(demuxer->stream, next_offset); | |
349 } | |
350 #endif | |
16175 | 351 |
352 | |
25707
d4fe6e23283e
Make all demuxer_desc_t const, thus moving them to .rodata
reimar
parents:
22605
diff
changeset
|
353 const demuxer_desc_t demuxer_desc_realaudio = { |
16175 | 354 "Realaudio demuxer", |
355 "realaudio", | |
356 "REALAUDIO", | |
357 "Roberto Togni", | |
358 "handles old audio only .ra files", | |
359 DEMUXER_TYPE_REALAUDIO, | |
360 1, // safe autodetect | |
361 ra_check_file, | |
362 demux_ra_fill_buffer, | |
363 demux_open_ra, | |
364 demux_close_ra, | |
365 NULL, | |
366 NULL | |
367 }; |