diff --git a/packager/mpd/base/simple_mpd_notifier.cc b/packager/mpd/base/simple_mpd_notifier.cc index 9faa0bb73e..1449ad9e3d 100644 --- a/packager/mpd/base/simple_mpd_notifier.cc +++ b/packager/mpd/base/simple_mpd_notifier.cc @@ -6,6 +6,8 @@ #include "packager/mpd/base/simple_mpd_notifier.h" +#include + #include "packager/base/logging.h" #include "packager/base/stl_util.h" #include "packager/mpd/base/adaptation_set.h" @@ -15,6 +17,17 @@ #include "packager/mpd/base/period.h" #include "packager/mpd/base/representation.h" +DEFINE_int32( + pto_adjustment, + -1, + "There could be rounding errors in MSE which could cut the first key frame " + "of the representation and thus cut all the frames until the next key " + "frame, which then leads to a big gap in presentation timeline which " + "stalls playback. A small back off may be necessary to compensate for the " + "possible rounding error. It should not cause any playback issues if it is " + "small enough. The workaround can be removed once the problem is handled " + "in all players."); + namespace shaka { SimpleMpdNotifier::SimpleMpdNotifier(const MpdOptions& mpd_options) @@ -151,9 +164,13 @@ Representation* SimpleMpdNotifier::AddRepresentationToPeriod( Representation* representation = nullptr; if (original_representation) { + uint64_t presentation_time_offset = + period->start_time_in_seconds() * media_info.reference_time_scale(); + if (presentation_time_offset > 0) { + presentation_time_offset += FLAGS_pto_adjustment; + } representation = adaptation_set->CopyRepresentationWithTimeOffset( - *original_representation, - period->start_time_in_seconds() * media_info.reference_time_scale()); + *original_representation, presentation_time_offset); } else { representation = adaptation_set->AddRepresentation(media_info); } diff --git a/packager/mpd/base/simple_mpd_notifier_unittest.cc b/packager/mpd/base/simple_mpd_notifier_unittest.cc index 8469b7c1c4..3c212a44a3 100644 --- a/packager/mpd/base/simple_mpd_notifier_unittest.cc +++ b/packager/mpd/base/simple_mpd_notifier_unittest.cc @@ -4,6 +4,7 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd +#include #include #include #include @@ -16,6 +17,8 @@ #include "packager/mpd/base/simple_mpd_notifier.h" #include "packager/mpd/test/mpd_builder_test_helper.h" +DECLARE_int32(pto_adjustment); + namespace shaka { using ::testing::_; @@ -242,9 +245,10 @@ TEST_F(SimpleMpdNotifierTest, NotifyCueEvent) { EXPECT_CALL(*mock_period2, GetOrCreateAdaptationSet(EqualsProto(valid_media_info1_), _)) .WillOnce(Return(mock_adaptation_set2.get())); - EXPECT_CALL(*mock_adaptation_set2, - CopyRepresentationWithTimeOffset(Ref(*mock_representation), - kCueEventTimestamp)) + EXPECT_CALL( + *mock_adaptation_set2, + CopyRepresentationWithTimeOffset( + Ref(*mock_representation), kCueEventTimestamp + FLAGS_pto_adjustment)) .WillOnce(Return(mock_representation2.get())); EXPECT_TRUE(notifier.NotifyCueEvent(container_id, kCueEventTimestamp)); } diff --git a/packager/mpd/mpd.gyp b/packager/mpd/mpd.gyp index b5cd65a56d..a89a195652 100644 --- a/packager/mpd/mpd.gyp +++ b/packager/mpd/mpd.gyp @@ -57,6 +57,7 @@ '../base/base.gyp:base', '../file/file.gyp:file', '../media/base/media_base.gyp:media_base', + '../third_party/gflags/gflags.gyp:gflags', '../third_party/libxml/libxml.gyp:libxml', '../version/version.gyp:version', 'media_info_proto', @@ -103,6 +104,7 @@ '../media/test/media_test.gyp:run_tests_with_atexit_manager', '../testing/gmock.gyp:gmock', '../testing/gtest.gyp:gtest', + '../third_party/gflags/gflags.gyp:gflags', 'mpd_builder', 'mpd_mocks', 'mpd_util',