Added a vector to hold the indices over INDEX 01. Previously matroska didn't allow for more than INDEX 00 and INDEX 01 for a track, now it allows for [INDEX 00 - INDEX 99], inclusive, bringing it in compliance with the Red Book specification for audio CDs. Patch by Vegard Pettersen <vegard_p at broadpark adot no>.

This commit is contained in:
Moritz Bunkus 2004-09-30 18:34:27 +00:00
parent 84e25ea39f
commit ac2ecf55df
3 changed files with 76 additions and 76 deletions

View File

@ -1,3 +1,10 @@
2004-09-30 Moritz Bunkus <moritz@bunkus.org>
* mkvmerge: new feature: The CUE sheet parser now accepts INDEX
lines with indices from 00 up to 99 and implements the Red Book
specification for audio CDs that way. Patch by Vegard Pettersen
<vegard_p at broadpark adot no>.
2004-09-28 Moritz Bunkus <moritz@bunkus.org>
* mkvmerge, mkvextract: bug fix: ASS was handled like SSA which is

View File

@ -104,8 +104,9 @@ cue_entries_to_chapter_name(string &performer,
typedef struct {
int num;
int64_t start_00;
int64_t start_01;
int64_t start_of_track;
vector<int64_t> start_indices;
bool index00_missing;
int64_t end;
int64_t min_tc;
int64_t max_tc;
@ -245,28 +246,18 @@ static void
add_subchapters_for_index_entries(cue_parser_args_t &a) {
KaxChapterAtom *atom;
KaxChapterDisplay *display;
int i, offset;
if ((a.start_00 == -1) && (a.start_01 == -1))
if (a.start_indices.empty())
return;
if (a.index00_missing)
offset = 1;
else
offset = 0;
atom = NULL;
if (a.start_00 != -1) {
atom = &GetChild<KaxChapterAtom>(*a.atom);
*static_cast<EbmlUInteger *>(&GetChild<KaxChapterUID>(*atom)) =
create_unique_uint32(UNIQUE_CHAPTER_IDS);
*static_cast<EbmlUInteger *>(&GetChild<KaxChapterTimeStart>(*atom)) =
a.start_00 - a.offset;
display = &GetChild<KaxChapterDisplay>(*atom);
*static_cast<EbmlUnicodeString *>(&GetChild<KaxChapterString>(*display)) =
cstrutf8_to_UTFstring("INDEX 00");
*static_cast<EbmlString *>(&GetChild<KaxChapterLanguage>(*display)) =
"eng";
*static_cast<EbmlUInteger *>(&GetChild<KaxChapterFlagHidden>(*atom)) = 1;
}
if (a.start_01 != -1) {
for (i = 0; i < a.start_indices.size(); i++) {
if (atom == NULL)
atom = &GetChild<KaxChapterAtom>(*a.atom);
else
@ -275,11 +266,11 @@ add_subchapters_for_index_entries(cue_parser_args_t &a) {
*static_cast<EbmlUInteger *>(&GetChild<KaxChapterUID>(*atom)) =
create_unique_uint32(UNIQUE_CHAPTER_IDS);
*static_cast<EbmlUInteger *>(&GetChild<KaxChapterTimeStart>(*atom)) =
a.start_01 - a.offset;
a.start_indices[i] - a.offset;
display = &GetChild<KaxChapterDisplay>(*atom);
*static_cast<EbmlUnicodeString *>(&GetChild<KaxChapterString>(*display)) =
cstrutf8_to_UTFstring("INDEX 01");
cstrutf8_to_UTFstring(mxsprintf("INDEX %02d", i + offset).c_str());
*static_cast<EbmlString *>(&GetChild<KaxChapterLanguage>(*display)) =
"eng";
@ -293,17 +284,12 @@ add_elements_for_cue_entry(cue_parser_args_t &a,
KaxChapterDisplay *display;
UTFstring wchar_string;
uint32_t cuid;
int64_t start;
if ((a.start_00 == -1) && (a.start_01 == -1))
if (a.start_indices.empty())
mxerror("Cue sheet parser: No INDEX entry found for the previous "
"TRACK entry (current line: %d)\n", a.line_num);
if (a.start_01 != -1)
start = a.start_01;
else
start = a.start_00;
if (!((start >= a.min_tc) && ((start <= a.max_tc) || (a.max_tc == -1))))
if (!((a.start_indices[0] >= a.min_tc) &&
((a.start_indices[0] <= a.max_tc) || (a.max_tc == -1))))
return;
if (a.edition == NULL) {
@ -320,7 +306,7 @@ add_elements_for_cue_entry(cue_parser_args_t &a,
*static_cast<EbmlUInteger *>(&GetChild<KaxChapterUID>(*a.atom)) = cuid;
*static_cast<EbmlUInteger *>(&GetChild<KaxChapterTimeStart>(*a.atom)) =
start - a.offset;
a.start_of_track - a.offset;
display = &GetChild<KaxChapterDisplay>(*a.atom);
@ -378,7 +364,6 @@ parse_cue_chapters(mm_text_io_c *in,
const char *charset,
bool exception_on_error,
KaxTags **tags) {
int index, min, sec, frames;
cue_parser_args_t a;
string line;
@ -407,8 +392,7 @@ parse_cue_chapters(mm_text_io_c *in,
a.edition = NULL;
a.num = 0;
a.line_num = 0;
a.start_00 = -1;
a.start_01 = -1;
a.start_of_track = -1;
a.edition_uid = create_unique_uint32(UNIQUE_EDITION_IDS);
try {
while (in->getline2(line)) {
@ -433,22 +417,39 @@ parse_cue_chapters(mm_text_io_c *in,
a.title = get_quoted(line, 6);
} else if (starts_with_case(line, "index ")) {
int index, min, sec, frames;
bool index_ok;
line.erase(0, 6);
strip(line);
if (sscanf(line.c_str(), "%d %d:%d:%d", &index, &min, &sec, &frames) <
4)
mxerror("Cue sheet parser: Invalid INDEX entry in line %d.\n",
a.line_num);
if ((a.start_00 == -1) && (index == 0))
a.start_00 = min * 60 * 1000000000ll + sec * 1000000000ll + frames *
1000000000ll / 75;
else if ((a.start_01 == -1) && (index == 1))
a.start_01 = min * 60 * 1000000000ll + sec * 1000000000ll + frames *
1000000000ll / 75;
index_ok = false;
if ((index >= 0) && (index <= 99)) {
if ((a.start_indices.size() == 0) && (index == 1))
a.index00_missing = true;
if ((a.start_indices.size() == index) ||
((a.start_indices.size() == (index - 1)) && a.index00_missing)) {
int64_t timestamp = min * 60 * 1000000000ll + sec * 1000000000ll +
frames * 1000000000ll / 75;
a.start_indices.push_back(timestamp);
if ((index == 1) || (index == 0))
a.start_of_track = timestamp;
index_ok = true;
}
}
if (!index_ok)
mxerror("Cue sheet parser: Invalid INDEX number (got %d, "
"expected %d) in line %d,\n",
index, a.start_indices.size(), a.line_num);
} else if (starts_with_case(line, "track ")) {
if ((line.length() < 5) || strcasecmp(&line[line.length() - 5],
"audio"))
if ((line.length() < 5) ||
strcasecmp(&line[line.length() - 5], "audio"))
continue;
if (a.num >= 1)
@ -457,9 +458,9 @@ parse_cue_chapters(mm_text_io_c *in,
add_tag_for_global_cue_settings(a, tags);
a.num++;
a.start_00 = -1;
a.start_01 = -1;
a.start_of_track = -1;
a.start_indices.clear();
a.index00_missing = false;
a.performer = "";
a.title = "";
a.isrc = "";

View File

@ -182,7 +182,7 @@ get_chapter_index(int idx,
int i;
string sidx;
sidx = mxsprintf("INDEX 0%d", idx);
sidx = mxsprintf("INDEX %02d", idx);
for (i = 0; i < atom.ListSize(); i++)
if ((EbmlId(*atom[i]) == KaxChapterAtom::ClassInfos.GlobalId) &&
(get_chapter_name(*static_cast<KaxChapterAtom *>(atom[i])) == sidx))
@ -281,9 +281,10 @@ write_cuesheet(const char *file_name,
mm_io_c &out) {
KaxTag *tag;
string s;
int i;
int64_t index_00, index_01;
int i, j;
int64_t temp_index;
vector<int64_t> indices;
if (chapters.ListSize() == 0)
return;
@ -311,37 +312,28 @@ write_cuesheet(const char *file_name,
print_if_available("ARTIST", " PERFORMER \"%s\"\n");
print_if_available("ISRC", " ISRC %s\n");
print_if_available("CDAUDIO_TRACK_FLAGS", " FLAGS %s\n");
index_00 = get_chapter_index(0, atom);
index_01 = get_chapter_index(1, atom);
if (index_01 == -1) {
index_01 = get_chapter_start(atom);
if (index_01 == -1)
index_01 = 0;
}
if (index_00 != -1)
out.printf(" INDEX 00 %02lld:%02lld:%02lld\n",
index_00 / 1000000 / 1000 / 60,
(index_00 / 1000000 / 1000) % 60,
irnd((double)(index_00 % 1000000000ll) * 75.0 /
j = 0;
do {
if ((temp_index = get_chapter_index(j, atom)) != -1)
indices.push_back(temp_index);
j++;
} while ((temp_index != -1) && (j <= 99));
for (j = 0; j < indices.size(); j++) {
out.printf(" INDEX %02d %02lld:%02lld:%02lld\n",
j,
indices[j] / 1000000 / 1000 / 60,
(indices[j] / 1000000 / 1000) % 60,
irnd((double)(indices[j] % 1000000000ll) * 75.0 /
1000000000.0));
out.printf(" INDEX 01 %02lld:%02lld:%02lld\n",
index_01 / 1000000 / 1000 / 60,
(index_01 / 1000000 / 1000) % 60,
irnd((double)(index_01 % 1000000000ll) * 75.0 /
1000000000.0));
}
indices.clear();
print_if_available("DATE", " REM DATE \"%s\"\n");
print_if_available("GENRE", " REM GENRE \"%s\"\n");
print_comments(" ", *tag, out);
} else {
index_01 = get_chapter_start(atom);
out.printf(" TITLE \"%s\"\n",
get_chapter_name(atom).c_str());
out.printf(" INDEX 01 %02lld:%02lld:%02lld\n",
index_01 / 1000000 / 1000 / 60,
(index_01 / 1000000 / 1000) % 60,
irnd((double)(index_01 % 1000000000ll) * 75.0 /
1000000000.0));
}
}
}
}