Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Update usage of minBufferTime according to the DASH spec #7616

Merged
merged 3 commits into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 0 additions & 13 deletions docs/tutorials/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,19 +191,6 @@ the ad blocker in compiled mode as well.

<hr>

**Q:** Why does some DASH content take a long time to start playback?

**A:** Shaka Player honors the `minBufferTime` field in DASH. If this field is
set to a large value, Shaka Player will buffer that much content before
beginning playback. To override this behavior and ignore the `minBufferTime`
field, we offer the following configuration:

```js
player.configure('manifest.dash.ignoreMinBufferTime', true);
```

<hr>

**Q:** My HLS stream is failing on Chrome, with a chunk demuxer append failed
error.

Expand Down
1 change: 0 additions & 1 deletion docs/tutorials/manifest-parser.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,6 @@ MyManifestParser.prototype.loadManifest_ = function(data) {

return {
presentationTimeline: timeline,
minBufferTime: 5, // seconds
offlineSessionIds: [],
variants: [
this.loadVariant_(true, true),
Expand Down
3 changes: 0 additions & 3 deletions docs/tutorials/network-and-buffering-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,6 @@ This is a minimum; if the stream's max segment size is longer than the

*NOTES:*
- *`rebufferingGoal` should always be less than `bufferingGoal`.*
avelad marked this conversation as resolved.
Show resolved Hide resolved
- *A DASH manifest's `minBufferTime`, if greater, overrides `rebufferingGoal`.*
- *You can ignore `minBufferTime` by setting the
`manifest.dash.ignoreMinBufferTime` configuration to true.*

All of these settings should be customized for your application. The default
values are very conservative.
Expand Down
6 changes: 0 additions & 6 deletions externs/shaka/manifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
* textStreams: !Array.<shaka.extern.Stream>,
* imageStreams: !Array.<shaka.extern.Stream>,
* offlineSessionIds: !Array.<string>,
* minBufferTime: number,
* sequenceMode: boolean,
* ignoreManifestTimestampsInSegmentsMode: boolean,
* type: string,
Expand Down Expand Up @@ -76,11 +75,6 @@
* @property {!Array.<string>} offlineSessionIds
* <i>Defaults to [].</i> <br>
* An array of EME sessions to load for offline playback.
* @property {number} minBufferTime
* <i>Defaults to 0.</i> <br>
* The minimum number of seconds of content that must be buffered before
* playback can begin. Can be overridden by a higher value from the Player
* configuration.
* @property {boolean} sequenceMode
* If true, we will append the media segments using sequence mode; that is to
* say, ignoring any timestamps inside the media files.
Expand Down
3 changes: 1 addition & 2 deletions externs/shaka/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -1104,8 +1104,7 @@ shaka.extern.xml.Node;
* Defaults to <code>false</code>.
* @property {boolean} ignoreMinBufferTime
* If true will cause DASH parser to ignore <code>minBufferTime</code> from
* manifest. It allows player config to take precedence over manifest for
* <code>rebufferingGoal</code>.
* manifest.
* <br>
* Defaults to <code>false</code>.
* @property {boolean} autoCorrectDrift
Expand Down
17 changes: 6 additions & 11 deletions lib/dash/dash_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -643,13 +643,6 @@ shaka.dash.DashParser = class {
}
this.manifestPatchContext_.availabilityTimeOffset = availabilityTimeOffset;

const ignoreMinBufferTime = this.config_.dash.ignoreMinBufferTime;
let minBufferTime = 0;
if (!ignoreMinBufferTime) {
minBufferTime =
TXml.parseAttr(mpd, 'minBufferTime', TXml.parseDuration) || 0;
}

this.updatePeriod_ = /** @type {number} */ (TXml.parseAttr(
mpd, 'minimumUpdatePeriod', TXml.parseDuration, -1));

Expand Down Expand Up @@ -702,6 +695,12 @@ shaka.dash.DashParser = class {
}
}
} else {
const ignoreMinBufferTime = this.config_.dash.ignoreMinBufferTime;
let minBufferTime = 0;
if (!ignoreMinBufferTime) {
minBufferTime =
TXml.parseAttr(mpd, 'minBufferTime', TXml.parseDuration) || 0;
}
// DASH IOP v3.0 suggests using a default delay between minBufferTime
// and timeShiftBufferDepth. This is literally the range of all
// feasible choices for the value. Nothing older than
Expand Down Expand Up @@ -799,10 +798,7 @@ shaka.dash.DashParser = class {

await contentSteeringPromise;

// Set minBufferTime to 0 for low-latency DASH live stream to achieve the
// best latency
if (this.lowLatencyMode_) {
minBufferTime = 0;
const presentationDelay = suggestedPresentationDelay != null ?
suggestedPresentationDelay : this.config_.defaultPresentationDelay;
presentationTimeline.setDelay(presentationDelay);
Expand All @@ -818,7 +814,6 @@ shaka.dash.DashParser = class {
textStreams: this.periodCombiner_.getTextStreams(),
imageStreams: this.periodCombiner_.getImageStreams(),
offlineSessionIds: [],
minBufferTime: minBufferTime || 0,
avelad marked this conversation as resolved.
Show resolved Hide resolved
sequenceMode: this.config_.dash.sequenceMode,
ignoreManifestTimestampsInSegmentsMode: false,
type: shaka.media.ManifestParser.DASH,
Expand Down
1 change: 0 additions & 1 deletion lib/hls/hls_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -1002,7 +1002,6 @@ shaka.hls.HlsParser = class {
textStreams,
imageStreams,
offlineSessionIds: [],
minBufferTime: 0,
sequenceMode: this.config_.hls.sequenceMode,
ignoreManifestTimestampsInSegmentsMode:
this.config_.hls.ignoreManifestTimestampsInSegmentsMode,
Expand Down
8 changes: 1 addition & 7 deletions lib/media/playhead.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,6 @@ shaka.media.MediaSourcePlayhead = class {
/** @private {shaka.media.PresentationTimeline} */
this.timeline_ = manifest.presentationTimeline;

/** @private {number} */
this.minBufferTime_ = manifest.minBufferTime || 0;

/** @private {?shaka.extern.StreamingConfiguration} */
this.config_ = config;

Expand Down Expand Up @@ -482,10 +479,7 @@ shaka.media.MediaSourcePlayhead = class {
const isBuffered = (playheadTime) => shaka.media.TimeRangesUtils.isBuffered(
this.mediaElement_.buffered, playheadTime);

const rebufferingGoal = Math.max(
this.minBufferTime_,
this.config_.rebufferingGoal);

const rebufferingGoal = this.config_.rebufferingGoal;
const safeSeekOffset = this.config_.safeSeekOffset;

let start = this.timeline_.getSeekRangeStart();
Expand Down
8 changes: 2 additions & 6 deletions lib/media/streaming_engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -779,9 +779,7 @@ shaka.media.StreamingEngine = class {
// If the new segment can be finished in time without risking a buffer
// underflow, we should abort the old one and switch.
const bufferedAhead = (bufferEnd || 0) - presentationTime;
const safetyBuffer = Math.max(
this.manifest_.minBufferTime || 0,
this.config_.rebufferingGoal);
const safetyBuffer = this.config_.rebufferingGoal;
const safeBufferedAhead = bufferedAhead - safetyBuffer;
if (timeToFetchNewSegment < safeBufferedAhead) {
return true;
Expand Down Expand Up @@ -1366,9 +1364,7 @@ shaka.media.StreamingEngine = class {
'bufferedAhead=' + bufferedAhead);

const unscaledBufferingGoal = Math.max(
this.manifest_.minBufferTime || 0,
this.config_.rebufferingGoal,
this.config_.bufferingGoal);
this.config_.rebufferingGoal, this.config_.bufferingGoal);

const scaledBufferingGoal = Math.max(1,
unscaledBufferingGoal * this.bufferingScale_);
Expand Down
1 change: 0 additions & 1 deletion lib/mss/mss_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,6 @@ shaka.mss.MssParser = class {
textStreams: context.textStreams,
imageStreams: [],
offlineSessionIds: [],
minBufferTime: 0,
sequenceMode: this.config_.mss.sequenceMode,
ignoreManifestTimestampsInSegmentsMode: false,
type: shaka.media.ManifestParser.MSS,
Expand Down
1 change: 0 additions & 1 deletion lib/offline/manifest_converter.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ shaka.offline.ManifestConverter = class {

return {
presentationTimeline: timeline,
minBufferTime: 2,
offlineSessionIds: manifestDB.sessionIds,
variants: Array.from(variants.values()),
textStreams: textStreams,
Expand Down
16 changes: 3 additions & 13 deletions lib/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -2638,13 +2638,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
this.playheadObservers_ =
this.createPlayheadObserversForMSE_(startTime);

// We need to start the buffer management code near the end because it
// will set the initial buffering state and that depends on other
// components being initialized.
const rebufferThreshold = Math.max(
this.manifest_.minBufferTime,
this.config_.streaming.rebufferingGoal);
this.startBufferManagement_(mediaElement, rebufferThreshold);
this.startBufferManagement_(
mediaElement, this.config_.streaming.rebufferingGoal);
};

if (!this.config_.streaming.startAtSegmentBoundary) {
Expand Down Expand Up @@ -4187,12 +4182,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
this.onAbrStatusChanged_();
}
if (this.bufferObserver_) {
let rebufferThreshold = this.config_.streaming.rebufferingGoal;
if (this.manifest_) {
rebufferThreshold =
Math.max(rebufferThreshold, this.manifest_.minBufferTime);
}
this.updateBufferingSettings_(rebufferThreshold);
this.updateBufferingSettings_(this.config_.streaming.rebufferingGoal);
}

if (this.manifest_) {
Expand Down
54 changes: 1 addition & 53 deletions test/dash/dash_parser_manifest_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,6 @@ describe('DashParser Manifest', () => {
manifest.sequenceMode = true;
manifest.type = shaka.media.ManifestParser.DASH;
manifest.anyTimeline();
manifest.minBufferTime = 75;
manifest.addPartialVariant((variant) => {
variant.language = 'en';
variant.bandwidth = 200;
Expand Down Expand Up @@ -256,7 +255,6 @@ describe('DashParser Manifest', () => {
manifest.sequenceMode = false;
manifest.type = shaka.media.ManifestParser.DASH;
manifest.anyTimeline();
manifest.minBufferTime = 75;
manifest.addPartialVariant((variant) => {
variant.language = 'en';
variant.bandwidth = 200;
Expand Down Expand Up @@ -1759,56 +1757,6 @@ describe('DashParser Manifest', () => {
expect(stream).toBeUndefined();
});

it('override manifest value if ignoreMinBufferTime is true', async () => {
const manifestText = [
'<MPD minBufferTime="PT75S">',
' <Period id="1" duration="PT30S">',
' <AdaptationSet id="1" mimeType="video/mp4">',
' <Representation id="video-sd" width="640" height="480">',
' <BaseURL>v-sd.mp4</BaseURL>',
' <SegmentBase indexRange="100-200" />',
' </Representation>',
' </AdaptationSet>',
' </Period>',
'</MPD>',
].join('\n');

fakeNetEngine.setResponseText('dummy://foo', manifestText);
const config = shaka.util.PlayerConfiguration.createDefault().manifest;
config.dash.ignoreMinBufferTime = true;
parser.configure(config);

/** @type {shaka.extern.Manifest} */
const manifest = await parser.start('dummy://foo', playerInterface);
const minBufferTime = manifest.minBufferTime;
expect(minBufferTime).toBe(0);
});

it('get manifest value if ignoreMinBufferTime is false', async () => {
const manifestText = [
'<MPD minBufferTime="PT75S">',
' <Period id="1" duration="PT30S">',
' <AdaptationSet id="1" mimeType="video/mp4">',
' <Representation id="video-sd" width="640" height="480">',
' <BaseURL>v-sd.mp4</BaseURL>',
' <SegmentBase indexRange="100-200" />',
' </Representation>',
' </AdaptationSet>',
' </Period>',
'</MPD>',
].join('\n');

fakeNetEngine.setResponseText('dummy://foo', manifestText);
const config = shaka.util.PlayerConfiguration.createDefault().manifest;
config.dash.ignoreMinBufferTime = false;
parser.configure(config);

/** @type {shaka.extern.Manifest} */
const manifest = await parser.start('dummy://foo', playerInterface);
const minBufferTime = manifest.minBufferTime;
expect(minBufferTime).toBe(75);
});

it('honors the ignoreMaxSegmentDuration config', async () => {
const manifestText = [
'<MPD maxSegmentDuration="PT5S">',
Expand Down Expand Up @@ -1944,7 +1892,7 @@ describe('DashParser Manifest', () => {
const manifest = await parser.start('dummy://foo', playerInterface);
const presentationTimeline = manifest.presentationTimeline;
const presentationDelay = presentationTimeline.getDelay();
expect(presentationDelay).toBe(1.5*manifest.minBufferTime);
expect(presentationDelay).toBe(3);
});

it('Honors the ignoreEmptyAdaptationSet config', async () => {
Expand Down
3 changes: 2 additions & 1 deletion test/media/playhead_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,6 @@ describe('Playhead', () => {
textStreams: [],
imageStreams: [],
presentationTimeline: timeline,
minBufferTime: 10,
offlineSessionIds: [],
sequenceMode: false,
ignoreManifestTimestampsInSegmentsMode: false,
Expand Down Expand Up @@ -405,6 +404,8 @@ describe('Playhead', () => {
timeline.getSeekRangeStart.and.returnValue(5);
timeline.getSeekRangeEnd.and.returnValue(60);

config.rebufferingGoal = 10;

playhead = new shaka.media.MediaSourcePlayhead(
video,
manifest,
Expand Down
1 change: 0 additions & 1 deletion test/media/streaming_engine_integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,6 @@ describe('StreamingEngine', () => {
return {
presentationTimeline: timeline,
offlineSessionIds: [],
minBufferTime: 2,
textStreams: [],
imageStreams: [],
sequenceMode: false,
Expand Down
6 changes: 0 additions & 6 deletions test/media/streaming_engine_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -2641,8 +2641,6 @@ describe('StreamingEngine', () => {
beforeEach(() => {
setupVod();

manifest.minBufferTime = 1;

config = shaka.util.PlayerConfiguration.createDefault().streaming;
config.rebufferingGoal = 1;
config.bufferingGoal = 1;
Expand Down Expand Up @@ -2752,8 +2750,6 @@ describe('StreamingEngine', () => {
it('does not fail immediately', async () => {
setupVod();

manifest.minBufferTime = 1;

// Create StreamingEngine.
const config = shaka.util.PlayerConfiguration.createDefault().streaming;
config.rebufferingGoal = 1;
Expand Down Expand Up @@ -2816,8 +2812,6 @@ describe('StreamingEngine', () => {
it('fails after multiple QuotaExceededError', async () => {
setupVod();

manifest.minBufferTime = 1;

// Create StreamingEngine.
const config = shaka.util.PlayerConfiguration.createDefault().streaming;
config.rebufferingGoal = 1;
Expand Down
1 change: 0 additions & 1 deletion test/offline/storage_compatibility_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,6 @@ filterDescribe('Storage Compatibility', offlineSupported, () => {

const expected = shaka.test.ManifestGenerator.generate((manifest) => {
manifest.anyTimeline();
manifest.minBufferTime = 2;

manifest.addPartialVariant((variant) => {
variant.addPartialStream(ContentType.VIDEO, (stream) => {
Expand Down
2 changes: 0 additions & 2 deletions test/test/util/manifest_generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,6 @@ shaka.test.ManifestGenerator.Manifest = class {
this.presentationTimeline = timeline;
/** @type {!Array.<string>} */
this.offlineSessionIds = [];
/** @type {number} */
this.minBufferTime = 0;
/** @type {boolean} */
this.sequenceMode = false;
/** @type {boolean} */
Expand Down
1 change: 0 additions & 1 deletion test/test/util/streaming_engine_util.js
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,6 @@ shaka.test.StreamingEngineUtil = class {
/** @type {shaka.extern.Manifest} */
const manifest = {
presentationTimeline,
minBufferTime: 2,
offlineSessionIds: [],
variants: [],
textStreams: [],
Expand Down
Loading