From cbd9c7bf01e99478172e3ac5798201ed42fff0cf Mon Sep 17 00:00:00 2001 From: Moritz Bunkus Date: Sat, 16 Oct 2004 13:46:34 +0000 Subject: [PATCH] Always regenerate Vorbis timecodes. This is necessary because Vorbis is laced, and when reading it from Matroska the timestamps might come out wrong if the output has different lacing, e.g. when splitting is active. --- ChangeLog | 7 +++++ src/output/p_vorbis.cpp | 59 ++++++++++++++++++++++++++--------------- src/output/p_vorbis.h | 3 +-- tests/results.txt | 8 +++--- 4 files changed, 50 insertions(+), 27 deletions(-) diff --git a/ChangeLog b/ChangeLog index 855215603..2999c1be3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2004-10-16 Moritz Bunkus + + * mkvmerge: bug fix: Timecodes for Vorbis were wrong on rare + occasions (when reading laced Vorbis from a Matroska file and + changing the lacing, e.g. when splitting for the second and all + following files). + 2004-10-10 Moritz Bunkus * mkvmerge/mkvinfo/mkvextract: bug fix: The chapter and tag diff --git a/src/output/p_vorbis.cpp b/src/output/p_vorbis.cpp index f7b7a4476..181ccb841 100644 --- a/src/output/p_vorbis.cpp +++ b/src/output/p_vorbis.cpp @@ -45,9 +45,11 @@ vorbis_packetizer_c::vorbis_packetizer_c(generic_reader_c *nreader, generic_packetizer_c(nreader, nti) { int i; - packetno = 0; last_bs = 0; samples = 0; + timecode_offset = 0; + last_samples_sum = 0; + last_timecode = 0; memset(headers, 0, 3 * sizeof(ogg_packet)); headers[0].packet = (unsigned char *)safememdup(d_header, l_header); headers[1].packet = (unsigned char *)safememdup(d_comments, l_comments); @@ -144,12 +146,17 @@ vorbis_packetizer_c::process(memory_c &mem, int64_t) { unsigned char zero[2]; ogg_packet op; - int64_t this_bs, samples_here, samples_needed; + int64_t this_bs, samples_here, samples_needed, expected_timecode, duration; + int64_t chosen_timecode; debug_enter("vorbis_packetizer_c::process"); + // Remember the very first timecode we received. + if ((samples == 0) && (timecode > 0)) + timecode_offset = timecode; + // Positive displacement, first packet? Well then lets create silence. - if ((packetno == 0) && (initial_displacement > 0)) { + if ((samples == 0) && (initial_displacement > 0)) { // Create a fake packet so we can use vorbis_packet_blocksize(). zero[0] = 0; zero[1] = 0; @@ -172,37 +179,47 @@ vorbis_packetizer_c::process(memory_c &mem, } } - // Recalculate the timecode if needed. - if (timecode == -1) { - if (initial_displacement > 0) - timecode = samples * 1000000000 / vi.rate; - else - timecode = samples * 1000000000 / vi.rate + initial_displacement; - } else - timecode += initial_displacement; - - // Handle the linear sync - simply multiply with the given factor. - timecode = (int64_t)((double)timecode * ti->async.linear); - // Update the number of samples we have processed so that we can // calculate the timecode on the next call. op.packet = mem.data; op.bytes = mem.size; this_bs = vorbis_packet_blocksize(&vi, &op); samples_here = (this_bs + last_bs) / 4; - samples += samples_here; last_bs = this_bs; + samples += samples_here; + + expected_timecode = last_timecode + last_samples_sum * 1000000000 / vi.rate + + timecode_offset; + if (initial_displacement < 0) + expected_timecode += initial_displacement; + + if (timecode > (expected_timecode + 100000000)) { + chosen_timecode = timecode; + duration = timecode - last_timecode; + last_timecode = timecode; + last_samples_sum = 0; + } else { + chosen_timecode = expected_timecode; + duration = (int64_t)(samples_here * 1000000000 * ti->async.linear / + vi.rate); + } + + last_samples_sum += samples_here; + + // Handle the linear sync - simply multiply with the given factor. + chosen_timecode = (int64_t)((double)chosen_timecode * ti->async.linear); // If a negative sync value was used we may have to skip this packet. - if (timecode < 0) { + if (chosen_timecode < 0) { debug_leave("vorbis_packetizer_c::process"); return EMOREDATA; } - mxverb(2, "Vorbis: samples_here: %lld\n", samples_here); - add_packet(mem, (int64_t)timecode, - (int64_t)(samples_here * 1000000000 * ti->async.linear / - vi.rate)); + mxverb(2, "Vorbis: samples_here at %lld (orig %lld expected %lld): %lld " + "(last_samples_sum: %lld)\n", + chosen_timecode, timecode, expected_timecode, + samples_here, last_samples_sum); + add_packet(mem, expected_timecode, duration); debug_leave("vorbis_packetizer_c::process"); diff --git a/src/output/p_vorbis.h b/src/output/p_vorbis.h index 7c1d8065a..89d9ca1ad 100644 --- a/src/output/p_vorbis.h +++ b/src/output/p_vorbis.h @@ -29,8 +29,7 @@ class vorbis_packetizer_c: public generic_packetizer_c { private: - int64_t last_bs, samples; - int packetno; + int64_t last_bs, samples, last_samples_sum, last_timecode, timecode_offset; vorbis_info vi; vorbis_comment vc; ogg_packet headers[3]; diff --git a/tests/results.txt b/tests/results.txt index d6f4a6718..79133cb59 100644 --- a/tests/results.txt +++ b/tests/results.txt @@ -17,14 +17,14 @@ T_016cuesheet:e2e88f91b6bf6ff411f4984ce7d89e35:passed:20040825-175700 T_017chapters:990b4b6b0931b7d52e589f715c919e10-4fff45a76f54708f881312aca04fd887:passed:20040825-175700 T_018attachments:bac27359516bab4984df3021aa295213-7e8e1f17615f157db0e98fba9ad88bad:passed:20040825-175700 T_019attachments2:8d9ba46c4edbf3daf50175f9de2f87b4-94349d68c9b7d493ec0d5a49f7291e40-8d9ba46c4edbf3daf50175f9de2f87b4-5c639e8a08cf526d051fdf64f856c0d2:passed:20040825-175700 -T_020languages:dc8b8792f86ac4e92e70154faef990a7:passed:20040825-234208 +T_020languages:7d853f21fe2d3e73b3ca0d29801e8d39:passed:20040825-234208 T_021aspect_ratio:f6e8aa4cfd776d99ff824f21d4e3c640-990a5f94678b5c8886dc8c3a5c6a22dd:passed:20040825-234244 T_022display_dimensions:108880396ffe5244465a3d25e8a57f93:passed:20040825-234339 -T_023no_x:0b7f257f1c801da7b2ef1976291e5d44-39f690e6a11bc2e32b54334e67374feb-2662148f7a3d60c152c92ad9a9d5e672:passed:20040825-234343 +T_023no_x:0b7f257f1c801da7b2ef1976291e5d44-49870185a891e8b3f6f265dca6f0e707-c43a34f68db19f5a318bd90c6f6446ab:passed:20040825-234343 T_024sync_mp3:a6c35d309947a52196d2a5428f87224a-6a638028d795bd48db95446f3521c302:passed:20040825-234344 -T_025sync_vorbis:e9d13a6b769cf6c2e4987bf6bd160698-51fcfab150642a66484d3c6bedff697a:passed:20040825-234344 +T_025sync_vorbis:e9d13a6b769cf6c2e4987bf6bd160698-51fcfab150642a66484d3c6bedff697a:failed:20040825-234344 T_026sync_pcm:f337f057c059d771128206c0da3d4807-9b559191edb65655e49186c302c4b815:passed:20040825-234346 -T_027default_track:e3177712483af5b129bbeb9cf0e6a820:passed:20040825-234348 +T_027default_track:5e3cdf80eff356e84a94c877f6514b02:passed:20040825-234348 T_028compression:f6c15855e42e5a0e80d22a2060ae13e8:passed:20040825-234348 T_029link:d92e5f123b799212f65bb7b394dd4f6e:passed:20040825-235039 T_032cues:f84c58a6380b3104434b6943e0eb87e3:passed:20040825-235040