diff options
Diffstat (limited to 'firmware/mp3data.c')
-rw-r--r-- | firmware/mp3data.c | 96 |
1 files changed, 53 insertions, 43 deletions
diff --git a/firmware/mp3data.c b/firmware/mp3data.c index c2d4cd2c37..519bc60b04 100644 --- a/firmware/mp3data.c +++ b/firmware/mp3data.c | |||
@@ -406,7 +406,7 @@ int get_mp3file_info(int fd, struct mp3info *info) | |||
406 | /* Is it a VBR file? */ | 406 | /* Is it a VBR file? */ |
407 | info->is_vbr = info->is_xing_vbr = !memcmp(vbrheader, "Xing", 4); | 407 | info->is_vbr = info->is_xing_vbr = !memcmp(vbrheader, "Xing", 4); |
408 | 408 | ||
409 | if(vbrheader[7] & VBR_FRAMES_FLAG) /* Is the frame count there? */ | 409 | if (vbrheader[7] & VBR_FRAMES_FLAG) /* Is the frame count there? */ |
410 | { | 410 | { |
411 | info->frame_count = BYTES2INT(vbrheader[i], vbrheader[i+1], | 411 | info->frame_count = BYTES2INT(vbrheader[i], vbrheader[i+1], |
412 | vbrheader[i+2], vbrheader[i+3]); | 412 | vbrheader[i+2], vbrheader[i+3]); |
@@ -417,19 +417,24 @@ int get_mp3file_info(int fd, struct mp3info *info) | |||
417 | i += 4; | 417 | i += 4; |
418 | } | 418 | } |
419 | 419 | ||
420 | if(vbrheader[7] & VBR_BYTES_FLAG) /* Is byte count there? */ | 420 | if (vbrheader[7] & VBR_BYTES_FLAG) /* Is byte count there? */ |
421 | { | 421 | { |
422 | info->byte_count = BYTES2INT(vbrheader[i], vbrheader[i+1], | 422 | info->byte_count = BYTES2INT(vbrheader[i], vbrheader[i+1], |
423 | vbrheader[i+2], vbrheader[i+3]); | 423 | vbrheader[i+2], vbrheader[i+3]); |
424 | i += 4; | 424 | i += 4; |
425 | } | 425 | } |
426 | 426 | ||
427 | if(info->file_time && info->byte_count) | 427 | if (info->file_time && info->byte_count) |
428 | info->bitrate = info->byte_count * 8 / info->file_time; | 428 | { |
429 | if (info->byte_count <= (ULONG_MAX/8)) | ||
430 | info->bitrate = info->byte_count * 8 / info->file_time; | ||
431 | else | ||
432 | info->bitrate = info->byte_count / (info->file_time >> 3); | ||
433 | } | ||
429 | else | 434 | else |
430 | info->bitrate = 0; | 435 | info->bitrate = 0; |
431 | 436 | ||
432 | if(vbrheader[7] & VBR_TOC_FLAG) /* Is table-of-contents there? */ | 437 | if (vbrheader[7] & VBR_TOC_FLAG) /* Is table-of-contents there? */ |
433 | { | 438 | { |
434 | memcpy( info->toc, vbrheader+i, 100 ); | 439 | memcpy( info->toc, vbrheader+i, 100 ); |
435 | i += 100; | 440 | i += 100; |
@@ -492,7 +497,11 @@ int get_mp3file_info(int fd, struct mp3info *info) | |||
492 | info->file_time = info->frame_count * info->ft_num / info->ft_den; | 497 | info->file_time = info->frame_count * info->ft_num / info->ft_den; |
493 | else | 498 | else |
494 | info->file_time = info->frame_count / info->ft_den * info->ft_num; | 499 | info->file_time = info->frame_count / info->ft_den * info->ft_num; |
495 | info->bitrate = info->byte_count * 8 / info->file_time; | 500 | |
501 | if (info->byte_count <= (ULONG_MAX/8)) | ||
502 | info->bitrate = info->byte_count * 8 / info->file_time; | ||
503 | else | ||
504 | info->bitrate = info->byte_count / (info->file_time >> 3); | ||
496 | 505 | ||
497 | /* We don't parse the TOC, since we don't yet know how to (FIXME) */ | 506 | /* We don't parse the TOC, since we don't yet know how to (FIXME) */ |
498 | num_offsets = BYTES2INT(0, 0, vbrheader[18], vbrheader[19]); | 507 | num_offsets = BYTES2INT(0, 0, vbrheader[18], vbrheader[19]); |
@@ -587,37 +596,35 @@ int count_mp3_frames(int fd, int startpos, int filesize, | |||
587 | 596 | ||
588 | static const char cooltext[] = "Rockbox - rocks your box"; | 597 | static const char cooltext[] = "Rockbox - rocks your box"; |
589 | 598 | ||
590 | int create_xing_header(int fd, int startpos, int filesize, | 599 | /* buf needs to be the audio buffer with TOC generation enabled, |
591 | unsigned char *buf, /* must be at least 288 bytes */ | 600 | and at least MAX_XING_HEADER_SIZE bytes otherwise */ |
592 | int num_frames, unsigned long header_template, | 601 | int create_xing_header(int fd, long startpos, long filesize, |
602 | unsigned char *buf, unsigned long num_frames, | ||
603 | unsigned long rec_time, unsigned long header_template, | ||
593 | void (*progressfunc)(int), bool generate_toc) | 604 | void (*progressfunc)(int), bool generate_toc) |
594 | { | 605 | { |
595 | unsigned long header = 0; | ||
596 | struct mp3info info; | 606 | struct mp3info info; |
597 | int pos, last_pos; | 607 | unsigned char toc[100]; |
598 | int i, j; | 608 | unsigned long header = 0; |
599 | long bytes; | 609 | unsigned long xing_header_template = header_template; |
600 | unsigned long filepos; | 610 | unsigned long filepos; |
601 | int x; | 611 | long pos, last_pos; |
612 | long j; | ||
613 | long bytes; | ||
614 | int i; | ||
602 | int index; | 615 | int index; |
603 | unsigned char toc[100]; | ||
604 | unsigned long xing_header_template = 0; | ||
605 | 616 | ||
606 | DEBUGF("create_xing_header()\n"); | 617 | DEBUGF("create_xing_header()\n"); |
607 | 618 | ||
608 | if(header_template) | ||
609 | xing_header_template = header_template; | ||
610 | |||
611 | if(generate_toc) | 619 | if(generate_toc) |
612 | { | 620 | { |
613 | lseek(fd, startpos, SEEK_SET); | 621 | lseek(fd, startpos, SEEK_SET); |
614 | buf_init(); | 622 | buf_init(); |
615 | 623 | ||
616 | /* Generate filepos table */ | 624 | /* Generate filepos table */ |
617 | last_pos = 0; | 625 | last_pos = 0; |
618 | filepos = 0; | 626 | filepos = 0; |
619 | header = 0; | 627 | header = 0; |
620 | x = 0; | ||
621 | for(i = 0;i < 100;i++) { | 628 | for(i = 0;i < 100;i++) { |
622 | /* Calculate the absolute frame number for this seek point */ | 629 | /* Calculate the absolute frame number for this seek point */ |
623 | pos = i * num_frames / 100; | 630 | pos = i * num_frames / 100; |
@@ -654,7 +661,7 @@ int create_xing_header(int fd, int startpos, int filesize, | |||
654 | * the upper 8 bits of the file position are nonzero | 661 | * the upper 8 bits of the file position are nonzero |
655 | * (i.e. files over 16mb in size). | 662 | * (i.e. files over 16mb in size). |
656 | */ | 663 | */ |
657 | if (filepos > 0xFFFFFF) | 664 | if (filepos > (ULONG_MAX/256)) |
658 | { | 665 | { |
659 | /* instead of multiplying filepos by 256, we divide | 666 | /* instead of multiplying filepos by 256, we divide |
660 | * filesize by 256. | 667 | * filesize by 256. |
@@ -673,46 +680,49 @@ int create_xing_header(int fd, int startpos, int filesize, | |||
673 | } | 680 | } |
674 | } | 681 | } |
675 | 682 | ||
676 | /* Check the template header for validity and get some preliminary info. */ | 683 | /* Use the template header and create a new one. |
677 | if (!mp3headerinfo(&info, xing_header_template)) | 684 | We ignore the Protection bit even if the rest of the stream is |
685 | protected. */ | ||
686 | header = xing_header_template & ~(BITRATE_MASK|PROTECTION_MASK|PADDING_MASK); | ||
687 | header |= 8 << 12; /* This gives us plenty of space, 192..576 bytes */ | ||
688 | |||
689 | if (!mp3headerinfo(&info, header)) | ||
678 | return 0; /* invalid header */ | 690 | return 0; /* invalid header */ |
679 | 691 | ||
692 | if (num_frames == 0 && rec_time) { | ||
693 | /* estimate the number of frames based on the recording time */ | ||
694 | if (rec_time <= ULONG_MAX / info.ft_den) | ||
695 | num_frames = rec_time * info.ft_den / info.ft_num; | ||
696 | else | ||
697 | num_frames = rec_time / info.ft_num * info.ft_den; | ||
698 | } | ||
699 | |||
680 | /* Clear the frame */ | 700 | /* Clear the frame */ |
681 | memset(buf, 0, MAX_XING_HEADER_SIZE); | 701 | memset(buf, 0, MAX_XING_HEADER_SIZE); |
682 | 702 | ||
683 | /* Use the template header and create a new one. */ | 703 | /* Write the header to the buffer */ |
684 | header = xing_header_template & ~(BITRATE_MASK | PROTECTION_MASK); | 704 | long2bytes(buf, header); |
685 | 705 | ||
686 | /* Calculate position of VBR header and required frame bitrate */ | 706 | /* Calculate position of VBR header */ |
687 | if (info.version == MPEG_VERSION1) { | 707 | if (info.version == MPEG_VERSION1) { |
688 | header |= 5 << 12; | ||
689 | if (info.channel_mode == 3) /* mono */ | 708 | if (info.channel_mode == 3) /* mono */ |
690 | index = 21; | 709 | index = 21; |
691 | else | 710 | else |
692 | index = 36; | 711 | index = 36; |
693 | } | 712 | } |
694 | else { | 713 | else { |
695 | if (info.version == MPEG_VERSION2) | ||
696 | header |= 8 << 12; | ||
697 | else /* MPEG_VERSION2_5 */ | ||
698 | header |= 4 << 12; | ||
699 | if (info.channel_mode == 3) /* mono */ | 714 | if (info.channel_mode == 3) /* mono */ |
700 | index = 13; | 715 | index = 13; |
701 | else | 716 | else |
702 | index = 21; | 717 | index = 21; |
703 | } | 718 | } |
704 | mp3headerinfo(&info, header); /* Get final header info */ | ||
705 | /* Size is now always one of 192, 208 or 288 bytes */ | ||
706 | |||
707 | /* Write the header to the buffer */ | ||
708 | long2bytes(buf, header); | ||
709 | 719 | ||
710 | /* Create the Xing data */ | 720 | /* Create the Xing data */ |
711 | memcpy(&buf[index], "Xing", 4); | 721 | memcpy(&buf[index], "Xing", 4); |
712 | long2bytes(&buf[index+4], ((num_frames?VBR_FRAMES_FLAG:0) | | 722 | long2bytes(&buf[index+4], (num_frames ? VBR_FRAMES_FLAG : 0) |
713 | (filesize?VBR_BYTES_FLAG:0) | | 723 | | (filesize ? VBR_BYTES_FLAG : 0) |
714 | (generate_toc?VBR_TOC_FLAG:0))); | 724 | | (generate_toc ? VBR_TOC_FLAG : 0)); |
715 | index = index+8; | 725 | index += 8; |
716 | if(num_frames) | 726 | if(num_frames) |
717 | { | 727 | { |
718 | long2bytes(&buf[index], num_frames); | 728 | long2bytes(&buf[index], num_frames); |