File Coverage

src/flac.c
Criterion Covered Total %
statement 374 486 76.9
branch 167 296 56.4
condition n/a
subroutine n/a
pod n/a
total 541 782 69.1


line stmt bran cond sub pod time code
1             /*
2             * This program is free software; you can redistribute it and/or modify
3             * it under the terms of the GNU General Public License as published by
4             * the Free Software Foundation; either version 2 of the License, or
5             * (at your option) any later version.
6             *
7             * This program is distributed in the hope that it will be useful,
8             * but WITHOUT ANY WARRANTY; without even the implied warranty of
9             * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10             * GNU General Public License for more details.
11             *
12             * You should have received a copy of the GNU General Public License
13             * along with this program; if not, write to the Free Software
14             * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15             */
16              
17             #include "flac.h"
18              
19             int
20 8           get_flac_metadata(PerlIO *infile, char *file, HV *info, HV *tags)
21             {
22 8           flacinfo *flac = _flac_parse(infile, file, info, tags, 0);
23              
24 8           Safefree(flac);
25              
26 8           return 0;
27             }
28              
29             flacinfo *
30 15           _flac_parse(PerlIO *infile, char *file, HV *info, HV *tags, uint8_t seeking)
31             {
32 15           int err = 0;
33 15           int done = 0;
34             unsigned char *bptr;
35 15           unsigned int id3_size = 0;
36             uint32_t song_length_ms;
37              
38             flacinfo *flac;
39 15           Newz(0, flac, sizeof(flacinfo), flacinfo);
40 15           Newz(0, flac->buf, sizeof(Buffer), Buffer);
41              
42 15           flac->infile = infile;
43 15           flac->file = file;
44 15           flac->info = info;
45 15           flac->tags = tags;
46 15           flac->audio_offset = 0;
47 15           flac->seeking = seeking ? 1 : 0;
48 15           flac->num_seekpoints = 0;
49              
50 15           buffer_init(flac->buf, FLAC_BLOCK_SIZE);
51              
52 15           flac->file_size = _file_size(infile);
53              
54 15 50         if ( !_check_buf(infile, flac->buf, 10, FLAC_BLOCK_SIZE) ) {
55 0           err = -1;
56 0           goto out;
57             }
58              
59             // Check for ID3 tags
60 15           bptr = buffer_ptr(flac->buf);
61 15 100         if (
62 4 50         (bptr[0] == 'I' && bptr[1] == 'D' && bptr[2] == '3') &&
    50          
    50          
63 4 50         bptr[3] < 0xff && bptr[4] < 0xff &&
    50          
64 4 50         bptr[6] < 0x80 && bptr[7] < 0x80 && bptr[8] < 0x80 && bptr[9] < 0x80
    50          
    50          
65             ) {
66             /* found an ID3 header... */
67 4           id3_size = 10 + (bptr[6]<<21) + (bptr[7]<<14) + (bptr[8]<<7) + bptr[9];
68              
69 4 50         if (bptr[5] & 0x10) {
70             // footer present
71 0           id3_size += 10;
72             }
73              
74             DEBUG_TRACE("Found ID3v2 tag of size %d\n", id3_size);
75              
76 4           flac->audio_offset += id3_size;
77              
78             // seek past ID3, we will parse it later
79 4 100         if ( id3_size < buffer_len(flac->buf) ) {
80 1           buffer_consume(flac->buf, id3_size);
81             }
82             else {
83 3           buffer_clear(flac->buf);
84              
85 3 50         if (PerlIO_seek(infile, id3_size, SEEK_SET) < 0) {
86 0           err = -1;
87 0           goto out;
88             }
89             }
90              
91 4 50         if ( !_check_buf(infile, flac->buf, 4, FLAC_BLOCK_SIZE) ) {
92 0           err = -1;
93 0           goto out;
94             }
95             }
96              
97             // Verify fLaC magic
98 15           bptr = buffer_ptr(flac->buf);
99 15 50         if ( memcmp(bptr, "fLaC", 4) != 0 ) {
100 0           PerlIO_printf(PerlIO_stderr(), "Not a valid FLAC file: %s\n", file);
101 0           err = -1;
102 0           goto out;
103             }
104              
105 15           buffer_consume(flac->buf, 4);
106              
107 15           flac->audio_offset += 4;
108              
109             // Parse all metadata blocks
110 71 100         while ( !done ) {
111             uint8_t type;
112             off_t len;
113              
114 57 50         if ( !_check_buf(infile, flac->buf, 4, FLAC_BLOCK_SIZE) ) {
115 0           err = -1;
116 0           goto out;
117             }
118              
119 57           bptr = buffer_ptr(flac->buf);
120              
121 57 100         if ( bptr[0] & 0x80 ) {
122             // last metadata block flag
123 14           done = 1;
124             }
125              
126 57           type = bptr[0] & 0x7f;
127 57           len = (bptr[1] << 16) | (bptr[2] << 8) | bptr[3];
128              
129 57           buffer_consume(flac->buf, 4);
130              
131             DEBUG_TRACE("Parsing metadata block, type %d, len %d, done %d\n", type, (int)len, done);
132              
133 57 100         if ( len > flac->file_size - flac->audio_offset ) {
134 1           err = -1;
135 1           goto out;
136             }
137              
138             // Don't read in the full picture in case we aren't reading artwork
139             // Do the same for padding, as it can be quite large in some files
140 56 100         if ( type != FLAC_TYPE_PICTURE && type != FLAC_TYPE_PADDING ) {
    100          
141 40 50         if ( !_check_buf(infile, flac->buf, len, len) ) {
142 0           err = -1;
143 0           goto out;
144             }
145             }
146              
147 56           flac->audio_offset += 4 + len;
148              
149 56           switch (type) {
150             case FLAC_TYPE_STREAMINFO:
151 15           _flac_parse_streaminfo(flac);
152 15           break;
153              
154             case FLAC_TYPE_VORBIS_COMMENT:
155 13 100         if ( !flac->seeking ) {
156             // Vorbis comment parsing code from ogg.c
157 7           _parse_vorbis_comments(flac->infile, flac->buf, tags, 0);
158             }
159             else {
160             DEBUG_TRACE(" seeking, not parsing comments\n");
161 6           buffer_consume(flac->buf, len);
162             }
163 13           break;
164              
165             case FLAC_TYPE_APPLICATION:
166 2 100         if ( !flac->seeking ) {
167 1           _flac_parse_application(flac, len);
168             }
169             else {
170             DEBUG_TRACE(" seeking, skipping application\n");
171 1           buffer_consume(flac->buf, len);
172             }
173 2           break;
174              
175             case FLAC_TYPE_SEEKTABLE:
176 8 100         if (flac->seeking) {
177 3           _flac_parse_seektable(flac, len);
178             }
179             else {
180             DEBUG_TRACE(" not seeking, skipping seektable\n");
181 5           buffer_consume(flac->buf, len);
182             }
183 8           break;
184              
185             case FLAC_TYPE_CUESHEET:
186 2 100         if ( !flac->seeking ) {
187 1           _flac_parse_cuesheet(flac);
188             }
189             else {
190             DEBUG_TRACE(" seeking, skipping cuesheet\n");
191 1           buffer_consume(flac->buf, len);
192             }
193 2           break;
194              
195             case FLAC_TYPE_PICTURE:
196 3 100         if ( !flac->seeking ) {
197 2 50         if ( !_flac_parse_picture(flac) ) {
198 0           goto out;
199             }
200             }
201             else {
202             DEBUG_TRACE(" seeking, skipping picture\n");
203 1           _flac_skip(flac, len);
204             }
205 3           break;
206              
207             case FLAC_TYPE_PADDING:
208             default:
209             DEBUG_TRACE(" unhandled or padding, skipping\n");
210 13           _flac_skip(flac, len);
211             }
212             }
213              
214 14 50         song_length_ms = SvIV( *( my_hv_fetch(info, "song_length_ms") ) );
215              
216 14 100         if (song_length_ms > 0) {
217 13           my_hv_store( info, "bitrate", newSVuv( _bitrate(flac->file_size - flac->audio_offset, song_length_ms) ) );
218             }
219             else {
220 1 50         if (!seeking) {
221             // Find the first/last frames and manually calculate duration and bitrate
222             off_t frame_offset;
223             uint64_t first_sample;
224             uint64_t last_sample;
225             uint64_t tmp;
226              
227             DEBUG_TRACE("Manually determining duration/bitrate\n");
228              
229 1           Newz(0, flac->scratch, sizeof(Buffer), Buffer);
230              
231 1 50         if ( _flac_first_last_sample(flac, flac->audio_offset, &frame_offset, &first_sample, &tmp, 0) ) {
232             DEBUG_TRACE(" First sample: %llu (offset %llu)\n", first_sample, frame_offset);
233              
234             // XXX This last sample isn't really correct, seeking back max_framesize will most likely be several frames
235             // from the end, resulting in a slightly shortened duration. Reading backwards through the file
236             // would provide a more accurate result
237 1 50         if ( _flac_first_last_sample(flac, flac->file_size - flac->max_framesize, &frame_offset, &tmp, &last_sample, 0) ) {
238 1 50         if (flac->samplerate) {
239 1           song_length_ms = (uint32_t)(( ((last_sample - first_sample) * 1.0) / flac->samplerate) * 1000);
240 1           my_hv_store( info, "song_length_ms", newSVuv(song_length_ms) );
241 1           my_hv_store( info, "bitrate", newSVuv( _bitrate(flac->file_size - flac->audio_offset, song_length_ms) ) );
242 1           my_hv_store( info, "total_samples", newSVuv( last_sample - first_sample ) );
243             }
244              
245             DEBUG_TRACE(" Last sample: %llu (offset %llu)\n", last_sample, frame_offset);
246             }
247             }
248              
249 1           buffer_free(flac->scratch);
250 1           Safefree(flac->scratch);
251             }
252             }
253              
254 14           my_hv_store( info, "file_size", newSVuv(flac->file_size) );
255 14           my_hv_store( info, "audio_offset", newSVuv(flac->audio_offset) );
256 14           my_hv_store( info, "audio_size", newSVuv(flac->file_size - flac->audio_offset) );
257              
258             // Parse ID3 last, due to an issue with libid3tag screwing
259             // up the filehandle
260 14 100         if (id3_size && !seeking) {
    100          
261 2           parse_id3(infile, file, info, tags, 0, flac->file_size);
262             }
263              
264             out:
265 15           buffer_free(flac->buf);
266 15           Safefree(flac->buf);
267              
268 15           return flac;
269             }
270              
271             // offset is in ms, does sample-accurate seeking, using seektable if available
272             // based on libFLAC seek_to_absolute_sample_
273             static int
274 7           flac_find_frame(PerlIO *infile, char *file, int offset)
275             {
276 7           off_t frame_offset = -1;
277             uint64_t target_sample;
278             uint32_t approx_bytes_per_frame;
279             uint64_t lower_bound, upper_bound, lower_bound_sample, upper_bound_sample;
280 7           int64_t pos = -1;
281 7           int8_t max_tries = 100;
282              
283             // We need to read all metadata first to get some data we need to calculate
284 7           HV *info = newHV();
285 7           HV *tags = newHV();
286 7           flacinfo *flac = _flac_parse(infile, file, info, tags, 1);
287              
288             // Allocate scratch buffer
289 7           Newz(0, flac->scratch, sizeof(Buffer), Buffer);
290              
291 7 50         if ( !flac->samplerate || !flac->total_samples ) {
    50          
292             // Can't seek in file without samplerate
293             goto out;
294             }
295              
296             // Determine target sample we're looking for
297 7           target_sample = ((offset - 1) / 10) * (flac->samplerate / 100);
298             DEBUG_TRACE("Looking for target sample %llu\n", target_sample);
299              
300 7 50         if (flac->min_blocksize == flac->max_blocksize && flac->min_blocksize > 0)
    50          
301 7           approx_bytes_per_frame = flac->min_blocksize * flac->channels * flac->bits_per_sample/8 + 64;
302 0 0         else if (flac->max_framesize > 0)
303 0           approx_bytes_per_frame = (flac->max_framesize + flac->min_framesize) / 2 + 1;
304             else
305 0           approx_bytes_per_frame = 4096 * flac->channels * flac->bits_per_sample/8 + 64;
306              
307             DEBUG_TRACE("approx_bytes_per_frame: %d\n", approx_bytes_per_frame);
308              
309 7           lower_bound = flac->audio_offset;
310 7           lower_bound_sample = 0;
311 7           upper_bound = flac->file_size;
312 7           upper_bound_sample = flac->total_samples;
313              
314 7 100         if (flac->num_seekpoints) {
315             // Use seektable to find seek point
316             // Start looking at seekpoint 1
317             int i;
318 3           uint64_t new_lower_bound = lower_bound;
319 3           uint64_t new_upper_bound = upper_bound;
320 3           uint64_t new_lower_bound_sample = lower_bound_sample;
321 3           uint64_t new_upper_bound_sample = upper_bound_sample;
322              
323             DEBUG_TRACE("Checking seektable...\n");
324              
325 14 50         for (i = flac->num_seekpoints - 1; i >= 0; i--) {
326 14 100         if (
327 14           flac->seekpoints[i].sample_number != 0xFFFFFFFFFFFFFFFFLL
328 11 50         && flac->seekpoints[i].frame_samples > 0
329 11 50         && (flac->total_samples <= 0 || flac->seekpoints[i].sample_number < flac->total_samples)
    50          
330 11 100         && flac->seekpoints[i].sample_number <= target_sample
331             )
332 3           break;
333             }
334              
335 3 50         if (i >= 0) {
336             // we found a seek point
337 3           new_lower_bound = flac->audio_offset + flac->seekpoints[i].stream_offset;
338 3           new_lower_bound_sample = flac->seekpoints[i].sample_number;
339              
340             DEBUG_TRACE(" seektable new_lower_bound %llu, new_lower_bound_sample %llu\n",
341             new_lower_bound, new_lower_bound_sample);
342             }
343              
344             // Find the closest seek point > target_sample
345 26 100         for (i = 0; i < flac->num_seekpoints; i++) {
346 25 100         if (
347 25           flac->seekpoints[i].sample_number != 0xFFFFFFFFFFFFFFFFLL
348 24 50         && flac->seekpoints[i].frame_samples > 0
349 24 50         && (flac->total_samples <= 0 || flac->seekpoints[i].sample_number < flac->total_samples)
    50          
350 24 100         && flac->seekpoints[i].sample_number > target_sample
351             )
352 2           break;
353             }
354              
355 3 100         if (i < flac->num_seekpoints) {
356             // we found a seek point
357 2           new_upper_bound = flac->audio_offset + flac->seekpoints[i].stream_offset;
358 2           new_upper_bound_sample = flac->seekpoints[i].sample_number;
359              
360             DEBUG_TRACE(" seektable new_upper_bound %llu, new_upper_bound_sample %llu\n",
361             new_upper_bound, new_upper_bound_sample);
362             }
363              
364 3 50         if (new_upper_bound >= new_lower_bound) {
365 3           lower_bound = new_lower_bound;
366 3           upper_bound = new_upper_bound;
367 3           lower_bound_sample = new_lower_bound_sample;
368 3           upper_bound_sample = new_upper_bound_sample;
369             }
370             }
371              
372 7 50         if (upper_bound_sample == lower_bound_sample)
373 0           upper_bound_sample++;
374              
375 107 100         while (max_tries--) {
376 106           int ret = -1;
377             uint64_t this_frame_sample;
378             uint64_t last_sample;
379              
380             // check if bounds are still ok
381 106 50         if (lower_bound_sample >= upper_bound_sample || lower_bound > upper_bound) {
    50          
382             DEBUG_TRACE("Error: out of bounds\n");
383 0           frame_offset = -1;
384 0           goto out;
385             }
386              
387             // estimate position
388 212           pos = (int64_t)lower_bound + (int64_t)(
389 106           (double)((target_sample - lower_bound_sample) * (upper_bound - lower_bound))
390 106           /
391 106           (double)(upper_bound_sample - lower_bound_sample)
392 106           ) - approx_bytes_per_frame;
393              
394             DEBUG_TRACE("Initial pos: %lld\n", pos);
395              
396 106 50         if (pos < (int64_t)lower_bound)
397 106           pos = lower_bound;
398              
399 106 50         if (pos >= (int64_t)upper_bound)
400 0           pos = upper_bound - FLAC_FRAME_MAX_HEADER;
401              
402             DEBUG_TRACE("Searching at pos %lld (lb/lbs %llu/%llu, ub/ubs %llu/%llu)\n",
403             pos, lower_bound, lower_bound_sample, upper_bound, upper_bound_sample);
404              
405 106           ret = _flac_first_last_sample(flac, pos, &frame_offset, &this_frame_sample, &last_sample, target_sample);
406              
407 106 50         if (ret < 0) {
408             // Error
409 0           goto out;
410             }
411 106 50         else if (ret == 0) {
412             // No valid frame found in range pos - flac->max_framesize, adjust bounds and retry
413 0           upper_bound = pos;
414 0           upper_bound_sample -= flac->min_blocksize;
415              
416             DEBUG_TRACE(" No valid frame found, retrying (ub/ubs %llu/%llu)\n", upper_bound, upper_bound_sample);
417              
418 0           continue;
419             }
420              
421             // make sure we are not seeking in corrupted stream
422 106 50         if (this_frame_sample < lower_bound_sample) {
423             DEBUG_TRACE(" Frame at %d, this_frame_sample %llu, < lower_bound_sample %llu, aborting\n",
424             (int)frame_offset, this_frame_sample, lower_bound_sample);
425              
426 0           goto out;
427             }
428              
429             DEBUG_TRACE(" Frame at %d, this_frame_sample %llu, last_sample %llu (target %llu)\n",
430             (int)frame_offset, this_frame_sample, last_sample, target_sample);
431              
432 106 100         if (target_sample >= this_frame_sample && target_sample < last_sample) {
    50          
433             DEBUG_TRACE(" Found target frame\n");
434 6           break;
435             }
436              
437             // narrow the search
438 100 50         if (target_sample < this_frame_sample) {
439 100           upper_bound_sample = this_frame_sample;
440 100           upper_bound = frame_offset;
441 100           approx_bytes_per_frame = 2 * (upper_bound - pos) / 3 + 16;
442              
443             DEBUG_TRACE(" Moving upper_bound to %llu, upper_bound_sample to %llu, approx_bytes_per_frame %d\n",
444             upper_bound, upper_bound_sample, approx_bytes_per_frame);
445             }
446             else {
447 0           lower_bound_sample = last_sample;
448 0           lower_bound = frame_offset + 1;
449 100           approx_bytes_per_frame = 2 * (lower_bound - pos) / 3 + 16;
450              
451             DEBUG_TRACE(" Moving lower_bound to %llu, lower_bound_sample to %llu, approx_bytes_per_frame %d\n",
452             lower_bound, lower_bound_sample, approx_bytes_per_frame);
453             }
454             }
455              
456             DEBUG_TRACE("max_tries: %d\n", max_tries);
457              
458             out:
459             // Don't leak
460 7           SvREFCNT_dec(info);
461 7           SvREFCNT_dec(tags);
462              
463             // free seek struct
464 7           Safefree(flac->seekpoints);
465              
466             // free scratch buffer
467 7 50         if (flac->scratch->alloc)
468 7           buffer_free(flac->scratch);
469 7           Safefree(flac->scratch);
470              
471 7           Safefree(flac);
472              
473 7           return frame_offset;
474             }
475              
476             // Returns:
477             // 1: Found a valid frame
478             // 0: Did not find a valid frame
479             // -1: Error
480             int
481 108           _flac_first_last_sample(flacinfo *flac, off_t seek_offset, off_t *frame_offset, uint64_t *first_sample, uint64_t *last_sample, uint64_t target_sample)
482             {
483             unsigned char *bptr;
484             unsigned int buf_size;
485 108           int ret = 0;
486             uint32_t i;
487              
488 108           buffer_init_or_clear(flac->scratch, flac->max_framesize);
489              
490 108 50         if (seek_offset > flac->file_size - FLAC_FRAME_MAX_HEADER) {
491             DEBUG_TRACE(" Error: seek_offset > file_size - header size\n");
492 0           ret = -1;
493 0           goto out;
494             }
495              
496 108 50         if ( (PerlIO_seek(flac->infile, seek_offset, SEEK_SET)) == -1 ) {
497             DEBUG_TRACE(" Error: seek failed\n");
498 0           ret = -1;
499 0           goto out;
500             }
501              
502 108 50         if ( !_check_buf(flac->infile, flac->scratch, FLAC_FRAME_MAX_HEADER, flac->max_framesize) ) {
503             DEBUG_TRACE(" Error: read failed\n");
504 0           ret = -1;
505 0           goto out;
506             }
507              
508 108           bptr = buffer_ptr(flac->scratch);
509 108           buf_size = buffer_len(flac->scratch);
510              
511 194496 50         for (i = 0; i != buf_size - FLAC_HEADER_LEN; i++) {
512             // Verify sync and various reserved bits
513 194496 100         if ( bptr[i] != 0xFF
514 3201 100         || (bptr[i+1] >> 2) != 0x3E
515 266 100         || bptr[i+1] & 0x02
516 166 100         || bptr[i+3] & 0x01
517             ) {
518 194338           continue;
519             }
520              
521             DEBUG_TRACE("Checking frame header @ %d: %0x %0x %0x %0x\n", (int)seek_offset + i, bptr[i], bptr[i+1], bptr[i+2], bptr[i+3]);
522              
523             // Verify we have a valid FLAC frame header
524             // and get the first/last sample numbers in the frame if it's valid
525 158 100         if ( !_flac_read_frame_header(flac, &bptr[i], first_sample, last_sample) ) {
526             DEBUG_TRACE(" Unable to read frame header\n");
527 2           continue;
528             }
529              
530             DEBUG_TRACE(" first_sample %llu\n", *first_sample);
531              
532 156           *frame_offset = seek_offset + i;
533 156           ret = 1;
534              
535             // If looking for a target sample, return the nearest frame found in this buffer
536 156 100         if (target_sample) {
537 54 50         if (target_sample >= *first_sample && target_sample < *last_sample) {
    100          
538             // This frame is the one
539             break;
540             }
541 48 50         else if (target_sample < *first_sample) {
542             // Too far, return what we have
543 0           break;
544             }
545             }
546             else {
547             // Not looking for a target sample, return first one found
548 102           break;
549             }
550             }
551              
552             out:
553 108 50         if (ret <= 0)
554 0           *frame_offset = -1;
555              
556 108           return ret;
557             }
558              
559             int
560 158           _flac_read_frame_header(flacinfo *flac, unsigned char *buf, uint64_t *first_sample, uint64_t *last_sample)
561             {
562             // A lot of this code is based on libFLAC stream_decoder.c read_frame_header_
563             uint32_t x;
564             uint64_t xx;
565 158           uint32_t blocksize = 0;
566 158           uint32_t blocksize_hint = 0;
567 158           uint32_t samplerate_hint = 0;
568 158           uint32_t frame_number = 0;
569 158           uint8_t raw_header_len = 4;
570             uint8_t crc8;
571              
572             // Block size
573 158           switch(x = buf[2] >> 4) {
574             case 0:
575 0           return 0;
576             case 1:
577 0           blocksize = 192;
578 0           break;
579             case 2: case 3: case 4: case 5:
580 154           blocksize = 576 << (x-2);
581 154           break;
582             case 6: case 7:
583 1           blocksize_hint = x;
584 1           break;
585             case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15:
586 3           blocksize = 256 << (x-8);
587 3           break;
588             default:
589 0           break;
590             }
591              
592             // Sample rate, all we need here is the hint
593 158           switch(x = buf[2] & 0x0f) {
594             case 12: case 13: case 14:
595 0           samplerate_hint = x;
596 0           break;
597             case 15:
598 0           return 0;
599             default:
600 158           break;
601             }
602              
603 158 100         if ( buf[1] & 0x01 || flac->min_blocksize != flac->max_blocksize ) {
    50          
604             // Variable blocksize
605             // XXX need test
606 2 50         if ( !_flac_read_utf8_uint64(buf, &xx, &raw_header_len) )
607 0           return 0;
608              
609 2 50         if ( xx == 0xFFFFFFFFFFFFFFFFLL )
610 2           return 0;
611              
612             DEBUG_TRACE(" variable blocksize, first sample %llu\n", xx);
613              
614 0           *first_sample = xx;
615             }
616             else {
617             // Fixed blocksize, x = frame number
618 156 50         if ( !_flac_read_utf8_uint32(buf, &x, &raw_header_len) )
619 0           return 0;
620              
621 156 50         if ( x == 0xFFFFFFFF )
622 0           return 0;
623              
624             DEBUG_TRACE(" fixed blocksize, frame number %d\n", x);
625              
626 156           frame_number = x;
627             }
628              
629 156 100         if (blocksize_hint) {
630             DEBUG_TRACE(" blocksize_hint %d\n", blocksize_hint);
631 1           x = buf[raw_header_len++];
632 1 50         if (blocksize_hint == 7) {
633 1           uint32_t _x = buf[raw_header_len++];
634 1           x = (x << 8) | _x;
635             }
636 1           blocksize = x + 1;
637             }
638              
639             DEBUG_TRACE(" blocksize %d\n", blocksize);
640              
641             // XXX need test
642 156 50         if (samplerate_hint) {
643             DEBUG_TRACE(" samplerate_hint %d\n", samplerate_hint);
644 0           raw_header_len++;
645 0 0         if (samplerate_hint != 12) {
646 0           raw_header_len++;
647             }
648             }
649              
650             // Verify CRC-8
651 156           crc8 = buf[raw_header_len];
652 156 50         if ( _flac_crc8(buf, raw_header_len) != crc8 ) {
653             DEBUG_TRACE(" CRC failed\n");
654 0           return 0;
655             }
656              
657             // Calculate sample number from frame number if needed
658 156 100         if (frame_number) {
659             // Fixed blocksize, use min_blocksize value as blocksize above may be different if last frame
660 152           *first_sample = frame_number * flac->min_blocksize;
661             }
662             else {
663 4           *first_sample = 0;
664             }
665              
666 156           *last_sample = *first_sample + blocksize;
667              
668 158           return 1;
669             }
670              
671             void
672 15           _flac_parse_streaminfo(flacinfo *flac)
673             {
674             uint64_t tmp;
675             SV *md5;
676             unsigned char *bptr;
677             int i;
678             uint32_t song_length_ms;
679              
680 15           flac->min_blocksize = buffer_get_short(flac->buf);
681 15           my_hv_store( flac->info, "minimum_blocksize", newSVuv(flac->min_blocksize) );
682              
683 15           flac->max_blocksize = buffer_get_short(flac->buf);
684 15           my_hv_store( flac->info, "maximum_blocksize", newSVuv(flac->max_blocksize) );
685              
686 15           flac->min_framesize = buffer_get_int24(flac->buf);
687 15           my_hv_store( flac->info, "minimum_framesize", newSVuv(flac->min_framesize) );
688              
689 15           flac->max_framesize = buffer_get_int24(flac->buf);
690 15           my_hv_store( flac->info, "maximum_framesize", newSVuv(flac->max_framesize) );
691              
692 15 100         if ( !flac->max_framesize ) {
693 1           flac->max_framesize = FLAC_MAX_FRAMESIZE;
694             }
695              
696 15           tmp = buffer_get_int64(flac->buf);
697              
698 15           flac->samplerate = (uint32_t)((tmp >> 44) & 0xFFFFF);
699 15           flac->total_samples = tmp & 0xFFFFFFFFFLL;
700 15           flac->channels = (uint32_t)(((tmp >> 41) & 0x7) + 1);
701 15           flac->bits_per_sample = (uint32_t)(((tmp >> 36) & 0x1F) + 1);
702              
703 15           my_hv_store( flac->info, "samplerate", newSVuv(flac->samplerate) );
704 15           my_hv_store( flac->info, "channels", newSVuv(flac->channels) );
705 15           my_hv_store( flac->info, "bits_per_sample", newSVuv(flac->bits_per_sample) );
706 15           my_hv_store( flac->info, "total_samples", newSVnv(flac->total_samples) );
707              
708 15           bptr = buffer_ptr(flac->buf);
709 15           md5 = newSVpvf("%02x", bptr[0]);
710              
711 240 100         for (i = 1; i < 16; i++) {
712 225           sv_catpvf(md5, "%02x", bptr[i]);
713             }
714              
715 15           my_hv_store(flac->info, "audio_md5", md5);
716 15           buffer_consume(flac->buf, 16);
717              
718 15           song_length_ms = (uint32_t)(( (flac->total_samples * 1.0) / flac->samplerate) * 1000);
719 15           my_hv_store( flac->info, "song_length_ms", newSVuv(song_length_ms) );
720 15           }
721              
722             void
723 1           _flac_parse_application(flacinfo *flac, int len)
724             {
725             HV *app;
726 1           SV *id = newSVuv( buffer_get_int(flac->buf) );
727 1           SV *data = newSVpvn( buffer_ptr(flac->buf), len - 4 );
728 1           buffer_consume(flac->buf, len - 4);
729              
730 1 50         if ( my_hv_exists(flac->tags, "APPLICATION") ) {
731             // XXX needs test
732 0           SV **entry = my_hv_fetch(flac->tags, "APPLICATION");
733 0 0         if (entry != NULL) {
734 0           app = (HV *)SvRV(*entry);
735 0           my_hv_store_ent(app, id, data);
736             }
737             }
738             else {
739 1           app = newHV();
740              
741 1           my_hv_store_ent(app, id, data);
742              
743 1           my_hv_store( flac->tags, "APPLICATION", newRV_noinc( (SV *)app ) );
744             }
745              
746 1           SvREFCNT_dec(id);
747 1           }
748              
749             void
750 3           _flac_parse_seektable(flacinfo *flac, int len)
751             {
752             uint32_t i;
753 3           uint32_t count = len / 18;
754              
755 3           flac->num_seekpoints = count;
756              
757 3 50         New(0,
758             flac->seekpoints,
759             count * sizeof(*flac->seekpoints),
760             struct seekpoint
761             );
762              
763 36 100         for (i = 0; i < count; i++) {
764 33           flac->seekpoints[i].sample_number = buffer_get_int64(flac->buf);
765 33           flac->seekpoints[i].stream_offset = buffer_get_int64(flac->buf);
766 33           flac->seekpoints[i].frame_samples = buffer_get_short(flac->buf);
767              
768             DEBUG_TRACE(
769             " sample_number %llu stream_offset %llu frame_samples %d\n",
770             flac->seekpoints[i].sample_number,
771             flac->seekpoints[i].stream_offset,
772             flac->seekpoints[i].frame_samples
773             );
774             }
775 3           }
776              
777             void
778 1           _flac_parse_cuesheet(flacinfo *flac)
779             {
780 1           AV *cue = newAV();
781             unsigned char *bptr;
782             uint64_t leadin;
783             uint8_t is_cd;
784             char decimal[21];
785             uint8_t num_tracks;
786              
787             // Catalog number, may be empty
788 1           bptr = buffer_ptr(flac->buf);
789 1 50         if (bptr[0]) {
790 0           av_push( cue, newSVpvf("CATALOG %s\n", bptr) );
791             }
792 1           buffer_consume(flac->buf, 128);
793              
794 1           leadin = buffer_get_int64(flac->buf);
795 1           is_cd = (uint8_t)buffer_get_char(flac->buf);
796              
797 1           buffer_consume(flac->buf, 258);
798              
799 1           num_tracks = (uint8_t)buffer_get_char(flac->buf);
800             DEBUG_TRACE(" number of cue tracks: %d\n", num_tracks);
801              
802 1           av_push( cue, newSVpvf("FILE \"%s\" FLAC\n", flac->file) );
803              
804 16 100         while (num_tracks--) {
805             char isrc[13];
806             uint8_t tmp;
807             uint8_t type;
808             uint8_t pre;
809             uint8_t num_index;
810              
811 15           uint64_t track_offset = buffer_get_int64(flac->buf);
812 15           uint8_t tracknum = (uint8_t)buffer_get_char(flac->buf);
813              
814 15           buffer_get(flac->buf, isrc, 12);
815 15           isrc[12] = '\0';
816              
817 15           tmp = (uint8_t)buffer_get_char(flac->buf);
818 15           type = (tmp >> 7) & 0x1;
819 15           pre = (tmp >> 6) & 0x1;
820 15           buffer_consume(flac->buf, 13);
821              
822 15           num_index = (uint8_t)buffer_get_char(flac->buf);
823              
824             DEBUG_TRACE(" track %d: offset %llu, type %d, pre %d, num_index %d\n", tracknum, track_offset, type, pre, num_index);
825              
826 15 50         if (tracknum > 0 && tracknum < 100) {
    100          
827 14 50         av_push( cue, newSVpvf(" TRACK %02u %s\n",
828             tracknum, type == 0 ? "AUDIO" : "DATA"
829             ) );
830              
831 14 100         if (pre) {
832 1           av_push( cue, newSVpv(" FLAGS PRE\n", 0) );
833             }
834              
835 14 100         if (isrc[0]) {
836 1           av_push( cue, newSVpvf(" ISRC %s\n", isrc) );
837             }
838             }
839              
840 33 100         while (num_index--) {
841             SV *index;
842              
843 18           uint64_t index_offset = buffer_get_int64(flac->buf);
844 18           uint8_t index_num = (uint8_t)buffer_get_char(flac->buf);
845 18           buffer_consume(flac->buf, 3);
846              
847             DEBUG_TRACE(" index %d, offset %llu\n", index_num, index_offset);
848              
849 18           index = newSVpvf(" INDEX %02u ", index_num);
850              
851 18 50         if (is_cd) {
852 18           uint64_t frame = ((track_offset + index_offset) / (flac->samplerate / 75));
853             uint8_t m, s, f;
854              
855 18           f = (uint8_t)(frame % 75);
856 18           frame /= 75;
857 18           s = (uint8_t)(frame % 60);
858 18           frame /= 60;
859 18           m = (uint8_t)frame;
860              
861 18           sv_catpvf(index, "%02u:%02u:%02u\n", m, s, f);
862             }
863             else {
864             // XXX need test
865 0           sprintf(decimal, "%"PRIu64, track_offset + index_offset);
866 0           sv_catpvf(index, "%s\n", decimal);
867             }
868              
869 18           av_push( cue, index );
870             }
871              
872 15 100         if (tracknum == 170) {
873             // Add lead-in and lead-out
874 1           sprintf(decimal, "%"PRIu64, leadin);
875 1           av_push( cue, newSVpvf("REM FLAC__lead-in %s\n", decimal) );
876              
877             // XXX is tracknum right here?
878 1           sprintf(decimal, "%"PRIu64, track_offset);
879 15           av_push( cue, newSVpvf("REM FLAC__lead-out %u %s\n", tracknum, decimal) );
880             }
881             }
882              
883 1           my_hv_store( flac->tags, "CUESHEET_BLOCK", newRV_noinc( (SV *)cue ) );
884 1           }
885              
886             int
887 2           _flac_parse_picture(flacinfo *flac)
888             {
889             AV *pictures;
890             HV *picture;
891 2           int ret = 1;
892             uint32_t pic_length;
893              
894 2           picture = _decode_flac_picture(flac->infile, flac->buf, &pic_length);
895 2 50         if ( !picture ) {
896 0           PerlIO_printf(PerlIO_stderr(), "Invalid FLAC file: %s, bad picture block\n", flac->file);
897 0           ret = 0;
898 0           goto out;
899             }
900              
901             // Skip past pic data if necessary
902 2 100         if ( _env_true("AUDIO_SCAN_NO_ARTWORK") ) {
903 1           my_hv_store( picture, "offset", newSVuv(flac->audio_offset - pic_length) );
904 1           _flac_skip(flac, pic_length);
905             }
906             else {
907 1           buffer_consume(flac->buf, pic_length);
908             }
909              
910             DEBUG_TRACE(" found picture of length %d\n", pic_length);
911              
912 2 50         if ( my_hv_exists(flac->tags, "ALLPICTURES") ) {
913 0           SV **entry = my_hv_fetch(flac->tags, "ALLPICTURES");
914 0 0         if (entry != NULL) {
915 0           pictures = (AV *)SvRV(*entry);
916 0           av_push( pictures, newRV_noinc( (SV *)picture ) );
917             }
918             }
919             else {
920 2           pictures = newAV();
921              
922 2           av_push( pictures, newRV_noinc( (SV *)picture ) );
923              
924 2           my_hv_store( flac->tags, "ALLPICTURES", newRV_noinc( (SV *)pictures ) );
925             }
926              
927             out:
928 2           return ret;
929             }
930              
931             /* CRC-8, poly = x^8 + x^2 + x^1 + x^0, init = 0 */
932             uint8_t const _flac_crc8_table[256] = {
933             0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
934             0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
935             0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
936             0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
937             0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5,
938             0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
939             0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85,
940             0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
941             0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2,
942             0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
943             0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2,
944             0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
945             0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32,
946             0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
947             0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42,
948             0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
949             0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C,
950             0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
951             0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC,
952             0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
953             0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C,
954             0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
955             0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C,
956             0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
957             0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B,
958             0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
959             0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B,
960             0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
961             0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB,
962             0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
963             0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB,
964             0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
965             };
966              
967             uint8_t
968 156           _flac_crc8(const unsigned char *buf, unsigned len)
969             {
970 156           uint8_t crc = 0;
971              
972 938 100         while(len--)
973 782           crc = _flac_crc8_table[crc ^ *buf++];
974              
975 156           return crc;
976             }
977              
978             int
979 2           _flac_read_utf8_uint64(unsigned char *raw, uint64_t *val, uint8_t *rawlen)
980             {
981 2           uint64_t v = 0;
982             uint32_t x;
983             unsigned i;
984              
985 2           x = raw[(*rawlen)++];
986              
987 2 50         if(!(x & 0x80)) { /* 0xxxxxxx */
988 0           v = x;
989 0           i = 0;
990             }
991 2 50         else if(x & 0xC0 && !(x & 0x20)) { /* 110xxxxx */
    50          
992 2           v = x & 0x1F;
993 2           i = 1;
994             }
995 0 0         else if(x & 0xE0 && !(x & 0x10)) { /* 1110xxxx */
    0          
996 0           v = x & 0x0F;
997 0           i = 2;
998             }
999 0 0         else if(x & 0xF0 && !(x & 0x08)) { /* 11110xxx */
    0          
1000 0           v = x & 0x07;
1001 0           i = 3;
1002             }
1003 0 0         else if(x & 0xF8 && !(x & 0x04)) { /* 111110xx */
    0          
1004 0           v = x & 0x03;
1005 0           i = 4;
1006             }
1007 0 0         else if(x & 0xFC && !(x & 0x02)) { /* 1111110x */
    0          
1008 0           v = x & 0x01;
1009 0           i = 5;
1010             }
1011 0 0         else if(x & 0xFE && !(x & 0x01)) { /* 11111110 */
    0          
1012 0           v = 0;
1013 0           i = 6;
1014             }
1015             else {
1016 0           *val = 0xffffffffffffffffULL;
1017 0           return 1;
1018             }
1019              
1020 2 50         for( ; i; i--) {
1021 2           x = raw[(*rawlen)++];
1022 2 50         if(!(x & 0x80) || (x & 0x40)) { /* 10xxxxxx */
    0          
1023 2           *val = 0xffffffffffffffffULL;
1024 2           return 1;
1025             }
1026 0           v <<= 6;
1027 0           v |= (x & 0x3F);
1028             }
1029 0           *val = v;
1030 0           return 1;
1031             }
1032              
1033             int
1034 156           _flac_read_utf8_uint32(unsigned char *raw, uint32_t *val, uint8_t *rawlen)
1035             {
1036 156           uint32_t v = 0;
1037             uint32_t x;
1038             unsigned i;
1039              
1040 156           x = raw[(*rawlen)++];
1041              
1042 156 50         if(!(x & 0x80)) { /* 0xxxxxxx */
1043 156           v = x;
1044 156           i = 0;
1045             }
1046 0 0         else if(x & 0xC0 && !(x & 0x20)) { /* 110xxxxx */
    0          
1047 0           v = x & 0x1F;
1048 0           i = 1;
1049             }
1050 0 0         else if(x & 0xE0 && !(x & 0x10)) { /* 1110xxxx */
    0          
1051 0           v = x & 0x0F;
1052 0           i = 2;
1053             }
1054 0 0         else if(x & 0xF0 && !(x & 0x08)) { /* 11110xxx */
    0          
1055 0           v = x & 0x07;
1056 0           i = 3;
1057             }
1058 0 0         else if(x & 0xF8 && !(x & 0x04)) { /* 111110xx */
    0          
1059 0           v = x & 0x03;
1060 0           i = 4;
1061             }
1062 0 0         else if(x & 0xFC && !(x & 0x02)) { /* 1111110x */
    0          
1063 0           v = x & 0x01;
1064 0           i = 5;
1065             }
1066             else {
1067 0           *val = 0xffffffff;
1068 0           return 1;
1069             }
1070              
1071 156 50         for( ; i; i--) {
1072 0           x = raw[(*rawlen)++];
1073 0 0         if(!(x & 0x80) || (x & 0x40)) { /* 10xxxxxx */
    0          
1074 0           *val = 0xffffffff;
1075 0           return 1;
1076             }
1077 0           v <<= 6;
1078 0           v |= (x & 0x3F);
1079             }
1080 156           *val = v;
1081 156           return 1;
1082             }
1083              
1084             void
1085 15           _flac_skip(flacinfo *flac, uint32_t size)
1086             {
1087 15 100         if ( buffer_len(flac->buf) >= size ) {
1088 2           buffer_consume(flac->buf, size);
1089              
1090             DEBUG_TRACE(" skipped buffer data size %d\n", size);
1091             }
1092             else {
1093 13           PerlIO_seek(flac->infile, size - buffer_len(flac->buf), SEEK_CUR);
1094 13           buffer_clear(flac->buf);
1095              
1096             DEBUG_TRACE(" seeked past %d bytes to %d\n", size, (int)PerlIO_tell(flac->infile));
1097             }
1098 15           }