Workaround for possible rounding errors in MSE

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.

Adjusting presentationTimeOffset (PTO) by -1, i.e. backing off PTO by 1
to compensate for the possible rounding error. It should not cause any
playback issues as it is small enough. The workaround can be removed
once the problem is handled in all players.

The PTO adjustment is configurable with command line flag:
 --pto_adjustment, with value set to -1 by default.

b/71808910

Change-Id: I9c4d1e2ee84008b859a3638a8146c910cead1f15
This commit is contained in:
KongQun Yang 2018-01-17 17:26:03 -08:00
parent c9fb2b4a85
commit b74e511f29
3 changed files with 28 additions and 5 deletions

View File

@ -6,6 +6,8 @@
#include "packager/mpd/base/simple_mpd_notifier.h"
#include <gflags/gflags.h>
#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);
}

View File

@ -4,6 +4,7 @@
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#include <gflags/gflags.h>
#include <gmock/gmock.h>
#include <google/protobuf/util/message_differencer.h>
#include <gtest/gtest.h>
@ -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));
}

View File

@ -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',