Mercurial > audlegacy-plugins
comparison src/mpg123/common.c @ 12:3da1b8942b8b trunk
[svn] - remove src/Input src/Output src/Effect src/General src/Visualization src/Container
author | nenolod |
---|---|
date | Mon, 18 Sep 2006 03:14:20 -0700 |
parents | src/Input/mpg123/common.c@13389e613d67 |
children | 1e2d575fd2e7 |
comparison
equal
deleted
inserted
replaced
11:cff1d04026ae | 12:3da1b8942b8b |
---|---|
1 #include <stdlib.h> | |
2 #include <string.h> | |
3 #include <ctype.h> | |
4 | |
5 #include <signal.h> | |
6 #include <sys/types.h> | |
7 #include <sys/stat.h> | |
8 #include <fcntl.h> | |
9 | |
10 #include "mpg123.h" | |
11 | |
12 const int tabsel_123[2][3][16] = { | |
13 {{0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, | |
14 448,}, | |
15 {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384,}, | |
16 {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320,}}, | |
17 {{0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256,}, | |
18 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,}, | |
19 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,}} | |
20 }; | |
21 | |
22 const int mpgdec_freqs[9] = | |
23 { 44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000 }; | |
24 | |
25 struct bitstream_info bsi; | |
26 | |
27 extern gint mpgdec_bitrate, mpgdec_frequency, mpgdec_length; | |
28 extern gchar *mpgdec_title, *mpgdec_filename; | |
29 extern gboolean mpgdec_stereo; | |
30 | |
31 static int fsizeold = 0, ssize; | |
32 static unsigned char bsspace[2][MAXFRAMESIZE + 512]; /* MAXFRAMESIZE */ | |
33 static unsigned char *bsbuf = bsspace[1], *bsbufold; | |
34 static int bsnum = 0; | |
35 | |
36 unsigned char *mpgdec_pcm_sample; | |
37 int mpgdec_pcm_point = 0; | |
38 | |
39 static VFSFile *filept; | |
40 static int filept_opened; | |
41 | |
42 static int get_fileinfo(void); | |
43 | |
44 static int | |
45 fullread(VFSFile * fd, unsigned char *buf, int count) | |
46 { | |
47 int ret, cnt = 0; | |
48 | |
49 while (cnt < count) { | |
50 if (fd) | |
51 ret = vfs_fread(buf + cnt, 1, count - cnt, fd); | |
52 else | |
53 switch(mpgdec_info->stream_type) { | |
54 case STREAM_HTTP: | |
55 ret = mpgdec_http_read(buf + cnt, count - cnt); | |
56 break; | |
57 #ifdef HAVE_NEMESI | |
58 case STREAM_RTSP: | |
59 ret = mpgdec_rtsp_read(buf + cnt, count - cnt); | |
60 break; | |
61 #endif | |
62 default: | |
63 return -1; | |
64 } | |
65 if (ret < 0) | |
66 return ret; | |
67 if (ret == 0) | |
68 break; | |
69 cnt += ret; | |
70 } | |
71 return cnt; | |
72 } | |
73 | |
74 static int | |
75 stream_init(void) | |
76 { | |
77 if (get_fileinfo() < 0) | |
78 return -1; | |
79 return 0; | |
80 } | |
81 | |
82 void | |
83 mpgdec_stream_close(void) | |
84 { | |
85 if (filept) | |
86 vfs_fclose(filept); | |
87 else | |
88 switch(mpgdec_info->stream_type) { | |
89 case STREAM_HTTP: | |
90 mpgdec_http_close(); | |
91 break; | |
92 #ifdef HAVE_NEMESI | |
93 case STREAM_RTSP: | |
94 mpgdec_rtsp_close(); | |
95 break; | |
96 #endif | |
97 default: | |
98 break; | |
99 } | |
100 } | |
101 | |
102 /**************************************** | |
103 * HACK,HACK,HACK: step back <num> frames | |
104 * can only work if the 'stream' isn't a mpgdec_real stream but a file | |
105 static int stream_back_bytes(int bytes) | |
106 { | |
107 if (vfs_fseek(filept, -bytes, SEEK_CUR) < 0) | |
108 return -1; | |
109 return 0; | |
110 } | |
111 */ | |
112 | |
113 static int | |
114 stream_head_read(unsigned long *newhead) | |
115 { | |
116 unsigned char hbuf[4]; | |
117 | |
118 if (fullread(filept, hbuf, 4) != 4) | |
119 return FALSE; | |
120 | |
121 *newhead = ((unsigned long) hbuf[0] << 24) | | |
122 ((unsigned long) hbuf[1] << 16) | | |
123 ((unsigned long) hbuf[2] << 8) | (unsigned long) hbuf[3]; | |
124 | |
125 return TRUE; | |
126 } | |
127 | |
128 static int | |
129 stream_head_shift(unsigned long *head) | |
130 { | |
131 unsigned char hbuf; | |
132 | |
133 if (fullread(filept, &hbuf, 1) != 1) | |
134 return 0; | |
135 *head <<= 8; | |
136 *head |= hbuf; | |
137 *head &= 0xffffffff; | |
138 return 1; | |
139 } | |
140 | |
141 static int | |
142 stream_mpgdec_read_frame_body(unsigned char *buf, int size) | |
143 { | |
144 long l; | |
145 | |
146 if ((l = fullread(filept, buf, size)) != size) { | |
147 if (l <= 0) | |
148 return 0; | |
149 memset(buf + l, 0, size - l); | |
150 } | |
151 return 1; | |
152 } | |
153 | |
154 static long | |
155 stream_tell(void) | |
156 { | |
157 return vfs_ftell(filept); | |
158 } | |
159 | |
160 /* | |
161 static void stream_rewind(void) | |
162 { | |
163 vfs_fseek(filept, 0, SEEK_SET); | |
164 } | |
165 */ | |
166 | |
167 int | |
168 mpgdec_stream_jump_to_frame(struct frame *fr, int frame) | |
169 { | |
170 if (!filept) | |
171 return -1; | |
172 mpgdec_read_frame_init(); | |
173 vfs_fseek(filept, frame * (fr->framesize + 4), SEEK_SET); | |
174 mpgdec_read_frame(fr); | |
175 return 0; | |
176 } | |
177 | |
178 int | |
179 mpgdec_stream_jump_to_byte(struct frame *fr, int byte) | |
180 { | |
181 if (!filept) | |
182 return -1; | |
183 vfs_fseek(filept, byte, SEEK_SET); | |
184 mpgdec_read_frame(fr); | |
185 return 0; | |
186 } | |
187 | |
188 int | |
189 mpgdec_stream_check_for_xing_header(struct frame *fr, xing_header_t * xhead) | |
190 { | |
191 unsigned char *head_data; | |
192 int ret; | |
193 | |
194 vfs_fseek(filept, -(fr->framesize + 4), SEEK_CUR); | |
195 head_data = g_malloc(fr->framesize + 4); | |
196 vfs_fread(head_data, 1, fr->framesize + 4, filept); | |
197 ret = mpgdec_get_xing_header(xhead, head_data); | |
198 g_free(head_data); | |
199 return ret; | |
200 } | |
201 | |
202 static int | |
203 get_fileinfo(void) | |
204 { | |
205 guchar buf[3]; | |
206 | |
207 if (filept == NULL) | |
208 return -1; | |
209 if (vfs_fseek(filept, 0, SEEK_END) < 0) | |
210 return -1; | |
211 | |
212 mpgdec_info->filesize = vfs_ftell(filept); | |
213 if (vfs_fseek(filept, -128, SEEK_END) < 0) | |
214 return -1; | |
215 if (fullread(filept, buf, 3) != 3) | |
216 return -1; | |
217 if (!strncmp((char *) buf, "TAG", 3)) | |
218 mpgdec_info->filesize -= 128; | |
219 if (vfs_fseek(filept, 0, SEEK_SET) < 0) | |
220 return -1; | |
221 | |
222 if (mpgdec_info->filesize <= 0) | |
223 return -1; | |
224 | |
225 return mpgdec_info->filesize; | |
226 } | |
227 | |
228 void | |
229 mpgdec_read_frame_init(void) | |
230 { | |
231 memset(bsspace[0], 0, MAXFRAMESIZE + 512); | |
232 memset(bsspace[1], 0, MAXFRAMESIZE + 512); | |
233 mpgdec_info->output_audio = FALSE; | |
234 } | |
235 | |
236 int | |
237 mpgdec_head_check(unsigned long head) | |
238 { | |
239 if ((head & 0xffe00000) != 0xffe00000) | |
240 return FALSE; | |
241 if (!((head >> 17) & 3)) | |
242 return FALSE; | |
243 if (((head >> 12) & 0xf) == 0xf) | |
244 return FALSE; | |
245 if (!((head >> 12) & 0xf)) | |
246 return FALSE; | |
247 if (((head >> 10) & 0x3) == 0x3) | |
248 return FALSE; | |
249 if (((head >> 19) & 1) == 1 && | |
250 ((head >> 17) & 3) == 3 && ((head >> 16) & 1) == 1) | |
251 return FALSE; | |
252 if ((head & 0xffff0000) == 0xfffe0000) | |
253 return FALSE; | |
254 | |
255 return TRUE; | |
256 } | |
257 | |
258 /***************************************************************** | |
259 * read next frame | |
260 */ | |
261 int | |
262 mpgdec_read_frame(struct frame *fr) | |
263 { | |
264 unsigned long newhead; | |
265 | |
266 fsizeold = fr->framesize; /* for Layer3 */ | |
267 | |
268 if (!stream_head_read(&newhead)) | |
269 return FALSE; | |
270 | |
271 if (!mpgdec_head_check(newhead) || !mpgdec_decode_header(fr, newhead)) { | |
272 int try = 0; | |
273 | |
274 do { | |
275 try++; | |
276 if (!stream_head_shift(&newhead)) | |
277 return 0; | |
278 } | |
279 while ((!mpgdec_head_check(newhead) || | |
280 !mpgdec_decode_header(fr, newhead)) && try < (1024 * 1024)); | |
281 if (try >= (1024 * 1024)) | |
282 return FALSE; | |
283 #ifdef MPGDEC_INVBITSTREAM_NOTIFY | |
284 if (try >= 0) | |
285 g_log("mpgdec", G_LOG_LEVEL_WARNING, "mpgdec: illegal bitstream in the middle of the MPEG stream, skipped %d bytes", try); | |
286 #endif | |
287 mpgdec_info->filesize -= try; | |
288 } | |
289 /* flip/init buffer for Layer 3 */ | |
290 bsbufold = bsbuf; | |
291 bsbuf = bsspace[bsnum] + 512; | |
292 bsnum = (bsnum + 1) & 1; | |
293 | |
294 if (!stream_mpgdec_read_frame_body(bsbuf, fr->framesize)) | |
295 return 0; | |
296 | |
297 bsi.bitindex = 0; | |
298 bsi.wordpointer = (unsigned char *) bsbuf; | |
299 | |
300 | |
301 return 1; | |
302 | |
303 } | |
304 | |
305 /* | |
306 * the code a header and write the information | |
307 * into the frame structure | |
308 */ | |
309 int | |
310 mpgdec_decode_header(struct frame *fr, unsigned long newhead) | |
311 { | |
312 if (newhead & (1 << 20)) { | |
313 fr->lsf = (newhead & (1 << 19)) ? 0x0 : 0x1; | |
314 fr->mpeg25 = 0; | |
315 } | |
316 else { | |
317 fr->lsf = 1; | |
318 fr->mpeg25 = 1; | |
319 } | |
320 fr->lay = 4 - ((newhead >> 17) & 3); | |
321 if (fr->mpeg25) { | |
322 fr->sampling_frequency = 6 + ((newhead >> 10) & 0x3); | |
323 } | |
324 else | |
325 fr->sampling_frequency = ((newhead >> 10) & 0x3) + (fr->lsf * 3); | |
326 fr->error_protection = ((newhead >> 16) & 0x1) ^ 0x1; | |
327 | |
328 fr->bitrate_index = ((newhead >> 12) & 0xf); | |
329 fr->padding = ((newhead >> 9) & 0x1); | |
330 fr->extension = ((newhead >> 8) & 0x1); | |
331 fr->mode = ((newhead >> 6) & 0x3); | |
332 fr->mode_ext = ((newhead >> 4) & 0x3); | |
333 fr->copyright = ((newhead >> 3) & 0x1); | |
334 fr->original = ((newhead >> 2) & 0x1); | |
335 fr->emphasis = newhead & 0x3; | |
336 | |
337 fr->stereo = (fr->mode == MPG_MD_MONO) ? 1 : 2; | |
338 | |
339 ssize = 0; | |
340 | |
341 if (!fr->bitrate_index) | |
342 return (0); | |
343 | |
344 switch (fr->lay) { | |
345 case 1: | |
346 fr->do_layer = mpgdec_do_layer1; | |
347 /* inits also shared tables with layer1 */ | |
348 mpgdec_init_layer2(fr->synth_type == SYNTH_MMX); | |
349 fr->framesize = | |
350 (long) tabsel_123[fr->lsf][0][fr->bitrate_index] * 12000; | |
351 fr->framesize /= mpgdec_freqs[fr->sampling_frequency]; | |
352 fr->framesize = ((fr->framesize + fr->padding) << 2) - 4; | |
353 break; | |
354 case 2: | |
355 fr->do_layer = mpgdec_do_layer2; | |
356 /* inits also shared tables with layer1 */ | |
357 mpgdec_init_layer2(fr->synth_type == SYNTH_MMX); | |
358 fr->framesize = | |
359 (long) tabsel_123[fr->lsf][1][fr->bitrate_index] * 144000; | |
360 fr->framesize /= mpgdec_freqs[fr->sampling_frequency]; | |
361 fr->framesize += fr->padding - 4; | |
362 break; | |
363 case 3: | |
364 fr->do_layer = mpgdec_do_layer3; | |
365 if (fr->lsf) | |
366 ssize = (fr->stereo == 1) ? 9 : 17; | |
367 else | |
368 ssize = (fr->stereo == 1) ? 17 : 32; | |
369 if (fr->error_protection) | |
370 ssize += 2; | |
371 fr->framesize = | |
372 (long) tabsel_123[fr->lsf][2][fr->bitrate_index] * 144000; | |
373 fr->framesize /= mpgdec_freqs[fr->sampling_frequency] << (fr->lsf); | |
374 fr->framesize = fr->framesize + fr->padding - 4; | |
375 break; | |
376 default: | |
377 return (0); | |
378 } | |
379 if (fr->framesize > MAXFRAMESIZE) | |
380 return 0; | |
381 return 1; | |
382 } | |
383 | |
384 void | |
385 mpgdec_open_stream(char *bs_filenam, int fd) | |
386 { | |
387 filept_opened = 1; | |
388 if (!strncasecmp(bs_filenam, "http://", 7)) { | |
389 filept = NULL; | |
390 mpgdec_http_open(bs_filenam); | |
391 mpgdec_info->filesize = 0; | |
392 mpgdec_info->network_stream = TRUE; | |
393 mpgdec_info->stream_type = STREAM_HTTP; | |
394 } | |
395 else | |
396 #ifdef HAVE_NEMESI | |
397 if (!strncasecmp(bs_filenam, "rtsp://", 7)) { | |
398 filept = NULL; | |
399 mpgdec_info->filesize = 0; | |
400 mpgdec_info->network_stream = TRUE; | |
401 mpgdec_info->stream_type = STREAM_RTSP; | |
402 if (mpgdec_rtsp_open(bs_filenam)) mpgdec_info->eof = TRUE; | |
403 } else { | |
404 #else | |
405 { | |
406 #endif | |
407 if ((filept = vfs_fopen(bs_filenam, "rb")) == NULL || | |
408 stream_init() == -1) | |
409 mpgdec_info->eof = TRUE; | |
410 } | |
411 | |
412 } | |
413 | |
414 void | |
415 mpgdec_set_pointer(long backstep) | |
416 { | |
417 bsi.wordpointer = bsbuf + ssize - backstep; | |
418 if (backstep) | |
419 memcpy(bsi.wordpointer, bsbufold + fsizeold - backstep, backstep); | |
420 bsi.bitindex = 0; | |
421 } | |
422 | |
423 double | |
424 mpgdec_compute_bpf(struct frame *fr) | |
425 { | |
426 double bpf; | |
427 | |
428 switch (fr->lay) { | |
429 case 1: | |
430 bpf = tabsel_123[fr->lsf][0][fr->bitrate_index]; | |
431 bpf *= 12000.0 * 4.0; | |
432 bpf /= mpgdec_freqs[fr->sampling_frequency] << (fr->lsf); | |
433 break; | |
434 case 2: | |
435 case 3: | |
436 bpf = tabsel_123[fr->lsf][fr->lay - 1][fr->bitrate_index]; | |
437 bpf *= 144000; | |
438 bpf /= mpgdec_freqs[fr->sampling_frequency] << (fr->lsf); | |
439 break; | |
440 default: | |
441 bpf = 1.0; | |
442 } | |
443 | |
444 return bpf; | |
445 } | |
446 | |
447 int | |
448 mpgdec_calc_numframes(struct frame *fr) | |
449 { | |
450 return (int) (mpgdec_info->filesize / mpgdec_compute_bpf(fr)); | |
451 } | |
452 | |
453 double | |
454 mpgdec_relative_pos(void) | |
455 { | |
456 if (!filept || !mpgdec_info->filesize) | |
457 return 0; | |
458 return ((double) stream_tell()) / mpgdec_info->filesize; | |
459 } |