Mercurial > mplayer.hg
annotate libmpdemux/demux_realaud.c @ 17149:9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
files (old and new format), pass only real extradata to the codec
Enable cook codec from lavc, prefer lavc codecs for 14_4 and 28_8
formats. Disable internal 28_8, it's broken now and will be removed soon
author | rtognimp |
---|---|
date | Fri, 09 Dec 2005 16:25:37 +0000 |
parents | 9cb2b9b6a9b7 |
children | 7dd65dccf4f5 |
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 | |
14 #include "stream.h" | |
15 #include "demuxer.h" | |
16 #include "stheader.h" | |
17 #include "bswap.h" | |
18 | |
19 | |
20 #define FOURCC_DOTRA mmioFOURCC('.','r','a', 0xfd) | |
21 #define FOURCC_144 mmioFOURCC('1','4','_','4') | |
22 #define FOURCC_288 mmioFOURCC('2','8','_','8') | |
23 #define FOURCC_DNET mmioFOURCC('d','n','e','t') | |
24 #define FOURCC_LPCJ mmioFOURCC('l','p','c','J') | |
25 | |
26 | |
27 typedef struct { | |
28 unsigned short version; | |
29 unsigned int dotranum; | |
30 unsigned int data_size; | |
31 unsigned short version2; | |
32 unsigned int hdr_size; | |
33 unsigned short codec_flavor; | |
34 unsigned int coded_framesize; | |
35 unsigned short sub_packet_h; | |
36 unsigned short frame_size; | |
37 unsigned short sub_packet_size; | |
38 char genr[4]; | |
17149
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
39 char * audio_buf; |
10034 | 40 } ra_priv_t; |
41 | |
42 | |
43 | |
16175 | 44 static int ra_check_file(demuxer_t* demuxer) |
10034 | 45 { |
46 unsigned int chunk_id; | |
47 | |
48 chunk_id = stream_read_dword_le(demuxer->stream); | |
49 if (chunk_id == FOURCC_DOTRA) | |
16175 | 50 return DEMUXER_TYPE_REALAUDIO; |
10034 | 51 else |
52 return 0; | |
53 } | |
54 | |
55 | |
56 | |
57 void hexdump(char *, unsigned long); | |
58 | |
59 // return value: | |
60 // 0 = EOF or no stream found | |
61 // 1 = successfully read a packet | |
16175 | 62 static int demux_ra_fill_buffer(demuxer_t *demuxer, demux_stream_t *dsds) |
10034 | 63 { |
64 ra_priv_t *ra_priv = demuxer->priv; | |
65 int len; | |
66 int timestamp; | |
67 int flags; | |
68 demux_stream_t *ds = demuxer->audio; | |
69 sh_audio_t *sh = ds->sh; | |
70 WAVEFORMATEX *wf = sh->wf; | |
71 demux_packet_t *dp; | |
17149
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
72 int x, y; |
10034 | 73 |
74 if (demuxer->stream->eof) | |
75 return 0; | |
76 | |
77 len = wf->nBlockAlign; | |
78 demuxer->filepos = stream_tell(demuxer->stream); | |
79 | |
17149
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
80 if (sh->format == FOURCC_288) { |
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
81 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
|
82 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
|
83 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
|
84 y * ra_priv->coded_framesize, ra_priv->coded_framesize); |
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
85 // Release all the audio packets |
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
86 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
|
87 dp = new_demux_packet(len); |
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
88 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
|
89 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
|
90 dp->pos = demuxer->filepos; // all equal |
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
91 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
|
92 ds_add_packet(ds, dp); |
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
93 } |
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
94 } else { |
10034 | 95 dp = new_demux_packet(len); |
96 stream_read(demuxer->stream, dp->buffer, len); | |
97 | |
10035 | 98 dp->pts = demuxer->filepos / ra_priv->data_size; |
10034 | 99 dp->pos = demuxer->filepos; |
100 dp->flags = 0; | |
101 ds_add_packet(ds, dp); | |
17149
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
102 } |
10034 | 103 |
104 return 1; | |
105 } | |
106 | |
107 | |
108 | |
109 extern void print_wave_header(WAVEFORMATEX *h); | |
110 | |
111 | |
112 | |
16175 | 113 static demuxer_t* demux_open_ra(demuxer_t* demuxer) |
10034 | 114 { |
115 ra_priv_t* ra_priv = demuxer->priv; | |
116 sh_audio_t *sh; | |
117 int i; | |
118 char *buf; | |
119 | |
120 if ((ra_priv = (ra_priv_t *)malloc(sizeof(ra_priv_t))) == NULL) { | |
121 mp_msg(MSGT_DEMUX, MSGL_ERR, "[RealAudio] Can't allocate memory for private data.\n"); | |
10232 | 122 return 0; |
10034 | 123 } |
124 memset(ra_priv, 0, sizeof(ra_priv_t)); | |
125 | |
126 demuxer->priv = ra_priv; | |
127 sh = new_sh_audio(demuxer, 0); | |
128 demuxer->audio->id = 0; | |
129 sh->ds=demuxer->audio; | |
130 demuxer->audio->sh = sh; | |
131 | |
132 ra_priv->version = stream_read_word(demuxer->stream); | |
133 mp_msg(MSGT_DEMUX,MSGL_V,"[RealAudio] File version: %d\n", ra_priv->version); | |
134 if ((ra_priv->version < 3) || (ra_priv->version > 4)) { | |
135 mp_msg(MSGT_DEMUX,MSGL_WARN,"[RealAudio] ra version %d is not supported yet, please " | |
136 "contact MPlayer developers\n", ra_priv->version); | |
10232 | 137 return 0; |
10034 | 138 } |
139 if (ra_priv->version == 3) { | |
140 ra_priv->hdr_size = stream_read_word(demuxer->stream); | |
141 stream_skip(demuxer->stream, 10); | |
142 ra_priv->data_size = stream_read_dword(demuxer->stream); | |
143 } else { | |
144 stream_skip(demuxer->stream, 2); | |
145 ra_priv->dotranum = stream_read_dword(demuxer->stream); | |
146 ra_priv->data_size = stream_read_dword(demuxer->stream); | |
147 ra_priv->version2 = stream_read_word(demuxer->stream); | |
148 ra_priv->hdr_size = stream_read_dword(demuxer->stream); | |
149 ra_priv->codec_flavor = stream_read_word(demuxer->stream); | |
150 ra_priv->coded_framesize = stream_read_dword(demuxer->stream); | |
151 stream_skip(demuxer->stream, 4); // data size? | |
152 stream_skip(demuxer->stream, 8); | |
153 ra_priv->sub_packet_h = stream_read_word(demuxer->stream); | |
154 ra_priv->frame_size = stream_read_word(demuxer->stream); | |
155 mp_msg(MSGT_DEMUX,MSGL_V,"[RealAudio] Frame size: %d\n", ra_priv->frame_size); | |
156 ra_priv->sub_packet_size = stream_read_word(demuxer->stream); | |
157 mp_msg(MSGT_DEMUX,MSGL_V,"[RealAudio] Sub packet size: %d\n", ra_priv->sub_packet_size); | |
158 stream_skip(demuxer->stream, 2); | |
159 sh->samplerate = stream_read_word(demuxer->stream); | |
160 stream_skip(demuxer->stream, 2); | |
161 sh->samplesize = stream_read_word(demuxer->stream); | |
162 sh->channels = stream_read_word(demuxer->stream); | |
163 mp_msg(MSGT_DEMUX,MSGL_V,"[RealAudio] %d channel, %d bit, %dHz\n", sh->channels, | |
164 sh->samplesize, sh->samplerate); | |
165 i = stream_read_char(demuxer->stream); | |
16322
9cb2b9b6a9b7
Sparcs do not like wild pointer typecasting (unaligned access).
reimar
parents:
16175
diff
changeset
|
166 ra_priv->genr[0] = stream_read_char(demuxer->stream); |
9cb2b9b6a9b7
Sparcs do not like wild pointer typecasting (unaligned access).
reimar
parents:
16175
diff
changeset
|
167 ra_priv->genr[1] = stream_read_char(demuxer->stream); |
9cb2b9b6a9b7
Sparcs do not like wild pointer typecasting (unaligned access).
reimar
parents:
16175
diff
changeset
|
168 ra_priv->genr[2] = stream_read_char(demuxer->stream); |
9cb2b9b6a9b7
Sparcs do not like wild pointer typecasting (unaligned access).
reimar
parents:
16175
diff
changeset
|
169 ra_priv->genr[3] = stream_read_char(demuxer->stream); |
10034 | 170 if (i != 4) { |
171 mp_msg(MSGT_DEMUX,MSGL_WARN,"[RealAudio] Genr size is not 4 (%d), please report to " | |
172 "MPlayer developers\n", i); | |
173 stream_skip(demuxer->stream, i - 4); | |
174 } | |
175 i = stream_read_char(demuxer->stream); | |
176 sh->format = stream_read_dword_le(demuxer->stream); | |
177 if (i != 4) { | |
178 mp_msg(MSGT_DEMUX,MSGL_WARN,"[RealAudio] FourCC size is not 4 (%d), please report to " | |
179 "MPlayer developers\n", i); | |
180 stream_skip(demuxer->stream, i - 4); | |
181 } | |
182 stream_skip(demuxer->stream, 3); | |
183 } | |
184 | |
185 if ((i = stream_read_char(demuxer->stream)) != 0) { | |
186 buf = malloc(i+1); | |
187 stream_read(demuxer->stream, buf, i); | |
188 buf[i] = 0; | |
189 demux_info_add(demuxer, "Title", buf); | |
190 free(buf); | |
191 } | |
192 if ((i = stream_read_char(demuxer->stream)) != 0) { | |
193 buf = malloc(i+1); | |
194 stream_read(demuxer->stream, buf, i); | |
195 buf[i] = 0; | |
196 demux_info_add(demuxer, "Author", buf); | |
197 free(buf); | |
198 } | |
199 if ((i = stream_read_char(demuxer->stream)) != 0) { | |
200 buf = malloc(i+1); | |
201 stream_read(demuxer->stream, buf, i); | |
202 buf[i] = 0; | |
203 demux_info_add(demuxer, "Copyright", buf); | |
204 free(buf); | |
205 } | |
206 | |
14908 | 207 if ((i = stream_read_char(demuxer->stream)) != 0) { |
208 buf = malloc(i+1); | |
209 stream_read(demuxer->stream, buf, i); | |
210 buf[i] = 0; | |
211 demux_info_add(demuxer, "Comment", buf); | |
212 free(buf); | |
213 } | |
10034 | 214 |
215 if (ra_priv->version == 3) { | |
14909 | 216 if(ra_priv->hdr_size + 8 > stream_tell(demuxer->stream)) { |
10034 | 217 stream_skip(demuxer->stream, 1); |
218 i = stream_read_char(demuxer->stream); | |
219 sh->format = stream_read_dword_le(demuxer->stream); | |
220 if (i != 4) { | |
221 mp_msg(MSGT_DEMUX,MSGL_WARN,"[RealAudio] FourCC size is not 4 (%d), please report to " | |
222 "MPlayer developers\n", i); | |
223 stream_skip(demuxer->stream, i - 4); | |
224 } | |
225 | |
226 if (sh->format != FOURCC_LPCJ) { | |
227 mp_msg(MSGT_DEMUX,MSGL_WARN,"[RealAudio] Version 3 with FourCC %8x, please report to " | |
228 "MPlayer developers\n", sh->format); | |
229 } | |
14909 | 230 } else |
231 // If a stream does not have fourcc, let's assume it's 14.4 | |
232 sh->format = FOURCC_LPCJ; | |
10034 | 233 |
234 sh->channels = 1; | |
235 sh->samplesize = 16; | |
236 sh->samplerate = 8000; | |
237 ra_priv->frame_size = 240; | |
238 sh->format = FOURCC_144; | |
239 } | |
240 | |
241 /* Fill WAVEFORMATEX */ | |
242 sh->wf = malloc(sizeof(WAVEFORMATEX)); | |
243 memset(sh->wf, 0, sizeof(WAVEFORMATEX)); | |
244 sh->wf->nChannels = sh->channels; | |
245 sh->wf->wBitsPerSample = sh->samplesize; | |
246 sh->wf->nSamplesPerSec = sh->samplerate; | |
247 sh->wf->nAvgBytesPerSec = sh->samplerate*sh->samplesize/8; | |
248 sh->wf->nBlockAlign = ra_priv->frame_size; | |
249 sh->wf->cbSize = 0; | |
250 sh->wf->wFormatTag = sh->format; | |
251 | |
252 switch (sh->format) { | |
253 case FOURCC_144: | |
254 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
|
255 sh->wf->nBlockAlign = 0x14; |
10034 | 256 break; |
257 case FOURCC_288: | |
258 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
|
259 sh->wf->nBlockAlign = ra_priv->coded_framesize; |
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
260 ra_priv->audio_buf = malloc(ra_priv->sub_packet_h * ra_priv->frame_size); |
10034 | 261 break; |
262 case FOURCC_DNET: | |
263 mp_msg(MSGT_DEMUX,MSGL_V,"Audio: DNET -> AC3\n"); | |
264 break; | |
265 default: | |
266 mp_msg(MSGT_DEMUX,MSGL_V,"Audio: Unknown (%d)\n", sh->format); | |
267 } | |
268 | |
269 print_wave_header(sh->wf); | |
270 | |
271 /* disable seeking */ | |
272 demuxer->seekable = 0; | |
273 | |
274 if(!ds_fill_buffer(demuxer->audio)) | |
275 mp_msg(MSGT_DEMUXER,MSGL_INFO,"[RealAudio] No data.\n"); | |
10232 | 276 |
16175 | 277 return demuxer; |
10034 | 278 } |
279 | |
280 | |
281 | |
16175 | 282 static void demux_close_ra(demuxer_t *demuxer) |
10034 | 283 { |
284 ra_priv_t* ra_priv = demuxer->priv; | |
285 | |
17149
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
286 if (ra_priv) { |
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
287 if (ra_priv->audio_buf) |
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
288 free (ra_priv->audio_buf); |
10034 | 289 free(ra_priv); |
17149
9a0a376a54b1
Move audio packets reordering from codec interface to demuxers for real
rtognimp
parents:
16322
diff
changeset
|
290 } |
10034 | 291 return; |
292 } | |
293 | |
294 | |
295 #if 0 | |
296 /* please upload RV10 samples WITH INDEX CHUNK */ | |
297 int demux_seek_ra(demuxer_t *demuxer, float rel_seek_secs, int flags) | |
298 { | |
299 real_priv_t *priv = demuxer->priv; | |
300 demux_stream_t *d_audio = demuxer->audio; | |
301 sh_audio_t *sh_audio = d_audio->sh; | |
302 int aid = d_audio->id; | |
303 int next_offset = 0; | |
304 int rel_seek_frames = 0; | |
305 int streams = 0; | |
306 | |
307 return stream_seek(demuxer->stream, next_offset); | |
308 } | |
309 #endif | |
16175 | 310 |
311 | |
312 demuxer_desc_t demuxer_desc_realaudio = { | |
313 "Realaudio demuxer", | |
314 "realaudio", | |
315 "REALAUDIO", | |
316 "Roberto Togni", | |
317 "handles old audio only .ra files", | |
318 DEMUXER_TYPE_REALAUDIO, | |
319 1, // safe autodetect | |
320 ra_check_file, | |
321 demux_ra_fill_buffer, | |
322 demux_open_ra, | |
323 demux_close_ra, | |
324 NULL, | |
325 NULL | |
326 }; |