Mercurial > audlegacy
annotate Plugins/Input/mpg123/common.c @ 790:8f437afc4f4a trunk
[svn] - more sanity checking
author | nenolod |
---|---|
date | Fri, 03 Mar 2006 20:09:52 -0800 |
parents | 2d0e9b8d8403 |
children | 12f57026da8f |
rev | line source |
---|---|
61 | 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 #include "xmms-id3.h" | |
12 #include "id3_header.h" | |
13 | |
14 const int tabsel_123[2][3][16] = { | |
15 {{0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, | |
16 448,}, | |
17 {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384,}, | |
18 {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320,}}, | |
19 {{0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256,}, | |
20 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,}, | |
21 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,}} | |
22 }; | |
23 | |
24 const int mpg123_freqs[9] = | |
25 { 44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000 }; | |
26 | |
27 struct bitstream_info bsi; | |
28 | |
29 extern gint mpg123_bitrate, mpg123_frequency, mpg123_length; | |
30 extern gchar *mpg123_title, *mpg123_filename; | |
31 extern gboolean mpg123_stereo; | |
32 | |
33 static int fsizeold = 0, ssize; | |
34 static unsigned char bsspace[2][MAXFRAMESIZE + 512]; /* MAXFRAMESIZE */ | |
35 static unsigned char *bsbuf = bsspace[1], *bsbufold; | |
36 static int bsnum = 0; | |
37 | |
38 unsigned char *mpg123_pcm_sample; | |
39 int mpg123_pcm_point = 0; | |
40 | |
41 static VFSFile *filept; | |
42 static int filept_opened; | |
43 | |
44 static int get_fileinfo(void); | |
45 | |
46 static int | |
47 fullread(VFSFile * fd, unsigned char *buf, int count) | |
48 { | |
49 int ret, cnt = 0; | |
50 | |
51 while (cnt < count) { | |
52 if (fd) | |
53 ret = vfs_fread(buf + cnt, 1, count - cnt, fd); | |
54 else | |
55 ret = mpg123_http_read(buf + cnt, count - cnt); | |
56 if (ret < 0) | |
57 return ret; | |
58 if (ret == 0) | |
59 break; | |
60 cnt += ret; | |
61 } | |
62 return cnt; | |
63 } | |
64 | |
65 static int | |
66 stream_init(void) | |
67 { | |
68 if (get_fileinfo() < 0) | |
69 return -1; | |
70 return 0; | |
71 } | |
72 | |
73 void | |
74 mpg123_stream_close(void) | |
75 { | |
76 if (filept) | |
77 vfs_fclose(filept); | |
78 else if (mpg123_info->network_stream) | |
79 mpg123_http_close(); | |
80 } | |
81 | |
82 /**************************************** | |
83 * HACK,HACK,HACK: step back <num> frames | |
84 * can only work if the 'stream' isn't a real stream but a file | |
85 static int stream_back_bytes(int bytes) | |
86 { | |
87 if (vfs_fseek(filept, -bytes, SEEK_CUR) < 0) | |
88 return -1; | |
89 return 0; | |
90 } | |
91 */ | |
92 | |
93 static int | |
94 stream_head_read(unsigned long *newhead) | |
95 { | |
96 unsigned char hbuf[4]; | |
97 | |
98 if (fullread(filept, hbuf, 4) != 4) | |
99 return FALSE; | |
100 | |
101 *newhead = ((unsigned long) hbuf[0] << 24) | | |
102 ((unsigned long) hbuf[1] << 16) | | |
103 ((unsigned long) hbuf[2] << 8) | (unsigned long) hbuf[3]; | |
104 | |
105 return TRUE; | |
106 } | |
107 | |
108 static int | |
109 stream_head_shift(unsigned long *head) | |
110 { | |
111 unsigned char hbuf; | |
112 | |
113 if (fullread(filept, &hbuf, 1) != 1) | |
114 return 0; | |
115 *head <<= 8; | |
116 *head |= hbuf; | |
117 *head &= 0xffffffff; | |
118 return 1; | |
119 } | |
120 | |
121 static int | |
122 stream_mpg123_read_frame_body(unsigned char *buf, int size) | |
123 { | |
124 long l; | |
125 | |
126 if ((l = fullread(filept, buf, size)) != size) { | |
127 if (l <= 0) | |
128 return 0; | |
129 memset(buf + l, 0, size - l); | |
130 } | |
131 return 1; | |
132 } | |
133 | |
134 static long | |
135 stream_tell(void) | |
136 { | |
137 return vfs_ftell(filept); | |
138 } | |
139 | |
140 /* | |
141 static void stream_rewind(void) | |
142 { | |
143 vfs_fseek(filept, 0, SEEK_SET); | |
144 } | |
145 */ | |
146 | |
147 int | |
148 mpg123_stream_jump_to_frame(struct frame *fr, int frame) | |
149 { | |
150 if (!filept) | |
151 return -1; | |
152 mpg123_read_frame_init(); | |
153 vfs_fseek(filept, frame * (fr->framesize + 4), SEEK_SET); | |
154 mpg123_read_frame(fr); | |
155 return 0; | |
156 } | |
157 | |
158 int | |
159 mpg123_stream_jump_to_byte(struct frame *fr, int byte) | |
160 { | |
161 if (!filept) | |
162 return -1; | |
163 vfs_fseek(filept, byte, SEEK_SET); | |
164 mpg123_read_frame(fr); | |
165 return 0; | |
166 } | |
167 | |
168 int | |
169 mpg123_stream_check_for_xing_header(struct frame *fr, xing_header_t * xhead) | |
170 { | |
171 unsigned char *head_data; | |
172 int ret; | |
173 | |
174 vfs_fseek(filept, -(fr->framesize + 4), SEEK_CUR); | |
175 head_data = g_malloc(fr->framesize + 4); | |
176 vfs_fread(head_data, 1, fr->framesize + 4, filept); | |
177 ret = mpg123_get_xing_header(xhead, head_data); | |
178 g_free(head_data); | |
179 return ret; | |
180 } | |
181 | |
182 static int | |
183 get_fileinfo(void) | |
184 { | |
185 guchar buf[3]; | |
186 | |
187 if (filept == NULL) | |
188 return -1; | |
189 if (vfs_fseek(filept, 0, SEEK_END) < 0) | |
190 return -1; | |
191 | |
192 mpg123_info->filesize = vfs_ftell(filept); | |
193 if (vfs_fseek(filept, -128, SEEK_END) < 0) | |
194 return -1; | |
195 if (fullread(filept, buf, 3) != 3) | |
196 return -1; | |
197 if (!strncmp((char *) buf, "TAG", 3)) | |
198 mpg123_info->filesize -= 128; | |
199 if (vfs_fseek(filept, 0, SEEK_SET) < 0) | |
200 return -1; | |
201 | |
202 if (mpg123_info->filesize <= 0) | |
203 return -1; | |
204 | |
205 return mpg123_info->filesize; | |
206 } | |
207 | |
208 void | |
209 mpg123_read_frame_init(void) | |
210 { | |
211 memset(bsspace[0], 0, MAXFRAMESIZE + 512); | |
212 memset(bsspace[1], 0, MAXFRAMESIZE + 512); | |
213 mpg123_info->output_audio = FALSE; | |
214 } | |
215 | |
216 /* | |
217 * Function read_id3v2_tag (head) | |
218 * | |
219 * Read ID3v2 tag from stream. Return TRUE upon success, or FALSE if | |
220 * an error occurred. | |
221 * | |
222 */ | |
223 static gboolean | |
224 read_id3v2_tag(unsigned long head) | |
225 { | |
226 guchar *id3buf; | |
701
d539e5c5f730
[svn] Fixes of the remaining GCC 4.1 warnings from external contributor Diego "Flameeyes" Petteno (Gentoo).
chainsaw
parents:
170
diff
changeset
|
227 gsize hdrsize; |
61 | 228 struct id3_tag *id3d; |
229 struct id3tag_t tag; | |
230 guchar buf[7]; | |
231 | |
232 buf[0] = head & 0xff; | |
233 /* | |
234 * Read ID3tag header. | |
235 */ | |
236 if (fullread(filept, buf + 1, 6) != 6) | |
237 return FALSE; | |
238 | |
239 hdrsize = ID3_GET_SIZE28(buf[3], buf[4], buf[5], buf[6]); | |
240 | |
241 /* | |
242 * A invalid header could fool us into requesting insane | |
243 * amounts of memory. Make sure the header size is | |
244 * reasonable. | |
245 */ | |
246 if ((mpg123_info->filesize && hdrsize > mpg123_info->filesize) || | |
247 (!mpg123_info->filesize && hdrsize > 1000000)) | |
248 return FALSE; | |
249 | |
250 if (mpg123_cfg.disable_id3v2) { | |
251 guint8 *tmp = g_malloc(hdrsize); | |
252 gboolean ret; | |
701
d539e5c5f730
[svn] Fixes of the remaining GCC 4.1 warnings from external contributor Diego "Flameeyes" Petteno (Gentoo).
chainsaw
parents:
170
diff
changeset
|
253 ret = ((gsize)fullread(filept, tmp, hdrsize) == hdrsize); |
61 | 254 g_free(tmp); |
255 return ret; | |
256 } | |
257 | |
258 id3buf = g_malloc(hdrsize + ID3_TAGHDR_SIZE + 3); | |
259 memcpy(id3buf, "ID3", 3); | |
260 memcpy(id3buf + 3, buf, ID3_TAGHDR_SIZE); | |
261 | |
262 /* | |
263 * Read ID3tag body. | |
264 */ | |
701
d539e5c5f730
[svn] Fixes of the remaining GCC 4.1 warnings from external contributor Diego "Flameeyes" Petteno (Gentoo).
chainsaw
parents:
170
diff
changeset
|
265 if ((gsize)fullread(filept, id3buf + ID3_TAGHDR_SIZE + 3, hdrsize) != hdrsize) { |
61 | 266 g_free(id3buf); |
267 return FALSE; | |
268 } | |
269 | |
270 /* | |
271 * Get info from tag. | |
272 */ | |
273 if ((id3d = id3_open_mem(id3buf, 0)) != NULL) { | |
274 mpg123_get_id3v2(id3d, &tag); | |
275 if (!mpg123_info->first_frame) { | |
276 char *songname = mpg123_title; | |
277 mpg123_title = mpg123_format_song_title(&tag, mpg123_filename); | |
278 mpg123_ip.set_info(mpg123_title, mpg123_length, | |
279 mpg123_bitrate * 1000, | |
280 mpg123_frequency, mpg123_stereo); | |
281 if (songname) | |
282 g_free(songname); | |
283 } | |
284 else { | |
285 mpg123_title = mpg123_format_song_title(&tag, mpg123_filename); | |
286 } | |
287 id3_close(id3d); | |
288 } | |
289 g_free(id3buf); | |
290 | |
291 return TRUE; | |
292 } | |
293 | |
294 int | |
295 mpg123_head_check(unsigned long head) | |
296 { | |
297 if ((head & 0xffe00000) != 0xffe00000) | |
298 return FALSE; | |
299 if (!((head >> 17) & 3)) | |
300 return FALSE; | |
301 if (((head >> 12) & 0xf) == 0xf) | |
302 return FALSE; | |
303 if (!((head >> 12) & 0xf)) | |
304 return FALSE; | |
305 if (((head >> 10) & 0x3) == 0x3) | |
306 return FALSE; | |
307 if (((head >> 19) & 1) == 1 && | |
308 ((head >> 17) & 3) == 3 && ((head >> 16) & 1) == 1) | |
309 return FALSE; | |
310 if ((head & 0xffff0000) == 0xfffe0000) | |
311 return FALSE; | |
312 | |
313 return TRUE; | |
314 } | |
315 | |
316 /***************************************************************** | |
317 * read next frame | |
318 */ | |
319 int | |
320 mpg123_read_frame(struct frame *fr) | |
321 { | |
322 unsigned long newhead; | |
323 | |
324 fsizeold = fr->framesize; /* for Layer3 */ | |
325 | |
326 if (!stream_head_read(&newhead)) | |
327 return FALSE; | |
328 | |
329 if (!mpg123_head_check(newhead) || !mpg123_decode_header(fr, newhead)) { | |
330 int try = 0; | |
331 | |
332 do { | |
333 try++; | |
334 if ((newhead & 0xffffff00) == | |
335 ('I' << 24) + ('D' << 16) + ('3' << 8)) { | |
336 read_id3v2_tag(newhead); | |
337 if (!stream_head_read(&newhead)) | |
338 return FALSE; | |
339 } | |
340 else if (!stream_head_shift(&newhead)) | |
341 return 0; | |
342 | |
343 } | |
344 while ((!mpg123_head_check(newhead) || | |
345 !mpg123_decode_header(fr, newhead)) && try < (256 * 1024)); | |
346 if (try >= (256 * 1024)) | |
347 return FALSE; | |
348 | |
349 mpg123_info->filesize -= try; | |
350 } | |
351 /* flip/init buffer for Layer 3 */ | |
352 bsbufold = bsbuf; | |
353 bsbuf = bsspace[bsnum] + 512; | |
354 bsnum = (bsnum + 1) & 1; | |
355 | |
356 if (!stream_mpg123_read_frame_body(bsbuf, fr->framesize)) | |
357 return 0; | |
358 | |
359 bsi.bitindex = 0; | |
360 bsi.wordpointer = (unsigned char *) bsbuf; | |
361 | |
362 | |
363 return 1; | |
364 | |
365 } | |
366 | |
367 /* | |
368 * the code a header and write the information | |
369 * into the frame structure | |
370 */ | |
371 int | |
372 mpg123_decode_header(struct frame *fr, unsigned long newhead) | |
373 { | |
374 if (newhead & (1 << 20)) { | |
375 fr->lsf = (newhead & (1 << 19)) ? 0x0 : 0x1; | |
376 fr->mpeg25 = 0; | |
377 } | |
378 else { | |
379 fr->lsf = 1; | |
380 fr->mpeg25 = 1; | |
381 } | |
382 fr->lay = 4 - ((newhead >> 17) & 3); | |
383 if (fr->mpeg25) { | |
384 fr->sampling_frequency = 6 + ((newhead >> 10) & 0x3); | |
385 } | |
386 else | |
387 fr->sampling_frequency = ((newhead >> 10) & 0x3) + (fr->lsf * 3); | |
388 fr->error_protection = ((newhead >> 16) & 0x1) ^ 0x1; | |
389 | |
390 fr->bitrate_index = ((newhead >> 12) & 0xf); | |
391 fr->padding = ((newhead >> 9) & 0x1); | |
392 fr->extension = ((newhead >> 8) & 0x1); | |
393 fr->mode = ((newhead >> 6) & 0x3); | |
394 fr->mode_ext = ((newhead >> 4) & 0x3); | |
395 fr->copyright = ((newhead >> 3) & 0x1); | |
396 fr->original = ((newhead >> 2) & 0x1); | |
397 fr->emphasis = newhead & 0x3; | |
398 | |
399 fr->stereo = (fr->mode == MPG_MD_MONO) ? 1 : 2; | |
400 | |
401 ssize = 0; | |
402 | |
403 if (!fr->bitrate_index) | |
404 return (0); | |
405 | |
406 switch (fr->lay) { | |
407 case 1: | |
408 fr->do_layer = mpg123_do_layer1; | |
409 /* inits also shared tables with layer1 */ | |
410 mpg123_init_layer2(fr->synth_type == SYNTH_MMX); | |
411 fr->framesize = | |
412 (long) tabsel_123[fr->lsf][0][fr->bitrate_index] * 12000; | |
413 fr->framesize /= mpg123_freqs[fr->sampling_frequency]; | |
414 fr->framesize = ((fr->framesize + fr->padding) << 2) - 4; | |
415 break; | |
416 case 2: | |
417 fr->do_layer = mpg123_do_layer2; | |
418 /* inits also shared tables with layer1 */ | |
419 mpg123_init_layer2(fr->synth_type == SYNTH_MMX); | |
420 fr->framesize = | |
421 (long) tabsel_123[fr->lsf][1][fr->bitrate_index] * 144000; | |
422 fr->framesize /= mpg123_freqs[fr->sampling_frequency]; | |
423 fr->framesize += fr->padding - 4; | |
424 break; | |
425 case 3: | |
426 fr->do_layer = mpg123_do_layer3; | |
427 if (fr->lsf) | |
428 ssize = (fr->stereo == 1) ? 9 : 17; | |
429 else | |
430 ssize = (fr->stereo == 1) ? 17 : 32; | |
431 if (fr->error_protection) | |
432 ssize += 2; | |
433 fr->framesize = | |
434 (long) tabsel_123[fr->lsf][2][fr->bitrate_index] * 144000; | |
435 fr->framesize /= mpg123_freqs[fr->sampling_frequency] << (fr->lsf); | |
436 fr->framesize = fr->framesize + fr->padding - 4; | |
437 break; | |
438 default: | |
439 return (0); | |
440 } | |
441 if (fr->framesize > MAXFRAMESIZE) | |
442 return 0; | |
443 return 1; | |
444 } | |
445 | |
446 void | |
447 mpg123_open_stream(char *bs_filenam, int fd) | |
448 { | |
449 filept_opened = 1; | |
450 if (!strncasecmp(bs_filenam, "http://", 7)) { | |
451 filept = NULL; | |
452 mpg123_http_open(bs_filenam); | |
453 mpg123_info->filesize = 0; | |
454 mpg123_info->network_stream = TRUE; | |
455 } | |
456 else { | |
457 if ((filept = vfs_fopen(bs_filenam, "rb")) == NULL || | |
458 stream_init() == -1) | |
459 mpg123_info->eof = TRUE; | |
460 } | |
461 | |
462 } | |
463 | |
464 void | |
465 mpg123_set_pointer(long backstep) | |
466 { | |
467 bsi.wordpointer = bsbuf + ssize - backstep; | |
468 if (backstep) | |
469 memcpy(bsi.wordpointer, bsbufold + fsizeold - backstep, backstep); | |
470 bsi.bitindex = 0; | |
471 } | |
472 | |
473 double | |
474 mpg123_compute_bpf(struct frame *fr) | |
475 { | |
476 double bpf; | |
477 | |
478 switch (fr->lay) { | |
479 case 1: | |
480 bpf = tabsel_123[fr->lsf][0][fr->bitrate_index]; | |
481 bpf *= 12000.0 * 4.0; | |
482 bpf /= mpg123_freqs[fr->sampling_frequency] << (fr->lsf); | |
483 break; | |
484 case 2: | |
485 case 3: | |
486 bpf = tabsel_123[fr->lsf][fr->lay - 1][fr->bitrate_index]; | |
487 bpf *= 144000; | |
488 bpf /= mpg123_freqs[fr->sampling_frequency] << (fr->lsf); | |
489 break; | |
490 default: | |
491 bpf = 1.0; | |
492 } | |
493 | |
494 return bpf; | |
495 } | |
496 | |
497 int | |
498 mpg123_calc_numframes(struct frame *fr) | |
499 { | |
500 return (int) (mpg123_info->filesize / mpg123_compute_bpf(fr)); | |
501 } | |
502 | |
503 double | |
504 mpg123_relative_pos(void) | |
505 { | |
506 if (!filept || !mpg123_info->filesize) | |
507 return 0; | |
508 return ((double) stream_tell()) / mpg123_info->filesize; | |
509 } |