Prevent trimming buffer between segment boundaries (#773)
* add trimBuffer_ helper function to streamline loadSegment
Showing
2 changed files
with
48 additions
and
7 deletions
... | @@ -503,14 +503,16 @@ export default class SegmentLoader extends videojs.EventTarget { | ... | @@ -503,14 +503,16 @@ export default class SegmentLoader extends videojs.EventTarget { |
503 | } | 503 | } |
504 | 504 | ||
505 | /** | 505 | /** |
506 | * load a specific segment from a request into the buffer | 506 | * trim the back buffer so we only remove content |
507 | * on segment boundaries | ||
507 | * | 508 | * |
508 | * @private | 509 | * @private |
510 | * | ||
511 | * @param {Object} segmentInfo - the current segment | ||
512 | * @returns {Number} removeToTime - the end point in time, in seconds | ||
513 | * that the the buffer should be trimmed. | ||
509 | */ | 514 | */ |
510 | loadSegment_(segmentInfo) { | 515 | trimBuffer_(segmentInfo) { |
511 | let segment; | ||
512 | let keyXhr; | ||
513 | let segmentXhr; | ||
514 | let seekable = this.seekable_(); | 516 | let seekable = this.seekable_(); |
515 | let currentTime = this.currentTime_(); | 517 | let currentTime = this.currentTime_(); |
516 | let removeToTime = 0; | 518 | let removeToTime = 0; |
... | @@ -531,6 +533,43 @@ export default class SegmentLoader extends videojs.EventTarget { | ... | @@ -531,6 +533,43 @@ export default class SegmentLoader extends videojs.EventTarget { |
531 | removeToTime = currentTime - 60; | 533 | removeToTime = currentTime - 60; |
532 | } | 534 | } |
533 | 535 | ||
536 | // If we are going to remove time from the front of the buffer, make | ||
537 | // sure we aren't discarding a partial segment to avoid throwing | ||
538 | // PLAYER_ERR_TIMEOUT while trying to read a partially discarded segment | ||
539 | for (let i = 0; i <= segmentInfo.playlist.segments.length; i++) { | ||
540 | // Loop through the segments and calculate the duration to compare | ||
541 | // against the removeToTime | ||
542 | let removeDuration = duration(segmentInfo.playlist, | ||
543 | segmentInfo.playlist.mediaSequence + i, | ||
544 | this.expired_); | ||
545 | |||
546 | // If we are close to next segment begining, remove to end of previous | ||
547 | // segment instead | ||
548 | let previousDuration = duration(segmentInfo.playlist, | ||
549 | segmentInfo.playlist.mediaSequence + (i - 1), | ||
550 | this.expired_); | ||
551 | |||
552 | if (removeDuration >= removeToTime) { | ||
553 | removeToTime = previousDuration; | ||
554 | break; | ||
555 | } | ||
556 | } | ||
557 | return removeToTime; | ||
558 | } | ||
559 | |||
560 | /** | ||
561 | * load a specific segment from a request into the buffer | ||
562 | * | ||
563 | * @private | ||
564 | */ | ||
565 | loadSegment_(segmentInfo) { | ||
566 | let segment; | ||
567 | let keyXhr; | ||
568 | let segmentXhr; | ||
569 | let removeToTime = 0; | ||
570 | |||
571 | removeToTime = this.trimBuffer_(segmentInfo); | ||
572 | |||
534 | if (removeToTime > 0) { | 573 | if (removeToTime > 0) { |
535 | this.sourceUpdater_.remove(0, removeToTime); | 574 | this.sourceUpdater_.remove(0, removeToTime); |
536 | } | 575 | } | ... | ... |
... | @@ -2016,7 +2016,9 @@ QUnit.test('cleans up the buffer when loading live segments', function() { | ... | @@ -2016,7 +2016,9 @@ QUnit.test('cleans up the buffer when loading live segments', function() { |
2016 | QUnit.strictEqual(this.requests[0].url, 'liveStart30sBefore.m3u8', | 2016 | QUnit.strictEqual(this.requests[0].url, 'liveStart30sBefore.m3u8', |
2017 | 'master playlist requested'); | 2017 | 'master playlist requested'); |
2018 | QUnit.equal(removes.length, 1, 'remove called'); | 2018 | QUnit.equal(removes.length, 1, 'remove called'); |
2019 | QUnit.deepEqual(removes[0], [0, seekable.start(0)], | 2019 | // segment-loader removes up to the segment prior to seekable.start |
2020 | // to avoid crossing segment-boundaries | ||
2021 | QUnit.deepEqual(removes[0], [0, seekable.start(0) - 10], | ||
2020 | 'remove called with the right range'); | 2022 | 'remove called with the right range'); |
2021 | 2023 | ||
2022 | // verify stats | 2024 | // verify stats |
... | @@ -2071,7 +2073,7 @@ QUnit.test('cleans up the buffer based on currentTime when loading a live segmen | ... | @@ -2071,7 +2073,7 @@ QUnit.test('cleans up the buffer based on currentTime when loading a live segmen |
2071 | 2073 | ||
2072 | QUnit.strictEqual(this.requests[0].url, 'liveStart30sBefore.m3u8', 'master playlist requested'); | 2074 | QUnit.strictEqual(this.requests[0].url, 'liveStart30sBefore.m3u8', 'master playlist requested'); |
2073 | QUnit.equal(removes.length, 1, 'remove called'); | 2075 | QUnit.equal(removes.length, 1, 'remove called'); |
2074 | QUnit.deepEqual(removes[0], [0, 80 - 60], 'remove called with the right range'); | 2076 | QUnit.deepEqual(removes[0], [0, 80 - 70], 'remove called with the right range'); |
2075 | 2077 | ||
2076 | // verify stats | 2078 | // verify stats |
2077 | QUnit.equal(this.player.tech_.hls.stats.mediaBytesTransferred, 16, '16 bytes'); | 2079 | QUnit.equal(this.player.tech_.hls.stats.mediaBytesTransferred, 16, '16 bytes'); | ... | ... |
-
Please register or sign in to post a comment