diff --git a/ChangeLog b/ChangeLog index 9d0b3c475..552a8dd8e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2004-08-01 Moritz Bunkus + * mkvmerge: bug fix: Handle TTA files with ID3 tags correctly ( = + skip the ID3 tags). + * mkvmerge: bug fix: There was an illegal free() in the OGM reader. diff --git a/src/common/id3_common.cpp b/src/common/id3_common.cpp new file mode 100644 index 000000000..93d0842fc --- /dev/null +++ b/src/common/id3_common.cpp @@ -0,0 +1,106 @@ +/* + * mkvmerge -- utility for splicing together matroska files + * from component media subtypes + * + * Distributed under the GPL + * see the file COPYING for details + * or visit http://www.gnu.org/copyleft/gpl.html + * + * $Id$ + * + * helper functions for ID3 tags + * + * Written by Moritz Bunkus . + */ + +#include "os.h" + +#include "mm_io.h" + +int +skip_id3v2_tag(mm_io_c &io) { + unsigned char buffer[10]; + int tag_size; + + io.setFilePointer(0, seek_beginning); + if (io.read(buffer, 10) != 10) { + io.setFilePointer(0, seek_beginning); + return -1; + } + + if (strncmp((char *)buffer, "ID3", 3) || + (buffer[3] == 0xff) || (buffer[4] == 0xff) || + (buffer[6] >= 0x80) || (buffer[7] >= 0x80) || + (buffer[7] >= 0x80) || (buffer[8] >= 0x80)) { + io.setFilePointer(0, seek_beginning); + return 0; + } + + tag_size = (buffer[6] << 21) | (buffer[7] << 14) | (buffer[8] << 7) | + buffer[9]; + tag_size += 10; // tag header + if ((buffer[5] & 0x10) != 0) + tag_size += 10; // footer present + + io.setFilePointer(tag_size, seek_beginning); + if (io.getFilePointer() == tag_size) + return tag_size; + + io.setFilePointer(0, seek_beginning); + return -1; +} + +int +id3v2_tag_present_at_end(mm_io_c &io) { + unsigned char buffer[10]; + int tag_size; + + io.save_pos(); + io.setFilePointer(-10, seek_end); + if (io.read(buffer, 10) != 10) { + io.restore_pos(); + return 0; + } + + if (strncmp((char *)buffer, "3DI", 3) || + (buffer[3] == 0xff) || (buffer[4] == 0xff) || + (buffer[6] >= 0x80) || (buffer[7] >= 0x80) || + (buffer[7] >= 0x80) || (buffer[8] >= 0x80)) { + io.restore_pos(); + return 0; + } + + tag_size = (buffer[6] << 21) | (buffer[7] << 14) | (buffer[8] << 7) | + buffer[9]; + tag_size += 10; // tag header + tag_size += 10; // tag footer + + io.restore_pos(); + + return tag_size; +} + +int +id3v1_tag_present_at_end(mm_io_c &io) { + unsigned char buffer[3]; + + if (io.get_size() < 128) + return 0; + io.save_pos(); + io.setFilePointer(-128, seek_end); + if (io.read(buffer, 3) != 3) { + io.restore_pos(); + return 0; + } + io.restore_pos(); + if (strncmp((char *)buffer, "TAG", 3) == 0) + return 128; + return 0; +} + +int +id3_tag_present_at_end(mm_io_c &io) { + if (id3v1_tag_present_at_end(io)) + return 128; + return id3v2_tag_present_at_end(io); +} diff --git a/src/common/id3_common.h b/src/common/id3_common.h new file mode 100644 index 000000000..7f77ca436 --- /dev/null +++ b/src/common/id3_common.h @@ -0,0 +1,28 @@ +/* + * mkvmerge -- utility for splicing together matroska files + * from component media subtypes + * + * Distributed under the GPL + * see the file COPYING for details + * or visit http://www.gnu.org/copyleft/gpl.html + * + * $Id$ + * + * helper functions for ID3 tags + * + * Written by Moritz Bunkus . + */ + +#ifndef __ID3_COMMON_H +#define __ID3_COMMON_H + +#include "os.h" + +class mm_io_c; + +int MTX_DLL_API skip_id3v2_tag(mm_io_c &io); +int MTX_DLL_API id3v1_tag_present_at_end(mm_io_c &io); +int MTX_DLL_API id3v2_tag_present_at_end(mm_io_c &io); +int MTX_DLL_API id3_tag_present_at_end(mm_io_c &io); + +#endif /* __ID3_COMMON_H */ diff --git a/src/input/r_tta.cpp b/src/input/r_tta.cpp index 74fe005c8..ea27da2aa 100644 --- a/src/input/r_tta.cpp +++ b/src/input/r_tta.cpp @@ -21,20 +21,25 @@ #include "mkvmerge.h" #include "common.h" #include "error.h" +#include "id3_common.h" #include "p_tta.h" #include "r_tta.h" int tta_reader_c::probe_file(mm_io_c *mm_io, int64_t size) { + int tag_size; unsigned char buf[4]; if (size < 26) return 0; try { mm_io->setFilePointer(0, seek_beginning); + tag_size = skip_id3v2_tag(*mm_io); + if (tag_size == -1) + return 0; if (mm_io->read(buf, 4) != 4) - mm_io->setFilePointer(0, seek_beginning); + return 0; mm_io->setFilePointer(0, seek_beginning); } catch (exception &ex) { return 0; @@ -49,6 +54,7 @@ tta_reader_c::tta_reader_c(track_info_c *nti) generic_reader_c(nti) { uint32_t seek_point; int64_t seek_sum; + int tag_size; try { mm_io = new mm_io_c(ti->fname, MODE_READ); @@ -57,10 +63,17 @@ tta_reader_c::tta_reader_c(track_info_c *nti) if (identifying) return; + tag_size = skip_id3v2_tag(*mm_io); + if (tag_size < 0) + mxerror(_("tta_reader: tag_size < 0 in the c'tor. %s\n"), BUGMSG); + size -= tag_size; + if (mm_io->read(&header, sizeof(tta_file_header_t)) != sizeof(tta_file_header_t)) mxerror(FMT_FN "The file header is too short.\n", ti->fname); - seek_sum = mm_io->getFilePointer() + 4; + seek_sum = mm_io->getFilePointer() + 4 - tag_size; + + size -= id3_tag_present_at_end(*mm_io); do { seek_point = mm_io->read_uint32();