Rev 1905 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1905 | Rev 3960 | ||
---|---|---|---|
Line 1... | Line 1... | ||
1 | /* |
1 | /* |
2 | frame: Heap of routines dealing with the core mpg123 data structure. |
2 | frame: Heap of routines dealing with the core mpg123 data structure. |
Line 3... | Line 3... | ||
3 | 3 | ||
4 | copyright 2008-9 by the mpg123 project - free software under the terms of the LGPL 2.1 |
4 | copyright 2008-2010 by the mpg123 project - free software under the terms of the LGPL 2.1 |
5 | see COPYING and AUTHORS files in distribution or http://mpg123.org |
5 | see COPYING and AUTHORS files in distribution or http://mpg123.org |
6 | initially written by Thomas Orgis |
6 | initially written by Thomas Orgis |
Line 7... | Line 7... | ||
7 | */ |
7 | */ |
Line 12... | Line 12... | ||
12 | 12 | ||
Line 13... | Line 13... | ||
13 | static void frame_fixed_reset(mpg123_handle *fr); |
13 | static void frame_fixed_reset(mpg123_handle *fr); |
14 | 14 | ||
- | 15 | /* that's doubled in decode_ntom.c */ |
|
15 | /* that's doubled in decode_ntom.c */ |
16 | #define NTOM_MUL (32768) |
- | 17 | ||
- | 18 | #define aligned_pointer(p, type, alignment) align_the_pointer(p, alignment) |
|
- | 19 | static void *align_the_pointer(void *base, unsigned int alignment) |
|
- | 20 | { |
|
- | 21 | /* |
|
- | 22 | Work in unsigned integer realm, explicitly. |
|
- | 23 | Tricking the compiler into integer operations like % by invoking base-NULL is dangerous: It results into ptrdiff_t, which gets negative on big addresses. Big screw up, that. |
|
- | 24 | I try to do it "properly" here: Casting only to uintptr_t and no artihmethic with void*. |
|
16 | #define NTOM_MUL (32768) |
25 | */ |
- | 26 | uintptr_t baseval = (uintptr_t)(char*)base; |
|
- | 27 | uintptr_t aoff = baseval % alignment; |
|
- | 28 | ||
- | 29 | debug3("align_the_pointer: pointer %p is off by %u from %u", |
|
17 | #define aligned_pointer(p,type,alignment) \ |
30 | base, (unsigned int)aoff, alignment); |
18 | (((char*)(p)-(char*)NULL) % (alignment)) \ |
31 | |
- | 32 | if(aoff) return (char*)base+alignment-aoff; |
|
- | 33 | else return base; |
|
19 | ? (type*)((char*)(p) + (alignment) - (((char*)(p)-(char*)NULL) % (alignment))) \ |
34 | } |
20 | : (type*)(p) |
35 | |
21 | void frame_default_pars(mpg123_pars *mp) |
36 | static void frame_default_pars(mpg123_pars *mp) |
22 | { |
- | |
23 | mp->outscale = 1.0; |
- | |
24 | #ifdef GAPLESS |
- | |
25 | mp->flags = MPG123_GAPLESS; |
37 | { |
- | 38 | mp->outscale = 1.0; |
|
- | 39 | mp->flags = 0; |
|
26 | #else |
40 | #ifdef GAPLESS |
- | 41 | mp->flags |= MPG123_GAPLESS; |
|
27 | mp->flags = 0; |
42 | #endif |
28 | #endif |
43 | mp->flags |= MPG123_AUTO_RESAMPLE; |
29 | #ifndef NO_NTOM |
44 | #ifndef NO_NTOM |
30 | mp->force_rate = 0; |
45 | mp->force_rate = 0; |
31 | #endif |
46 | #endif |
Line 35... | Line 50... | ||
35 | mp->doublespeed = 0; |
50 | mp->doublespeed = 0; |
36 | mp->verbose = 0; |
51 | mp->verbose = 0; |
37 | #ifndef NO_ICY |
52 | #ifndef NO_ICY |
38 | mp->icy_interval = 0; |
53 | mp->icy_interval = 0; |
39 | #endif |
54 | #endif |
40 | #ifndef WIN32 |
- | |
41 | mp->timeout = 0; |
55 | mp->timeout = 0; |
42 | #endif |
- | |
43 | mp->resync_limit = 1024; |
56 | mp->resync_limit = 1024; |
44 | #ifdef FRAME_INDEX |
57 | #ifdef FRAME_INDEX |
45 | mp->index_size = INDEX_SIZE; |
58 | mp->index_size = INDEX_SIZE; |
46 | #endif |
59 | #endif |
47 | mp->preframes = 4; /* That's good for layer 3 ISO compliance bitstream. */ |
60 | mp->preframes = 4; /* That's good for layer 3 ISO compliance bitstream. */ |
48 | mpg123_fmt_all(mp); |
61 | mpg123_fmt_all(mp); |
- | 62 | /* Default of keeping some 4K buffers at hand, should cover the "usual" use case (using 16K pipe buffers as role model). */ |
|
- | 63 | #ifndef NO_FEEDER |
|
- | 64 | mp->feedpool = 5; |
|
- | 65 | mp->feedbuffer = 4096; |
|
- | 66 | #endif |
|
49 | } |
67 | } |
Line 50... | Line 68... | ||
50 | 68 | ||
51 | void frame_init(mpg123_handle *fr) |
69 | void frame_init(mpg123_handle *fr) |
52 | { |
70 | { |
53 | frame_init_par(fr, NULL); |
71 | frame_init_par(fr, NULL); |
Line 54... | Line 72... | ||
54 | } |
72 | } |
55 | 73 | ||
56 | void frame_init_par(mpg123_handle *fr, mpg123_pars *mp) |
74 | void frame_init_par(mpg123_handle *fr, mpg123_pars *mp) |
57 | { |
75 | { |
- | 76 | fr->own_buffer = TRUE; |
|
- | 77 | fr->buffer.data = NULL; |
|
- | 78 | fr->buffer.rdata = NULL; |
|
58 | fr->own_buffer = FALSE; |
79 | fr->buffer.fill = 0; |
59 | fr->buffer.data = NULL; |
80 | fr->buffer.size = 0; |
60 | fr->rawbuffs = NULL; |
81 | fr->rawbuffs = NULL; |
61 | fr->rawbuffss = 0; |
82 | fr->rawbuffss = 0; |
62 | fr->rawdecwin = NULL; |
83 | fr->rawdecwin = NULL; |
63 | fr->rawdecwins = 0; |
84 | fr->rawdecwins = 0; |
64 | #ifndef NO_8BIT |
85 | #ifndef NO_8BIT |
65 | fr->conv16to8_buf = NULL; |
86 | fr->conv16to8_buf = NULL; |
66 | #endif |
87 | #endif |
67 | #ifdef OPT_DITHER |
88 | #ifdef OPT_DITHER |
- | 89 | fr->dithernoise = NULL; |
|
68 | fr->dithernoise = NULL; |
90 | #endif |
69 | #endif |
91 | fr->layerscratch = NULL; |
70 | fr->xing_toc = NULL; |
92 | fr->xing_toc = NULL; |
71 | fr->cpu_opts.type = defdec(); |
93 | fr->cpu_opts.type = defdec(); |
72 | fr->cpu_opts.class = decclass(fr->cpu_opts.type); |
94 | fr->cpu_opts.class = decclass(fr->cpu_opts.type); |
Line 84... | Line 106... | ||
84 | /* frame_buffers is missing... that one needs cpu opt setting! */ |
106 | /* frame_buffers is missing... that one needs cpu opt setting! */ |
85 | /* after these... frame_reset is needed before starting full decode */ |
107 | /* after these... frame_reset is needed before starting full decode */ |
86 | invalidate_format(&fr->af); |
108 | invalidate_format(&fr->af); |
87 | fr->rdat.r_read = NULL; |
109 | fr->rdat.r_read = NULL; |
88 | fr->rdat.r_lseek = NULL; |
110 | fr->rdat.r_lseek = NULL; |
- | 111 | fr->rdat.iohandle = NULL; |
|
- | 112 | fr->rdat.r_read_handle = NULL; |
|
- | 113 | fr->rdat.r_lseek_handle = NULL; |
|
- | 114 | fr->rdat.cleanup_handle = NULL; |
|
- | 115 | fr->wrapperdata = NULL; |
|
- | 116 | fr->wrapperclean = NULL; |
|
89 | fr->decoder_change = 1; |
117 | fr->decoder_change = 1; |
90 | fr->err = MPG123_OK; |
118 | fr->err = MPG123_OK; |
91 | if(mp == NULL) frame_default_pars(&fr->p); |
119 | if(mp == NULL) frame_default_pars(&fr->p); |
92 | else memcpy(&fr->p, mp, sizeof(struct mpg123_pars_struct)); |
120 | else memcpy(&fr->p, mp, sizeof(struct mpg123_pars_struct)); |
Line -... | Line 121... | ||
- | 121 | ||
- | 122 | #ifndef NO_FEEDER |
|
- | 123 | bc_prepare(&fr->rdat.buffer, fr->p.feedpool, fr->p.feedbuffer); |
|
- | 124 | #endif |
|
93 | 125 | ||
94 | fr->down_sample = 0; /* Initialize to silence harmless errors when debugging. */ |
126 | fr->down_sample = 0; /* Initialize to silence harmless errors when debugging. */ |
95 | frame_fixed_reset(fr); /* Reset only the fixed data, dynamic buffers are not there yet! */ |
127 | frame_fixed_reset(fr); /* Reset only the fixed data, dynamic buffers are not there yet! */ |
96 | fr->synth = NULL; |
128 | fr->synth = NULL; |
97 | fr->synth_mono = NULL; |
129 | fr->synth_mono = NULL; |
Line 141... | Line 173... | ||
141 | return MPG123_OK; |
173 | return MPG123_OK; |
142 | } |
174 | } |
Line 143... | Line 175... | ||
143 | 175 | ||
144 | int frame_outbuffer(mpg123_handle *fr) |
176 | int frame_outbuffer(mpg123_handle *fr) |
145 | { |
177 | { |
146 | size_t size = mpg123_safe_buffer()*AUDIOBUFSIZE; |
178 | size_t size = fr->outblock; |
147 | if(!fr->own_buffer) fr->buffer.data = NULL; |
- | |
148 | if(fr->buffer.data != NULL && fr->buffer.size != size) |
179 | if(!fr->own_buffer) |
- | 180 | { |
|
- | 181 | if(fr->buffer.size < size) |
|
- | 182 | { |
|
- | 183 | fr->err = MPG123_BAD_BUFFER; |
|
- | 184 | if(NOQUIET) error2("have external buffer of size %"SIZE_P", need %"SIZE_P, (size_p)fr->buffer.size, size); |
|
- | 185 | ||
- | 186 | return MPG123_ERR; |
|
- | 187 | } |
|
- | 188 | } |
|
- | 189 | ||
- | 190 | debug1("need frame buffer of %"SIZE_P, (size_p)size); |
|
- | 191 | if(fr->buffer.rdata != NULL && fr->buffer.size != size) |
|
149 | { |
192 | { |
150 | free(fr->buffer.data); |
193 | free(fr->buffer.rdata); |
151 | fr->buffer.data = NULL; |
194 | fr->buffer.rdata = NULL; |
152 | } |
195 | } |
- | 196 | fr->buffer.size = size; |
|
- | 197 | fr->buffer.data = NULL; |
|
153 | fr->buffer.size = size; |
198 | /* be generous: use 16 byte alignment */ |
154 | if(fr->buffer.data == NULL) fr->buffer.data = (unsigned char*) malloc(fr->buffer.size); |
199 | if(fr->buffer.rdata == NULL) fr->buffer.rdata = (unsigned char*) malloc(fr->buffer.size+15); |
155 | if(fr->buffer.data == NULL) |
200 | if(fr->buffer.rdata == NULL) |
156 | { |
201 | { |
157 | fr->err = MPG123_OUT_OF_MEM; |
202 | fr->err = MPG123_OUT_OF_MEM; |
158 | return -1; |
203 | return MPG123_ERR; |
- | 204 | } |
|
159 | } |
205 | fr->buffer.data = aligned_pointer(fr->buffer.rdata, unsigned char*, 16); |
160 | fr->own_buffer = TRUE; |
206 | fr->own_buffer = TRUE; |
161 | fr->buffer.fill = 0; |
207 | fr->buffer.fill = 0; |
162 | return 0; |
208 | return MPG123_OK; |
Line 163... | Line 209... | ||
163 | } |
209 | } |
164 | 210 | ||
- | 211 | int attribute_align_arg mpg123_replace_buffer(mpg123_handle *mh, unsigned char *data, size_t size) |
|
165 | int attribute_align_arg mpg123_replace_buffer(mpg123_handle *mh, unsigned char *data, size_t size) |
212 | { |
- | 213 | debug2("replace buffer with %p size %"SIZE_P, data, (size_p)size); |
|
166 | { |
214 | /* Will accept any size, the error comes later... */ |
167 | if(data == NULL || size < mpg123_safe_buffer()) |
215 | if(data == NULL) |
168 | { |
216 | { |
169 | mh->err = MPG123_BAD_BUFFER; |
217 | mh->err = MPG123_BAD_BUFFER; |
170 | return MPG123_ERR; |
218 | return MPG123_ERR; |
171 | } |
219 | } |
- | 220 | if(mh->buffer.rdata != NULL) free(mh->buffer.rdata); |
|
172 | if(mh->own_buffer && mh->buffer.data != NULL) free(mh->buffer.data); |
221 | mh->own_buffer = FALSE; |
173 | mh->own_buffer = FALSE; |
222 | mh->buffer.rdata = NULL; |
174 | mh->buffer.data = data; |
223 | mh->buffer.data = data; |
175 | mh->buffer.size = size; |
224 | mh->buffer.size = size; |
176 | mh->buffer.fill = 0; |
225 | mh->buffer.fill = 0; |
Line 291... | Line 340... | ||
291 | #ifdef OPT_MULTI |
340 | #ifdef OPT_MULTI |
292 | } |
341 | } |
293 | #endif |
342 | #endif |
294 | #endif |
343 | #endif |
295 | #if defined(OPT_ALTIVEC) || defined(OPT_ARM) |
344 | #if defined(OPT_ALTIVEC) || defined(OPT_ARM) |
- | 345 | /* sizeof(real) >= 4 ... yes, it could be 8, for example. |
|
296 | if(decwin_size < (512+32)*4) decwin_size = (512+32)*4; |
346 | We got it intialized to at least (512+32)*sizeof(real).*/ |
297 | decwin_size += 512*4; |
347 | decwin_size += 512*sizeof(real); |
298 | #endif |
348 | #endif |
299 | /* Hm, that's basically realloc() ... */ |
349 | /* Hm, that's basically realloc() ... */ |
300 | if(fr->rawdecwin != NULL && fr->rawdecwins != decwin_size) |
350 | if(fr->rawdecwin != NULL && fr->rawdecwins != decwin_size) |
301 | { |
351 | { |
302 | free(fr->rawdecwin); |
352 | free(fr->rawdecwin); |
Line 325... | Line 375... | ||
325 | } |
375 | } |
326 | else debug("no decwins/decwin_mmx for that class"); |
376 | else debug("no decwins/decwin_mmx for that class"); |
327 | #endif |
377 | #endif |
328 | #endif |
378 | #endif |
329 | } |
379 | } |
- | 380 | ||
- | 381 | /* Layer scratch buffers are of compile-time fixed size, so allocate only once. */ |
|
- | 382 | if(fr->layerscratch == NULL) |
|
- | 383 | { |
|
- | 384 | /* Allocate specific layer1/2/3 buffers, so that we know they'll work for SSE. */ |
|
- | 385 | size_t scratchsize = 0; |
|
- | 386 | real *scratcher; |
|
- | 387 | #ifndef NO_LAYER1 |
|
- | 388 | scratchsize += sizeof(real) * 2 * SBLIMIT; |
|
- | 389 | #endif |
|
- | 390 | #ifndef NO_LAYER2 |
|
- | 391 | scratchsize += sizeof(real) * 2 * 4 * SBLIMIT; |
|
- | 392 | #endif |
|
- | 393 | #ifndef NO_LAYER3 |
|
- | 394 | scratchsize += sizeof(real) * 2 * SBLIMIT * SSLIMIT; /* hybrid_in */ |
|
- | 395 | scratchsize += sizeof(real) * 2 * SSLIMIT * SBLIMIT; /* hybrid_out */ |
|
- | 396 | #endif |
|
- | 397 | /* |
|
- | 398 | Now figure out correct alignment: |
|
- | 399 | We need 16 byte minimum, smallest unit of the blocks is 2*SBLIMIT*sizeof(real), which is 64*4=256. Let's do 64bytes as heuristic for cache line (as proven useful in buffs above). |
|
- | 400 | */ |
|
- | 401 | fr->layerscratch = malloc(scratchsize+63); |
|
- | 402 | if(fr->layerscratch == NULL) return -1; |
|
- | 403 | ||
- | 404 | /* Get aligned part of the memory, then divide it up. */ |
|
- | 405 | scratcher = aligned_pointer(fr->layerscratch,real,64); |
|
- | 406 | /* Those funky pointer casts silence compilers... |
|
- | 407 | One might change the code at hand to really just use 1D arrays, but in practice, that would not make a (positive) difference. */ |
|
- | 408 | #ifndef NO_LAYER1 |
|
- | 409 | fr->layer1.fraction = (real(*)[SBLIMIT])scratcher; |
|
- | 410 | scratcher += 2 * SBLIMIT; |
|
- | 411 | #endif |
|
- | 412 | #ifndef NO_LAYER2 |
|
- | 413 | fr->layer2.fraction = (real(*)[4][SBLIMIT])scratcher; |
|
- | 414 | scratcher += 2 * 4 * SBLIMIT; |
|
- | 415 | #endif |
|
- | 416 | #ifndef NO_LAYER3 |
|
- | 417 | fr->layer3.hybrid_in = (real(*)[SBLIMIT][SSLIMIT])scratcher; |
|
- | 418 | scratcher += 2 * SBLIMIT * SSLIMIT; |
|
- | 419 | fr->layer3.hybrid_out = (real(*)[SSLIMIT][SBLIMIT])scratcher; |
|
- | 420 | scratcher += 2 * SSLIMIT * SBLIMIT; |
|
- | 421 | #endif |
|
- | 422 | /* Note: These buffers don't need resetting here. */ |
|
- | 423 | } |
|
- | 424 | ||
330 | /* Only reset the buffers we created just now. */ |
425 | /* Only reset the buffers we created just now. */ |
331 | frame_decode_buffers_reset(fr); |
426 | frame_decode_buffers_reset(fr); |
Line 332... | Line 427... | ||
332 | 427 | ||
333 | debug1("frame %p buffer done", (void*)fr); |
428 | debug1("frame %p buffer done", (void*)fr); |
Line 339... | Line 434... | ||
339 | fr->buffer.fill = 0; /* hm, reset buffer fill... did we do a flush? */ |
434 | fr->buffer.fill = 0; /* hm, reset buffer fill... did we do a flush? */ |
340 | fr->bsnum = 0; |
435 | fr->bsnum = 0; |
341 | /* Wondering: could it be actually _wanted_ to retain buffer contents over different files? (special gapless / cut stuff) */ |
436 | /* Wondering: could it be actually _wanted_ to retain buffer contents over different files? (special gapless / cut stuff) */ |
342 | fr->bsbuf = fr->bsspace[1]; |
437 | fr->bsbuf = fr->bsspace[1]; |
343 | fr->bsbufold = fr->bsbuf; |
438 | fr->bsbufold = fr->bsbuf; |
344 | fr->bitreservoir = 0; /* Not entirely sure if this is the right place for that counter. */ |
439 | fr->bitreservoir = 0; |
345 | frame_decode_buffers_reset(fr); |
440 | frame_decode_buffers_reset(fr); |
346 | memset(fr->bsspace, 0, 2*(MAXFRAMESIZE+512)); |
441 | memset(fr->bsspace, 0, 2*(MAXFRAMESIZE+512)); |
347 | memset(fr->ssave, 0, 34); |
442 | memset(fr->ssave, 0, 34); |
348 | fr->hybrid_blc[0] = fr->hybrid_blc[1] = 0; |
443 | fr->hybrid_blc[0] = fr->hybrid_blc[1] = 0; |
349 | memset(fr->hybrid_block, 0, sizeof(real)*2*2*SBLIMIT*SSLIMIT); |
444 | memset(fr->hybrid_block, 0, sizeof(real)*2*2*SBLIMIT*SSLIMIT); |
350 | return 0; |
445 | return 0; |
351 | } |
446 | } |
Line 352... | Line 447... | ||
352 | 447 | ||
353 | void frame_icy_reset(mpg123_handle* fr) |
448 | static void frame_icy_reset(mpg123_handle* fr) |
354 | { |
449 | { |
355 | #ifndef NO_ICY |
450 | #ifndef NO_ICY |
356 | if(fr->icy.data != NULL) free(fr->icy.data); |
451 | if(fr->icy.data != NULL) free(fr->icy.data); |
357 | fr->icy.data = NULL; |
452 | fr->icy.data = NULL; |
358 | fr->icy.interval = 0; |
453 | fr->icy.interval = 0; |
359 | fr->icy.next = 0; |
454 | fr->icy.next = 0; |
360 | #endif |
455 | #endif |
Line 361... | Line 456... | ||
361 | } |
456 | } |
362 | 457 | ||
363 | void frame_free_toc(mpg123_handle *fr) |
458 | static void frame_free_toc(mpg123_handle *fr) |
364 | { |
459 | { |
Line 365... | Line 460... | ||
365 | if(fr->xing_toc != NULL){ free(fr->xing_toc); fr->xing_toc = NULL; } |
460 | if(fr->xing_toc != NULL){ free(fr->xing_toc); fr->xing_toc = NULL; } |
Line 405... | Line 500... | ||
405 | frame_icy_reset(fr); |
500 | frame_icy_reset(fr); |
406 | open_bad(fr); |
501 | open_bad(fr); |
407 | fr->to_decode = FALSE; |
502 | fr->to_decode = FALSE; |
408 | fr->to_ignore = FALSE; |
503 | fr->to_ignore = FALSE; |
409 | fr->metaflags = 0; |
504 | fr->metaflags = 0; |
410 | fr->outblock = mpg123_safe_buffer(); |
505 | fr->outblock = 0; /* This will be set before decoding! */ |
411 | fr->num = -1; |
506 | fr->num = -1; |
- | 507 | fr->input_offset = -1; |
|
412 | fr->playnum = -1; |
508 | fr->playnum = -1; |
413 | fr->accurate = TRUE; |
509 | fr->state_flags = FRAME_ACCURATE; |
414 | fr->silent_resync = 0; |
510 | fr->silent_resync = 0; |
415 | fr->audio_start = 0; |
511 | fr->audio_start = 0; |
416 | fr->clip = 0; |
512 | fr->clip = 0; |
417 | fr->oldhead = 0; |
513 | fr->oldhead = 0; |
418 | fr->firsthead = 0; |
514 | fr->firsthead = 0; |
Line 436... | Line 532... | ||
436 | fr->ignoreframe = fr->firstframe-fr->p.preframes; |
532 | fr->ignoreframe = fr->firstframe-fr->p.preframes; |
437 | fr->lastframe = -1; |
533 | fr->lastframe = -1; |
438 | fr->fresh = 1; |
534 | fr->fresh = 1; |
439 | fr->new_format = 0; |
535 | fr->new_format = 0; |
440 | #ifdef GAPLESS |
536 | #ifdef GAPLESS |
441 | frame_gapless_init(fr,0,0); |
537 | frame_gapless_init(fr,-1,0,0); |
442 | fr->lastoff = 0; |
538 | fr->lastoff = 0; |
443 | fr->firstoff = 0; |
539 | fr->firstoff = 0; |
444 | #endif |
540 | #endif |
445 | #ifdef OPT_I486 |
541 | #ifdef OPT_I486 |
446 | fr->i486bo[0] = fr->i486bo[1] = FIR_SIZE-1; |
542 | fr->i486bo[0] = fr->i486bo[1] = FIR_SIZE-1; |
Line 459... | Line 555... | ||
459 | fr->halfphase = 0; /* here or indeed only on first-time init? */ |
555 | fr->halfphase = 0; /* here or indeed only on first-time init? */ |
460 | fr->error_protection = 0; |
556 | fr->error_protection = 0; |
461 | fr->freeformat_framesize = -1; |
557 | fr->freeformat_framesize = -1; |
462 | } |
558 | } |
Line 463... | Line 559... | ||
463 | 559 | ||
464 | void frame_free_buffers(mpg123_handle *fr) |
560 | static void frame_free_buffers(mpg123_handle *fr) |
465 | { |
561 | { |
466 | if(fr->rawbuffs != NULL) free(fr->rawbuffs); |
562 | if(fr->rawbuffs != NULL) free(fr->rawbuffs); |
467 | fr->rawbuffs = NULL; |
563 | fr->rawbuffs = NULL; |
468 | fr->rawbuffss = 0; |
564 | fr->rawbuffss = 0; |
Line 471... | Line 567... | ||
471 | fr->rawdecwins = 0; |
567 | fr->rawdecwins = 0; |
472 | #ifndef NO_8BIT |
568 | #ifndef NO_8BIT |
473 | if(fr->conv16to8_buf != NULL) free(fr->conv16to8_buf); |
569 | if(fr->conv16to8_buf != NULL) free(fr->conv16to8_buf); |
474 | fr->conv16to8_buf = NULL; |
570 | fr->conv16to8_buf = NULL; |
475 | #endif |
571 | #endif |
- | 572 | if(fr->layerscratch != NULL) free(fr->layerscratch); |
|
476 | } |
573 | } |
Line 477... | Line 574... | ||
477 | 574 | ||
478 | void frame_exit(mpg123_handle *fr) |
575 | void frame_exit(mpg123_handle *fr) |
479 | { |
576 | { |
480 | if(fr->own_buffer && fr->buffer.data != NULL) |
577 | if(fr->buffer.rdata != NULL) |
481 | { |
578 | { |
482 | debug1("freeing buffer at %p", (void*)fr->buffer.data); |
579 | debug1("freeing buffer at %p", (void*)fr->buffer.rdata); |
483 | free(fr->buffer.data); |
580 | free(fr->buffer.rdata); |
484 | } |
581 | } |
485 | fr->buffer.data = NULL; |
582 | fr->buffer.rdata = NULL; |
486 | frame_free_buffers(fr); |
583 | frame_free_buffers(fr); |
487 | frame_free_toc(fr); |
584 | frame_free_toc(fr); |
488 | #ifdef FRAME_INDEX |
585 | #ifdef FRAME_INDEX |
489 | fi_exit(&fr->index); |
586 | fi_exit(&fr->index); |
Line 495... | Line 592... | ||
495 | fr->dithernoise = NULL; |
592 | fr->dithernoise = NULL; |
496 | } |
593 | } |
497 | #endif |
594 | #endif |
498 | exit_id3(fr); |
595 | exit_id3(fr); |
499 | clear_icy(&fr->icy); |
596 | clear_icy(&fr->icy); |
- | 597 | /* Clean up possible mess from LFS wrapper. */ |
|
- | 598 | if(fr->wrapperclean != NULL) |
|
- | 599 | { |
|
- | 600 | fr->wrapperclean(fr->wrapperdata); |
|
- | 601 | fr->wrapperdata = NULL; |
|
- | 602 | } |
|
- | 603 | #ifndef NO_FEEDER |
|
- | 604 | bc_cleanup(&fr->rdat.buffer); |
|
- | 605 | #endif |
|
500 | } |
606 | } |
Line 501... | Line 607... | ||
501 | 607 | ||
502 | int attribute_align_arg mpg123_info(mpg123_handle *mh, struct mpg123_frameinfo *mi) |
608 | int attribute_align_arg mpg123_info(mpg123_handle *mh, struct mpg123_frameinfo *mi) |
503 | { |
609 | { |
Line 530... | Line 636... | ||
530 | mi->abr_rate = mh->abr_rate; |
636 | mi->abr_rate = mh->abr_rate; |
531 | mi->vbr = mh->vbr; |
637 | mi->vbr = mh->vbr; |
532 | return MPG123_OK; |
638 | return MPG123_OK; |
533 | } |
639 | } |
Line -... | Line 640... | ||
- | 640 | ||
- | 641 | int attribute_align_arg mpg123_framedata(mpg123_handle *mh, unsigned long *header, unsigned char **bodydata, size_t *bodybytes) |
|
- | 642 | { |
|
- | 643 | if(mh == NULL) return MPG123_ERR; |
|
- | 644 | if(!mh->to_decode) return MPG123_ERR; |
|
- | 645 | ||
- | 646 | if(header != NULL) *header = mh->oldhead; |
|
- | 647 | if(bodydata != NULL) *bodydata = mh->bsbuf; |
|
- | 648 | if(bodybytes != NULL) *bodybytes = mh->framesize; |
|
- | 649 | ||
- | 650 | return MPG123_OK; |
|
Line 534... | Line 651... | ||
534 | 651 | } |
|
535 | 652 | ||
536 | /* |
653 | /* |
537 | Fuzzy frame offset searching (guessing). |
654 | Fuzzy frame offset searching (guessing). |
538 | When we don't have an accurate position, we may use an inaccurate one. |
655 | When we don't have an accurate position, we may use an inaccurate one. |
539 | Possibilities: |
656 | Possibilities: |
540 | - use approximate positions from Xing TOC (not yet parsed) |
657 | - use approximate positions from Xing TOC (not yet parsed) |
Line 541... | Line 658... | ||
541 | - guess wildly from mean framesize and offset of first frame / beginning of file. |
658 | - guess wildly from mean framesize and offset of first frame / beginning of file. |
542 | */ |
659 | */ |
543 | 660 | ||
544 | off_t frame_fuzzy_find(mpg123_handle *fr, off_t want_frame, off_t* get_frame) |
661 | static off_t frame_fuzzy_find(mpg123_handle *fr, off_t want_frame, off_t* get_frame) |
545 | { |
662 | { |
Line 559... | Line 676... | ||
559 | if(toc_entry < 0) toc_entry = 0; |
676 | if(toc_entry < 0) toc_entry = 0; |
560 | if(toc_entry > 99) toc_entry = 99; |
677 | if(toc_entry > 99) toc_entry = 99; |
Line 561... | Line 678... | ||
561 | 678 | ||
562 | /* Now estimate back what frame we get. */ |
679 | /* Now estimate back what frame we get. */ |
563 | *get_frame = (off_t) ((double)toc_entry/100. * fr->track_frames); |
680 | *get_frame = (off_t) ((double)toc_entry/100. * fr->track_frames); |
564 | fr->accurate = FALSE; |
681 | fr->state_flags &= ~FRAME_ACCURATE; |
565 | fr->silent_resync = 1; |
682 | fr->silent_resync = 1; |
566 | /* Question: Is the TOC for whole file size (with/without ID3) or the "real" audio data only? |
683 | /* Question: Is the TOC for whole file size (with/without ID3) or the "real" audio data only? |
567 | ID3v1 info could also matter. */ |
684 | ID3v1 info could also matter. */ |
568 | ret = (off_t) ((double)fr->xing_toc[toc_entry]/256.* fr->rdat.filelen); |
685 | ret = (off_t) ((double)fr->xing_toc[toc_entry]/256.* fr->rdat.filelen); |
569 | } |
686 | } |
570 | else if(fr->mean_framesize > 0) |
687 | else if(fr->mean_framesize > 0) |
571 | { /* Just guess with mean framesize (may be exact with CBR files). */ |
688 | { /* Just guess with mean framesize (may be exact with CBR files). */ |
572 | /* Query filelen here or not? */ |
689 | /* Query filelen here or not? */ |
573 | fr->accurate = FALSE; /* Fuzzy! */ |
690 | fr->state_flags &= ~FRAME_ACCURATE; /* Fuzzy! */ |
574 | fr->silent_resync = 1; |
691 | fr->silent_resync = 1; |
575 | *get_frame = want_frame; |
692 | *get_frame = want_frame; |
576 | ret = (off_t) (fr->audio_start+fr->mean_framesize*want_frame); |
693 | ret = (off_t) (fr->audio_start+fr->mean_framesize*want_frame); |
577 | } |
694 | } |
Line 615... | Line 732... | ||
615 | fi = fr->index.fill - 1; |
732 | fi = fr->index.fill - 1; |
616 | } |
733 | } |
617 | /* We have index position, that yields frame and byte offsets. */ |
734 | /* We have index position, that yields frame and byte offsets. */ |
618 | *get_frame = fi*fr->index.step; |
735 | *get_frame = fi*fr->index.step; |
619 | gopos = fr->index.data[fi]; |
736 | gopos = fr->index.data[fi]; |
620 | fr->accurate = TRUE; /* When using the frame index, we are accurate. */ |
737 | fr->state_flags |= FRAME_ACCURATE; /* When using the frame index, we are accurate. */ |
621 | } |
738 | } |
622 | else |
739 | else |
623 | { |
740 | { |
624 | #endif |
741 | #endif |
625 | if(fr->p.flags & MPG123_FUZZY) |
742 | if(fr->p.flags & MPG123_FUZZY) |
Line 672... | Line 789... | ||
672 | default: error1("Bad down_sample (%i) ... should not be possible!!", fr->down_sample); |
789 | default: error1("Bad down_sample (%i) ... should not be possible!!", fr->down_sample); |
673 | } |
790 | } |
674 | return outs; |
791 | return outs; |
675 | } |
792 | } |
Line -... | Line 793... | ||
- | 793 | ||
- | 794 | /* Compute the number of output samples we expect from this frame. |
|
- | 795 | This is either simple spf() or a tad more elaborate for ntom. */ |
|
- | 796 | off_t frame_expect_outsamples(mpg123_handle *fr) |
|
- | 797 | { |
|
- | 798 | off_t outs = 0; |
|
- | 799 | switch(fr->down_sample) |
|
- | 800 | { |
|
- | 801 | case 0: |
|
- | 802 | # ifndef NO_DOWNSAMPLE |
|
- | 803 | case 1: |
|
- | 804 | case 2: |
|
- | 805 | # endif |
|
- | 806 | outs = spf(fr)>>fr->down_sample; |
|
- | 807 | break; |
|
- | 808 | #ifndef NO_NTOM |
|
- | 809 | case 3: outs = ntom_frame_outsamples(fr); break; |
|
- | 810 | #endif |
|
- | 811 | default: error1("Bad down_sample (%i) ... should not be possible!!", fr->down_sample); |
|
- | 812 | } |
|
- | 813 | return outs; |
|
- | 814 | } |
|
676 | 815 | ||
677 | off_t frame_offset(mpg123_handle *fr, off_t outs) |
816 | off_t frame_offset(mpg123_handle *fr, off_t outs) |
678 | { |
817 | { |
679 | off_t num = 0; |
818 | off_t num = 0; |
680 | switch(fr->down_sample) |
819 | switch(fr->down_sample) |
Line 694... | Line 833... | ||
694 | return num; |
833 | return num; |
695 | } |
834 | } |
Line 696... | Line 835... | ||
696 | 835 | ||
697 | #ifdef GAPLESS |
836 | #ifdef GAPLESS |
698 | /* input in _input_ samples */ |
837 | /* input in _input_ samples */ |
- | 838 | void frame_gapless_init(mpg123_handle *fr, off_t framecount, off_t bskip, off_t eskip) |
|
- | 839 | { |
|
- | 840 | debug3("frame_gaples_init: given %"OFF_P" frames, skip %"OFF_P" and %"OFF_P, (off_p)framecount, (off_p)bskip, (off_p)eskip); |
|
- | 841 | fr->gapless_frames = framecount; |
|
699 | void frame_gapless_init(mpg123_handle *fr, off_t b, off_t e) |
842 | if(fr->gapless_frames > 0) |
700 | { |
843 | { |
- | 844 | fr->begin_s = bskip+GAPLESS_DELAY; |
|
- | 845 | fr->end_s = framecount*spf(fr)-eskip+GAPLESS_DELAY; |
|
701 | fr->begin_s = b; |
846 | } |
702 | fr->end_s = e; |
847 | else fr->begin_s = fr->end_s = 0; |
703 | /* These will get proper values later, from above plus resampling info. */ |
848 | /* These will get proper values later, from above plus resampling info. */ |
704 | fr->begin_os = 0; |
849 | fr->begin_os = 0; |
- | 850 | fr->end_os = 0; |
|
705 | fr->end_os = 0; |
851 | fr->fullend_os = 0; |
706 | debug2("frame_gapless_init: from %lu to %lu samples", (long unsigned)fr->begin_s, (long unsigned)fr->end_s); |
852 | debug2("frame_gapless_init: from %"OFF_P" to %"OFF_P" samples", (off_p)fr->begin_s, (off_p)fr->end_s); |
Line 707... | Line 853... | ||
707 | } |
853 | } |
708 | 854 | ||
709 | void frame_gapless_realinit(mpg123_handle *fr) |
855 | void frame_gapless_realinit(mpg123_handle *fr) |
710 | { |
856 | { |
- | 857 | fr->begin_os = frame_ins2outs(fr, fr->begin_s); |
|
711 | fr->begin_os = frame_ins2outs(fr, fr->begin_s); |
858 | fr->end_os = frame_ins2outs(fr, fr->end_s); |
712 | fr->end_os = frame_ins2outs(fr, fr->end_s); |
859 | fr->fullend_os = frame_ins2outs(fr, fr->gapless_frames*spf(fr)); |
Line 713... | Line 860... | ||
713 | debug2("frame_gapless_realinit: from %lu to %lu samples", (long unsigned)fr->begin_os, (long unsigned)fr->end_os); |
860 | debug2("frame_gapless_realinit: from %"OFF_P" to %"OFF_P" samples", (off_p)fr->begin_os, (off_p)fr->end_os); |
714 | } |
861 | } |
715 | 862 | ||
- | 863 | /* At least note when there is trouble... */ |
|
- | 864 | void frame_gapless_update(mpg123_handle *fr, off_t total_samples) |
|
- | 865 | { |
|
- | 866 | off_t gapless_samples = fr->gapless_frames*spf(fr); |
|
- | 867 | debug2("gapless update with new sample count %"OFF_P" as opposed to known %"OFF_P, total_samples, gapless_samples); |
|
716 | /* When we got a new sample count, update the gaplessness. */ |
868 | if(NOQUIET && total_samples != gapless_samples) |
717 | void frame_gapless_update(mpg123_handle *fr, off_t total_samples) |
869 | fprintf(stderr, "\nWarning: Real sample count differs from given gapless sample count. Frankenstein stream?\n"); |
- | 870 | ||
- | 871 | if(gapless_samples > total_samples) |
|
718 | { |
872 | { |
719 | if(fr->end_s < 1) |
873 | if(NOQUIET) error2("End sample count smaller than gapless end! (%"OFF_P" < %"OFF_P"). Disabling gapless mode from now on.", (off_p)total_samples, (off_p)fr->end_s); |
720 | { |
- | |
721 | fr->end_s = total_samples; |
874 | /* This invalidates the current position... but what should I do? */ |
722 | frame_gapless_realinit(fr); |
- | |
723 | } |
- | |
724 | else if(fr->end_s > total_samples) |
875 | frame_gapless_init(fr, -1, 0, 0); |
725 | { |
876 | frame_gapless_realinit(fr); |
726 | if(NOQUIET) error2("end sample count smaller than gapless end! (%"OFF_P" < %"OFF_P").", (off_p)total_samples, (off_p)fr->end_s); |
877 | fr->lastframe = -1; |
Line 727... | Line 878... | ||
727 | fr->end_s = total_samples; |
878 | fr->lastoff = 0; |
Line 748... | Line 899... | ||
748 | With gapless, even the whole frame position could be advanced further than requested (since Homey don't play dat). */ |
899 | With gapless, even the whole frame position could be advanced further than requested (since Homey don't play dat). */ |
749 | void frame_set_frameseek(mpg123_handle *fr, off_t fe) |
900 | void frame_set_frameseek(mpg123_handle *fr, off_t fe) |
750 | { |
901 | { |
751 | fr->firstframe = fe; |
902 | fr->firstframe = fe; |
752 | #ifdef GAPLESS |
903 | #ifdef GAPLESS |
753 | if(fr->p.flags & MPG123_GAPLESS) |
904 | if(fr->p.flags & MPG123_GAPLESS && fr->gapless_frames > 0) |
754 | { |
905 | { |
755 | /* Take care of the beginning... */ |
906 | /* Take care of the beginning... */ |
756 | off_t beg_f = frame_offset(fr, fr->begin_os); |
907 | off_t beg_f = frame_offset(fr, fr->begin_os); |
757 | if(fe <= beg_f) |
908 | if(fe <= beg_f) |
758 | { |
909 | { |
Line 763... | Line 914... | ||
763 | /* The end is set once for a track at least, on the frame_set_frameseek called in get_next_frame() */ |
914 | /* The end is set once for a track at least, on the frame_set_frameseek called in get_next_frame() */ |
764 | if(fr->end_os > 0) |
915 | if(fr->end_os > 0) |
765 | { |
916 | { |
766 | fr->lastframe = frame_offset(fr,fr->end_os); |
917 | fr->lastframe = frame_offset(fr,fr->end_os); |
767 | fr->lastoff = fr->end_os - frame_outs(fr, fr->lastframe); |
918 | fr->lastoff = fr->end_os - frame_outs(fr, fr->lastframe); |
768 | } else fr->lastoff = 0; |
919 | } else {fr->lastframe = -1; fr->lastoff = 0; } |
769 | } else { fr->firstoff = fr->lastoff = 0; fr->lastframe = -1; } |
920 | } else { fr->firstoff = fr->lastoff = 0; fr->lastframe = -1; } |
770 | #endif |
921 | #endif |
771 | fr->ignoreframe = ignoreframe(fr); |
922 | fr->ignoreframe = ignoreframe(fr); |
772 | #ifdef GAPLESS |
923 | #ifdef GAPLESS |
773 | debug5("frame_set_frameseek: begin at %li frames and %li samples, end at %li and %li; ignore from %li", |
924 | debug5("frame_set_frameseek: begin at %li frames and %li samples, end at %li and %li; ignore from %li", |
Line 789... | Line 940... | ||
789 | /* Sample accurate seek prepare for decoder. */ |
940 | /* Sample accurate seek prepare for decoder. */ |
790 | /* This gets unadjusted output samples and takes resampling into account */ |
941 | /* This gets unadjusted output samples and takes resampling into account */ |
791 | void frame_set_seek(mpg123_handle *fr, off_t sp) |
942 | void frame_set_seek(mpg123_handle *fr, off_t sp) |
792 | { |
943 | { |
793 | fr->firstframe = frame_offset(fr, sp); |
944 | fr->firstframe = frame_offset(fr, sp); |
- | 945 | debug1("frame_set_seek: from %"OFF_P, fr->num); |
|
794 | #ifndef NO_NTOM |
946 | #ifndef NO_NTOM |
795 | if(fr->down_sample == 3) ntom_set_ntom(fr, fr->firstframe); |
947 | if(fr->down_sample == 3) ntom_set_ntom(fr, fr->firstframe); |
796 | #endif |
948 | #endif |
797 | fr->ignoreframe = ignoreframe(fr); |
949 | fr->ignoreframe = ignoreframe(fr); |
798 | #ifdef GAPLESS /* The sample offset is used for non-gapless mode, too! */ |
950 | #ifdef GAPLESS /* The sample offset is used for non-gapless mode, too! */ |
Line 884... | Line 1036... | ||
884 | if(really) *really = mh->lastscale; |
1036 | if(really) *really = mh->lastscale; |
885 | get_rva(mh, NULL, rva_db); |
1037 | get_rva(mh, NULL, rva_db); |
886 | return MPG123_OK; |
1038 | return MPG123_OK; |
887 | }>=>>>>>100;>>>4;>4;>>>> |
1039 | } |
Line -... | Line 1040... | ||
- | 1040 | ||
- | 1041 | off_t attribute_align_arg mpg123_framepos(mpg123_handle *mh) |
|
- | 1042 | { |
|
- | 1043 | if(mh == NULL) return MPG123_ERR; |
|
- | 1044 | ||
- | 1045 | return mh->input_offset; |