You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1419 lines
44 KiB

Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
Simplified fetch algorithm as much as possible (#875) Fixed seeking behavior Updated getMediaIndexForTime to be simple and stupid Remove spurious console logs Fixed an issue with forward seeks and a different problem with backwards seeking (thanks Matt!). Fixed fast rendition change behavior. Remove limits on gap-skipper. Skip instantly without waiting. Use the proper native MediaSource duration for buffer removals. Improvements for live stream rendition changes Fixed an undefined variable bug Some more simplification and a very conservative live stream rendition change approach VOD fixes Experimental change to the way we throttle the fetcher Use GOAL_BUFFER_LENGTH again Continued massive changes to segment fetching. Cleanup and comments. Fixed a bug where we were fetching starting at mediaIndex 0 on every seek. Refactor probing code in preparation for pulling into it's own module or class Moved sync-related logic out of segment-loader and into a new sync-controller class Removed expired from the SegmentLoader Update mux.js dependency to 2.5.0 Don't error when the tsprobe returns null Fixed two issues: MAAT switching and Flash seeking Rename duration variable fix flash failing first segment load (#859) dont use tech for has played (#861) Code Coverage and Unit tests for Simple Fetcher (#862) fix has played returning false on vod (#866) Fixed preload="none" behavior and reduced the incidence of repeating initial segment requests (#878) Provide option to set contrib-hls first in the HTML5 tech (#889) This reverts commit 59ddbe1188c0b4a1d55d63fa7a334174001fbd28. Add playback tests (#894) Fixed MSE and environment test helpers, restore properly Removed unused test files remove expired time tracking and use sync points to calculate seekable (#898) Fixing a few tests for QUnit 2.0
9 years ago
  1. import videojs from 'video.js';
  2. import QUnit from 'qunit';
  3. import {
  4. useFakeEnvironment,
  5. useFakeMediaSource,
  6. createPlayer,
  7. openMediaSource,
  8. standardXHRResponse
  9. } from './test-helpers.js';
  10. import {
  11. default as PlaybackWatcher,
  12. closeToBufferedContent
  13. } from '../src/playback-watcher';
  14. // needed for plugin registration
  15. import '../src/videojs-http-streaming';
  16. import sinon from 'sinon';
  17. let monitorCurrentTime_;
  18. QUnit.module('PlaybackWatcher', {
  19. beforeEach(assert) {
  20. this.env = useFakeEnvironment(assert);
  21. this.requests = this.env.requests;
  22. this.mse = useFakeMediaSource();
  23. this.clock = this.env.clock;
  24. this.old = {};
  25. // setup a player
  26. this.player = createPlayer({html5: {
  27. vhs: {
  28. overrideNative: true
  29. }
  30. }});
  31. this.player.muted(true);
  32. this.player.autoplay(true);
  33. },
  34. afterEach() {
  35. this.env.restore();
  36. this.mse.restore();
  37. this.player.dispose();
  38. }
  39. });
  40. QUnit.test('skips over gap in firefox with waiting event', function(assert) {
  41. let vhsGapSkipEvents = 0;
  42. let hlsGapSkipEvents = 0;
  43. this.player.autoplay(true);
  44. this.player.tech_.on('usage', (event) => {
  45. if (event.name === 'vhs-gap-skip') {
  46. vhsGapSkipEvents++;
  47. }
  48. if (event.name === 'hls-gap-skip') {
  49. hlsGapSkipEvents++;
  50. }
  51. });
  52. // create a buffer with a gap between 10 & 20 seconds
  53. this.player.tech_.buffered = function() {
  54. return videojs.createTimeRanges([[0, 10], [20, 30]]);
  55. };
  56. // set an arbitrary source
  57. this.player.src({
  58. src: 'master.m3u8',
  59. type: 'application/vnd.apple.mpegurl'
  60. });
  61. // start playback normally
  62. this.player.tech_.triggerReady();
  63. this.clock.tick(1);
  64. standardXHRResponse(this.requests.shift());
  65. openMediaSource(this.player, this.clock);
  66. this.player.tech_.trigger('canplay');
  67. this.player.tech_.trigger('play');
  68. this.player.tech_.trigger('playing');
  69. this.clock.tick(1);
  70. assert.equal(vhsGapSkipEvents, 0, 'there is no skipped gap');
  71. assert.equal(hlsGapSkipEvents, 0, 'there is no skipped gap');
  72. // seek to 10 seconds and wait 12 seconds
  73. this.player.currentTime(10);
  74. this.player.tech_.trigger('waiting');
  75. this.clock.tick(12000);
  76. // check that player jumped the gap
  77. assert.equal(
  78. Math.round(this.player.currentTime()),
  79. 20, 'Player seeked over gap after timer'
  80. );
  81. assert.equal(vhsGapSkipEvents, 1, 'there is one skipped gap');
  82. assert.equal(hlsGapSkipEvents, 1, 'there is one skipped gap');
  83. });
  84. QUnit.test('skips over gap in chrome without waiting event', function(assert) {
  85. let vhsGapSkipEvents = 0;
  86. let hlsGapSkipEvents = 0;
  87. this.player.autoplay(true);
  88. this.player.tech_.on('usage', (event) => {
  89. if (event.name === 'vhs-gap-skip') {
  90. vhsGapSkipEvents++;
  91. }
  92. if (event.name === 'hls-gap-skip') {
  93. hlsGapSkipEvents++;
  94. }
  95. });
  96. // create a buffer with a gap between 10 & 20 seconds
  97. this.player.tech_.buffered = function() {
  98. return videojs.createTimeRanges([[0, 10], [20, 30]]);
  99. };
  100. // set an arbitrary source
  101. this.player.src({
  102. src: 'master.m3u8',
  103. type: 'application/vnd.apple.mpegurl'
  104. });
  105. // start playback normally
  106. this.player.tech_.triggerReady();
  107. this.clock.tick(1);
  108. standardXHRResponse(this.requests.shift());
  109. openMediaSource(this.player, this.clock);
  110. this.player.tech_.trigger('canplay');
  111. this.player.tech_.trigger('play');
  112. this.player.tech_.trigger('playing');
  113. this.clock.tick(1);
  114. assert.equal(vhsGapSkipEvents, 0, 'there is no skipped gap');
  115. assert.equal(hlsGapSkipEvents, 0, 'there is no skipped gap');
  116. // seek to 10 seconds & simulate chrome waiting event
  117. this.player.currentTime(10);
  118. this.clock.tick(4000);
  119. // checks that player doesn't seek before timer expires
  120. assert.equal(this.player.currentTime(), 10, 'Player doesnt seek over gap pre-timer');
  121. this.clock.tick(10000);
  122. // check that player jumped the gap
  123. assert.equal(
  124. Math.round(this.player.currentTime()),
  125. 20, 'Player seeked over gap after timer'
  126. );
  127. assert.equal(vhsGapSkipEvents, 1, 'there is one skipped gap');
  128. assert.equal(hlsGapSkipEvents, 1, 'there is one skipped gap');
  129. });
  130. QUnit.test('skips over gap in Chrome due to video underflow', function(assert) {
  131. let vhsVideoUnderflowEvents = 0;
  132. let hlsVideoUnderflowEvents = 0;
  133. this.player.autoplay(true);
  134. this.player.tech_.on('usage', (event) => {
  135. if (event.name === 'vhs-video-underflow') {
  136. vhsVideoUnderflowEvents++;
  137. }
  138. if (event.name === 'hls-video-underflow') {
  139. hlsVideoUnderflowEvents++;
  140. }
  141. });
  142. this.player.tech_.buffered = () => {
  143. return videojs.createTimeRanges([[0, 10], [10.1, 20]]);
  144. };
  145. // set an arbitrary source
  146. this.player.src({
  147. src: 'master.m3u8',
  148. type: 'application/vnd.apple.mpegurl'
  149. });
  150. // start playback normally
  151. this.player.tech_.triggerReady();
  152. this.clock.tick(1);
  153. standardXHRResponse(this.requests.shift());
  154. openMediaSource(this.player, this.clock);
  155. this.player.tech_.trigger('play');
  156. this.player.tech_.trigger('playing');
  157. this.clock.tick(1);
  158. assert.equal(vhsVideoUnderflowEvents, 0, 'no video underflow event got triggered');
  159. assert.equal(hlsVideoUnderflowEvents, 0, 'no video underflow event got triggered');
  160. this.player.currentTime(13);
  161. const seeks = [];
  162. this.player.tech_.setCurrentTime = (time) => {
  163. seeks.push(time);
  164. };
  165. this.player.tech_.trigger('waiting');
  166. assert.equal(seeks.length, 1, 'one seek');
  167. assert.equal(seeks[0], 13, 'player seeked to current time');
  168. assert.equal(vhsVideoUnderflowEvents, 1, 'triggered a video underflow event');
  169. assert.equal(hlsVideoUnderflowEvents, 1, 'triggered a video underflow event');
  170. });
  171. QUnit.test(
  172. 'seek to live point if we fall off the end of a live playlist',
  173. function(assert) {
  174. // set an arbitrary live source
  175. this.player.src({
  176. src: 'liveStart30sBefore.m3u8',
  177. type: 'application/vnd.apple.mpegurl'
  178. });
  179. // start playback normally
  180. this.player.tech_.triggerReady();
  181. this.clock.tick(1);
  182. standardXHRResponse(this.requests.shift());
  183. openMediaSource(this.player, this.clock);
  184. this.player.tech_.trigger('play');
  185. this.player.tech_.trigger('playing');
  186. this.clock.tick(1);
  187. this.player.currentTime(0);
  188. const seeks = [];
  189. this.player.tech_.setCurrentTime = (time) => {
  190. seeks.push(time);
  191. };
  192. this.player.tech_.vhs.playbackWatcher_.seekable = () => {
  193. return videojs.createTimeRanges([[1, 45]]);
  194. };
  195. this.player.tech_.trigger('waiting');
  196. assert.equal(seeks.length, 1, 'one seek');
  197. assert.equal(seeks[0], 45, 'player seeked to live point');
  198. }
  199. );
  200. QUnit.test('seeks to current time when stuck inside buffered region', function(assert) {
  201. // set an arbitrary live source
  202. this.player.src({
  203. src: 'liveStart30sBefore.m3u8',
  204. type: 'application/vnd.apple.mpegurl'
  205. });
  206. // start playback normally
  207. this.player.tech_.triggerReady();
  208. this.clock.tick(1);
  209. standardXHRResponse(this.requests.shift());
  210. openMediaSource(this.player, this.clock);
  211. this.player.tech_.trigger('canplay');
  212. this.player.tech_.trigger('play');
  213. this.player.tech_.trigger('playing');
  214. this.clock.tick(1);
  215. this.player.currentTime(10);
  216. const seeks = [];
  217. this.player.tech_.setCurrentTime = (time) => {
  218. seeks.push(time);
  219. };
  220. this.player.tech_.seeking = () => false;
  221. this.player.tech_.buffered = () => videojs.createTimeRanges([[0, 30]]);
  222. this.player.tech_.seekable = () => videojs.createTimeRanges([[0, 30]]);
  223. this.player.tech_.paused = () => false;
  224. // Playback watcher loop runs on a 250ms clock
  225. this.clock.tick(250);
  226. // Loop has run through once, `lastRecordedTime` should have been recorded
  227. // and `consecutiveUpdates` set to 0 to begin count
  228. assert.equal(
  229. this.player.tech_.vhs.playbackWatcher_.lastRecordedTime, 10,
  230. 'Playback Watcher stored current time'
  231. );
  232. assert.equal(
  233. this.player.tech_.vhs.playbackWatcher_.consecutiveUpdates, 0,
  234. 'consecutiveUpdates set to 0'
  235. );
  236. // Playback watcher loop runs on a 250ms clock
  237. this.clock.tick(250);
  238. // Loop should increment consecutive updates until it is >= 5
  239. assert.equal(
  240. this.player.tech_.vhs.playbackWatcher_.consecutiveUpdates, 1,
  241. 'consecutiveUpdates incremented'
  242. );
  243. // Playback watcher loop runs on a 250ms clock
  244. this.clock.tick(250);
  245. // Loop should increment consecutive updates until it is >= 5
  246. assert.equal(
  247. this.player.tech_.vhs.playbackWatcher_.consecutiveUpdates, 2,
  248. 'consecutiveUpdates incremented'
  249. );
  250. // Playback watcher loop runs on a 250ms clock
  251. this.clock.tick(250);
  252. // Loop should increment consecutive updates until it is >= 5
  253. assert.equal(
  254. this.player.tech_.vhs.playbackWatcher_.consecutiveUpdates, 3,
  255. 'consecutiveUpdates incremented'
  256. );
  257. // Playback watcher loop runs on a 250ms clock
  258. this.clock.tick(250);
  259. // Loop should increment consecutive updates until it is >= 5
  260. assert.equal(
  261. this.player.tech_.vhs.playbackWatcher_.consecutiveUpdates, 4,
  262. 'consecutiveUpdates incremented'
  263. );
  264. // Playback watcher loop runs on a 250ms clock
  265. this.clock.tick(250);
  266. // Loop should increment consecutive updates until it is >= 5
  267. assert.equal(
  268. this.player.tech_.vhs.playbackWatcher_.consecutiveUpdates, 5,
  269. 'consecutiveUpdates incremented'
  270. );
  271. // Playback watcher loop runs on a 250ms clock
  272. this.clock.tick(250);
  273. // Loop should see consecutive updates >= 5, call `waiting_`
  274. assert.equal(
  275. this.player.tech_.vhs.playbackWatcher_.consecutiveUpdates, 0,
  276. 'consecutiveUpdates reset'
  277. );
  278. // Playback watcher seeked to currentTime in `waiting_` to correct the `unknownwaiting`
  279. assert.equal(seeks.length, 1, 'one seek');
  280. assert.equal(seeks[0], 10, 'player seeked to currentTime');
  281. });
  282. QUnit.test(
  283. 'does not seek to current time when stuck near edge of buffered region',
  284. function(assert) {
  285. // set an arbitrary live source
  286. this.player.src({
  287. src: 'liveStart30sBefore.m3u8',
  288. type: 'application/vnd.apple.mpegurl'
  289. });
  290. // start playback normally
  291. this.player.tech_.triggerReady();
  292. this.clock.tick(1);
  293. standardXHRResponse(this.requests.shift());
  294. openMediaSource(this.player, this.clock);
  295. this.player.tech_.trigger('canplay');
  296. this.player.tech_.trigger('play');
  297. this.player.tech_.trigger('playing');
  298. this.clock.tick(1);
  299. this.player.currentTime(29.98);
  300. const seeks = [];
  301. this.player.tech_.setCurrentTime = (time) => {
  302. seeks.push(time);
  303. };
  304. this.player.tech_.seeking = () => false;
  305. this.player.tech_.buffered = () => videojs.createTimeRanges([[0, 30]]);
  306. this.player.tech_.seekable = () => videojs.createTimeRanges([[0, 30]]);
  307. this.player.tech_.paused = () => false;
  308. // Playback watcher loop runs on a 250ms clock
  309. this.clock.tick(250);
  310. // Loop has run through once, `lastRecordedTime` should have been recorded
  311. // and `consecutiveUpdates` set to 0 to begin count
  312. assert.equal(
  313. this.player.tech_.vhs.playbackWatcher_.lastRecordedTime, 29.98,
  314. 'Playback Watcher stored current time'
  315. );
  316. assert.equal(
  317. this.player.tech_.vhs.playbackWatcher_.consecutiveUpdates, 0,
  318. 'consecutiveUpdates set to 0'
  319. );
  320. // Playback watcher loop runs on a 250ms clock
  321. this.clock.tick(250);
  322. // Loop has run through a second time, should detect that currentTime hasn't made
  323. // progress while at the end of the buffer. Since the currentTime is at the end of the
  324. // buffer, `consecutiveUpdates` should not be incremented
  325. assert.equal(
  326. this.player.tech_.vhs.playbackWatcher_.lastRecordedTime, 29.98,
  327. 'Playback Watcher stored current time'
  328. );
  329. assert.equal(
  330. this.player.tech_.vhs.playbackWatcher_.consecutiveUpdates, 0,
  331. 'consecutiveUpdates should still be 0'
  332. );
  333. // no corrective seek
  334. assert.equal(seeks.length, 0, 'no seek');
  335. }
  336. );
  337. QUnit.test('fires notifications when activated', function(assert) {
  338. let buffered = [[]];
  339. const seekable = [[]];
  340. let currentTime = 0;
  341. let vhsLiveResyncEvents = 0;
  342. let hlsLiveResyncEvents = 0;
  343. let vhsVideoUnderflowEvents = 0;
  344. let hlsVideoUnderflowEvents = 0;
  345. this.player.src({
  346. src: 'liveStart30sBefore.m3u8',
  347. type: 'application/vnd.apple.mpegurl'
  348. });
  349. this.player.tech_.triggerReady();
  350. this.clock.tick(1);
  351. this.player.tech_.currentTime = function() {
  352. return currentTime;
  353. };
  354. this.player.tech_.buffered = function() {
  355. return {
  356. length: buffered.length,
  357. start(i) {
  358. return buffered[i][0];
  359. },
  360. end(i) {
  361. return buffered[i][1];
  362. }
  363. };
  364. };
  365. const playbackWatcher = this.player.tech_.vhs.playbackWatcher_;
  366. playbackWatcher.seekable = function() {
  367. return {
  368. length: seekable.length,
  369. start(i) {
  370. return seekable[i][0];
  371. },
  372. end(i) {
  373. return seekable[i][1];
  374. }
  375. };
  376. };
  377. this.player.tech_.on('usage', (event) => {
  378. if (event.name === 'vhs-live-resync') {
  379. vhsLiveResyncEvents++;
  380. }
  381. if (event.name === 'hls-live-resync') {
  382. hlsLiveResyncEvents++;
  383. }
  384. if (event.name === 'vhs-video-underflow') {
  385. vhsVideoUnderflowEvents++;
  386. }
  387. if (event.name === 'hls-video-underflow') {
  388. hlsVideoUnderflowEvents++;
  389. }
  390. });
  391. currentTime = 19;
  392. seekable[0] = [20, 30];
  393. playbackWatcher.waiting_();
  394. assert.equal(vhsLiveResyncEvents, 1, 'triggered a liveresync event');
  395. assert.equal(hlsLiveResyncEvents, 1, 'triggered a liveresync event');
  396. currentTime = 12;
  397. seekable[0] = [0, 100];
  398. buffered = [[0, 9], [10, 20]];
  399. playbackWatcher.waiting_();
  400. assert.equal(vhsVideoUnderflowEvents, 1, 'triggered a videounderflow event');
  401. assert.equal(hlsVideoUnderflowEvents, 1, 'triggered a videounderflow event');
  402. assert.equal(vhsLiveResyncEvents, 1, 'did not trigger an additional liveresync event');
  403. assert.equal(hlsLiveResyncEvents, 1, 'did not trigger an additional liveresync event');
  404. });
  405. QUnit.test('fixes bad seeks', function(assert) {
  406. // set an arbitrary live source
  407. this.player.src({
  408. src: 'liveStart30sBefore.m3u8',
  409. type: 'application/vnd.apple.mpegurl'
  410. });
  411. // start playback normally
  412. this.player.tech_.triggerReady();
  413. this.clock.tick(1);
  414. standardXHRResponse(this.requests.shift());
  415. openMediaSource(this.player, this.clock);
  416. this.player.tech_.trigger('play');
  417. this.player.tech_.trigger('playing');
  418. this.clock.tick(1);
  419. const playbackWatcher = this.player.tech_.vhs.playbackWatcher_;
  420. const seeks = [];
  421. let seekable;
  422. let seeking;
  423. let currentTime;
  424. playbackWatcher.seekable = () => seekable;
  425. playbackWatcher.tech_ = {
  426. off: () => {},
  427. seeking: () => seeking,
  428. currentTime: () => currentTime,
  429. setCurrentTime: (time) => {
  430. seeks.push(time);
  431. },
  432. buffered: () => videojs.createTimeRanges()
  433. };
  434. currentTime = 50;
  435. seekable = videojs.createTimeRanges([[1, 45]]);
  436. seeking = false;
  437. assert.ok(!playbackWatcher.fixesBadSeeks_(), 'does nothing when not seeking');
  438. assert.equal(seeks.length, 0, 'did not seek');
  439. seeking = true;
  440. assert.ok(playbackWatcher.fixesBadSeeks_(), 'acts when seek past seekable range');
  441. assert.equal(seeks.length, 1, 'seeked');
  442. assert.equal(seeks[0], 45, 'player seeked to live point');
  443. currentTime = 0;
  444. assert.ok(playbackWatcher.fixesBadSeeks_(), 'acts when seek before seekable range');
  445. assert.equal(seeks.length, 2, 'seeked');
  446. assert.equal(seeks[1], 1.1, 'player seeked to start of the live window');
  447. currentTime = 30;
  448. assert.ok(!playbackWatcher.fixesBadSeeks_(), 'does nothing when time within range');
  449. assert.equal(seeks.length, 2, 'did not seek');
  450. });
  451. QUnit.test('corrects seek outside of seekable', function(assert) {
  452. // set an arbitrary live source
  453. this.player.src({
  454. src: 'liveStart30sBefore.m3u8',
  455. type: 'application/vnd.apple.mpegurl'
  456. });
  457. // start playback normally
  458. this.player.tech_.triggerReady();
  459. this.clock.tick(1);
  460. standardXHRResponse(this.requests.shift());
  461. openMediaSource(this.player, this.clock);
  462. this.player.tech_.trigger('play');
  463. this.player.tech_.trigger('playing');
  464. this.clock.tick(1);
  465. const playbackWatcher = this.player.tech_.vhs.playbackWatcher_;
  466. const seeks = [];
  467. let seekable;
  468. let seeking;
  469. let currentTime;
  470. playbackWatcher.seekable = () => seekable;
  471. playbackWatcher.tech_ = {
  472. off: () => {},
  473. seeking: () => seeking,
  474. setCurrentTime: (time) => {
  475. seeks.push(time);
  476. },
  477. currentTime: () => currentTime,
  478. // mocked out
  479. paused: () => false,
  480. buffered: () => videojs.createTimeRanges()
  481. };
  482. // waiting
  483. currentTime = 50;
  484. seekable = videojs.createTimeRanges([[1, 45]]);
  485. seeking = true;
  486. this.player.tech_.trigger('waiting');
  487. assert.equal(seeks.length, 1, 'seeked');
  488. assert.equal(seeks[0], 45, 'player seeked to live point');
  489. currentTime = 0;
  490. this.player.tech_.trigger('waiting');
  491. assert.equal(seeks.length, 2, 'seeked');
  492. assert.equal(seeks[1], 1.1, 'player seeked to start of the live window');
  493. // inside of seekable range
  494. currentTime = 10;
  495. this.player.tech_.trigger('waiting');
  496. assert.equal(seeks.length, 2, 'did not seek');
  497. currentTime = 50;
  498. // if we're not seeking, the case shouldn't be handled here
  499. seeking = false;
  500. this.player.tech_.trigger('waiting');
  501. assert.equal(seeks.length, 2, 'did not seek');
  502. // no check for 0 with seeking false because that should be handled by live falloff
  503. // checkCurrentTime
  504. seeking = true;
  505. currentTime = 50;
  506. playbackWatcher.checkCurrentTime_();
  507. assert.equal(seeks.length, 3, 'seeked');
  508. assert.equal(seeks[2], 45, 'player seeked to live point');
  509. currentTime = 0;
  510. playbackWatcher.checkCurrentTime_();
  511. assert.equal(seeks.length, 4, 'seeked');
  512. assert.equal(seeks[3], 1.1, 'player seeked to live point');
  513. currentTime = 10;
  514. playbackWatcher.checkCurrentTime_();
  515. assert.equal(seeks.length, 4, 'did not seek');
  516. seeking = false;
  517. currentTime = 50;
  518. playbackWatcher.checkCurrentTime_();
  519. assert.equal(seeks.length, 4, 'did not seek');
  520. currentTime = 0;
  521. playbackWatcher.checkCurrentTime_();
  522. assert.equal(seeks.length, 4, 'did not seek');
  523. });
  524. QUnit.test(
  525. 'corrected seeks respect allowSeeksWithinUnsafeLiveWindow flag',
  526. function(assert) {
  527. // set an arbitrary live source
  528. this.player.src({
  529. src: 'liveStart30sBefore.m3u8',
  530. type: 'application/vnd.apple.mpegurl'
  531. });
  532. // start playback normally
  533. this.player.tech_.triggerReady();
  534. this.clock.tick(1);
  535. standardXHRResponse(this.requests.shift());
  536. openMediaSource(this.player, this.clock);
  537. this.player.tech_.trigger('play');
  538. this.player.tech_.trigger('playing');
  539. this.clock.tick(1);
  540. const playbackWatcher = this.player.tech_.vhs.playbackWatcher_;
  541. const seeks = [];
  542. let seekable;
  543. let seeking;
  544. let currentTime;
  545. playbackWatcher.seekable = () => seekable;
  546. playbackWatcher.tech_ = {
  547. off: () => {},
  548. seeking: () => seeking,
  549. setCurrentTime: (time) => {
  550. seeks.push(time);
  551. },
  552. currentTime: () => currentTime,
  553. // mocked out
  554. paused: () => false,
  555. buffered: () => videojs.createTimeRanges()
  556. };
  557. playbackWatcher.allowSeeksWithinUnsafeLiveWindow = true;
  558. // waiting
  559. seekable = videojs.createTimeRanges([[1, 45]]);
  560. seeking = true;
  561. // target duration of 10, seekable end of 45
  562. // 45 + 3 * 10 = 75
  563. currentTime = 75;
  564. this.player.tech_.trigger('waiting');
  565. assert.equal(seeks.length, 0, 'did not seek');
  566. currentTime = 75.1;
  567. this.player.tech_.trigger('waiting');
  568. assert.equal(seeks.length, 1, 'seeked');
  569. assert.equal(seeks[0], 45, 'player seeked to live point');
  570. playbackWatcher.allowSeeksWithinUnsafeLiveWindow = true;
  571. currentTime = 75;
  572. this.player.tech_.trigger('waiting');
  573. assert.equal(seeks.length, 1, 'did not seek');
  574. }
  575. );
  576. QUnit.test('calls fixesBadSeeks_ on seekablechanged', function(assert) {
  577. // set an arbitrary live source
  578. this.player.src({
  579. src: 'liveStart30sBefore.m3u8',
  580. type: 'application/vnd.apple.mpegurl'
  581. });
  582. // start playback normally
  583. this.player.tech_.triggerReady();
  584. this.clock.tick(1);
  585. standardXHRResponse(this.requests.shift());
  586. openMediaSource(this.player, this.clock);
  587. this.player.tech_.trigger('play');
  588. this.player.tech_.trigger('playing');
  589. this.clock.tick(1);
  590. const playbackWatcher = this.player.tech_.vhs.playbackWatcher_;
  591. let fixesBadSeeks_ = 0;
  592. playbackWatcher.fixesBadSeeks_ = () => fixesBadSeeks_++;
  593. this.player.tech_.trigger('seekablechanged');
  594. assert.equal(fixesBadSeeks_, 1, 'fixesBadSeeks_ was called');
  595. });
  596. QUnit.test('jumps to buffered content if seeking just before', function(assert) {
  597. // target duration is 10 for this manifest
  598. this.player.src({
  599. src: 'liveStart30sBefore.m3u8',
  600. type: 'application/vnd.apple.mpegurl'
  601. });
  602. // start playback normally
  603. this.player.tech_.triggerReady();
  604. this.clock.tick(1);
  605. standardXHRResponse(this.requests.shift());
  606. openMediaSource(this.player, this.clock);
  607. this.player.tech_.trigger('play');
  608. this.player.tech_.trigger('playing');
  609. this.clock.tick(1);
  610. const playbackWatcher = this.player.tech_.vhs.playbackWatcher_;
  611. const seeks = [];
  612. let currentTime;
  613. let buffered;
  614. playbackWatcher.seekable = () => videojs.createTimeRanges([[10, 100]]);
  615. playbackWatcher.tech_ = {
  616. off: () => {},
  617. seeking: () => true,
  618. setCurrentTime: (time) => {
  619. seeks.push(time);
  620. },
  621. currentTime: () => currentTime,
  622. buffered: () => buffered
  623. };
  624. this.player.tech(true).vhs.setCurrentTime = (time) => seeks.push(time);
  625. currentTime = 10;
  626. // target duration is 10
  627. buffered = videojs.createTimeRanges([[20, 39]]);
  628. assert.notOk(playbackWatcher.fixesBadSeeks_(), 'does nothing when too far from buffer');
  629. assert.equal(seeks.length, 0, 'did not seek');
  630. buffered = videojs.createTimeRanges([[19, 38.9]]);
  631. assert.notOk(playbackWatcher.fixesBadSeeks_(), 'does nothing when not enough buffer');
  632. assert.equal(seeks.length, 0, 'did not seek');
  633. buffered = videojs.createTimeRanges([[19, 39]]);
  634. assert.ok(
  635. playbackWatcher.fixesBadSeeks_(),
  636. 'acts when close enough to, and enough, buffer'
  637. );
  638. assert.equal(seeks.length, 1, 'seeked');
  639. assert.equal(seeks[0], 19.1, 'player seeked to start of buffer');
  640. currentTime = 20;
  641. assert.notOk(
  642. playbackWatcher.fixesBadSeeks_(),
  643. 'does nothing when current time after buffer start'
  644. );
  645. assert.equal(seeks.length, 1, 'did not seek');
  646. // defers to fixing the bad seek over seeking into the buffer when seeking outside of
  647. // seekable range
  648. currentTime = 10;
  649. playbackWatcher.seekable = () => videojs.createTimeRanges([[11, 100]]);
  650. assert.ok(playbackWatcher.fixesBadSeeks_(), 'fixed bad seek');
  651. assert.equal(seeks.length, 2, 'seeked');
  652. assert.equal(seeks[1], 11.1, 'seeked to seekable range');
  653. });
  654. const loaderTypes = ['audio', 'main', 'subtitle'];
  655. const EXCLUDE_APPEND_COUNT = 10;
  656. QUnit.module('PlaybackWatcher download detection', {
  657. beforeEach(assert) {
  658. this.env = useFakeEnvironment(assert);
  659. this.requests = this.env.requests;
  660. this.mse = useFakeMediaSource();
  661. this.clock = this.env.clock;
  662. this.old = {};
  663. this.respondToPlaylists_ = () => {
  664. const regex = (/\.(m3u8|mpd)/i);
  665. for (let i = 0; i < this.requests.length; i++) {
  666. const r = this.requests[i];
  667. if (regex.test(r.uri)) {
  668. this.requests.splice(i, 1);
  669. standardXHRResponse(r);
  670. i--;
  671. }
  672. }
  673. };
  674. this.setup = function(src = {src: 'media.m3u8', type: 'application/vnd.apple.mpegurl'}) {
  675. // setup a player
  676. this.player = createPlayer({html5: {
  677. vhs: {
  678. overrideNative: true
  679. }
  680. }});
  681. this.player.src(src);
  682. // start playback normally
  683. this.player.tech_.triggerReady();
  684. this.clock.tick(1);
  685. standardXHRResponse(this.requests.shift());
  686. openMediaSource(this.player, this.clock);
  687. this.player.tech_.trigger('play');
  688. this.player.tech_.trigger('playing');
  689. this.clock.tick(1);
  690. this.respondToPlaylists_();
  691. this.usageEvents = {};
  692. this.mpcErrors = 0;
  693. this.playbackWatcher = this.player.tech(true).vhs.playbackWatcher_;
  694. this.mpc = this.player.tech(true).vhs.masterPlaylistController_;
  695. this.mpc.on('error', () => this.mpcErrors++);
  696. this.player.tech_.on('usage', (event) => {
  697. const name = event.name;
  698. this.usageEvents[name] = this.usageEvents[name] || 0;
  699. this.usageEvents[name]++;
  700. });
  701. this.setBuffered = (val) => {
  702. this.player.buffered = () => val;
  703. loaderTypes.forEach((type) => {
  704. this.mpc[`${type}SegmentLoader_`].buffered_ = () => val;
  705. });
  706. };
  707. };
  708. },
  709. afterEach() {
  710. this.env.restore();
  711. this.mse.restore();
  712. this.player.dispose();
  713. }
  714. });
  715. loaderTypes.forEach(function(type) {
  716. QUnit.test(`detects ${type} appends without buffer changes and excludes`, function(assert) {
  717. this.setup();
  718. const loader = this.mpc[`${type}SegmentLoader_`];
  719. const track = {label: 'foobar', mode: 'showing'};
  720. if (type === 'subtitle') {
  721. loader.track = () => track;
  722. sinon.stub(this.player.tech_.textTracks(), 'removeTrack');
  723. }
  724. this.setBuffered(videojs.createTimeRanges([[0, 30]]));
  725. for (let i = 0; i <= EXCLUDE_APPEND_COUNT; i++) {
  726. loader.trigger('appendsdone');
  727. if (i === EXCLUDE_APPEND_COUNT) {
  728. assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], 0, `append #${i} resets stalled downloads to 0`);
  729. } else {
  730. assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], i, `append #${i + 1} ${i} stalled downloads`);
  731. }
  732. }
  733. const expectedUsage = {};
  734. expectedUsage[`vhs-${type}-download-exclusion`] = 1;
  735. if (type !== 'subtitle') {
  736. expectedUsage['vhs-rendition-blacklisted'] = 1;
  737. expectedUsage['hls-rendition-blacklisted'] = 1;
  738. }
  739. assert.deepEqual(this.usageEvents, expectedUsage, 'usage as expected');
  740. if (type !== 'subtitle') {
  741. const message = 'Playback cannot continue. No available working or supported playlists.';
  742. assert.equal(this.mpcErrors, 1, 'one mpc error');
  743. assert.equal(this.mpc.error, message, 'mpc error set');
  744. assert.equal(this.player.error().message, message, 'player error set');
  745. assert.equal(this.env.log.error.callCount, 1, 'player error logged');
  746. assert.equal(this.env.log.error.args[0][1], message, 'error message as expected');
  747. this.env.log.error.resetHistory();
  748. } else {
  749. const message = 'Text track "foobar" is not working correctly. It will be disabled and excluded.';
  750. assert.equal(this.mpcErrors, 0, 'no mpc error set');
  751. assert.notOk(this.player.error(), 'no player error set');
  752. assert.equal(this.player.textTracks().removeTrack.callCount, 1, 'text track remove called');
  753. assert.equal(this.player.textTracks().removeTrack.args[0][0], track, 'text track remove called with expected');
  754. assert.equal(track.mode, 'disabled', 'mode set to disabled now');
  755. assert.equal(this.env.log.warn.callCount, 1, 'warning logged');
  756. assert.equal(this.env.log.warn.args[0][0], message, 'warning message as expected');
  757. this.env.log.warn.resetHistory();
  758. }
  759. });
  760. if (type !== 'subtitle') {
  761. QUnit.test(`detects ${type} appends without buffer changes and excludes many playlists`, function(assert) {
  762. this.setup({src: 'multipleAudioGroupsCombinedMain.m3u8', type: 'application/vnd.apple.mpegurl'});
  763. const loader = this.mpc[`${type}SegmentLoader_`];
  764. const playlists = this.mpc.master().playlists;
  765. const excludeAndVerify = () => {
  766. let oldPlaylist;
  767. // this test only needs 9 appends, since we do an intial append
  768. for (let i = 0; i < EXCLUDE_APPEND_COUNT; i++) {
  769. oldPlaylist = this.mpc.media();
  770. loader.trigger('appendsdone');
  771. if (i === EXCLUDE_APPEND_COUNT - 1) {
  772. assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], 0, `append #${i} resets stalled downloads to 0`);
  773. } else {
  774. assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], i + 1, `append #${i + 1} ${i + 1} stalled downloads`);
  775. }
  776. }
  777. const expectedUsage = {};
  778. expectedUsage[`vhs-${type}-download-exclusion`] = 1;
  779. expectedUsage['vhs-rendition-blacklisted'] = 1;
  780. expectedUsage['hls-rendition-blacklisted'] = 1;
  781. assert.deepEqual(this.usageEvents, expectedUsage, 'usage as expected');
  782. this.usageEvents = {};
  783. this.respondToPlaylists_();
  784. const otherPlaylistsLeft = this.mpc.master().playlists.some((p) => p.excludeUntil !== Infinity);
  785. if (otherPlaylistsLeft) {
  786. const message = `Problem encountered with playlist ${oldPlaylist.id}.` +
  787. ` Excessive ${type} segment downloading detected.` +
  788. ` Switching to playlist ${this.mpc.media().id}.`;
  789. assert.equal(this.mpcErrors, 0, 'no mpc error');
  790. assert.notOk(this.mpc.error, 'no mpc error set');
  791. assert.notOk(this.player.error(), 'player error not set');
  792. assert.equal(this.env.log.warn.callCount, 1, 'player warning logged');
  793. assert.equal(this.env.log.warn.args[0][0], message, 'warning message as expected');
  794. this.env.log.warn.resetHistory();
  795. } else {
  796. const message = 'Playback cannot continue. No available working or supported playlists.';
  797. assert.equal(this.mpcErrors, 1, 'one mpc error');
  798. assert.equal(this.mpc.error, message, 'mpc error set');
  799. assert.equal(this.player.error().message, message, 'player error set');
  800. assert.equal(this.env.log.error.callCount, 1, 'player error logged');
  801. assert.equal(this.env.log.error.args[0][1], message, 'error message as expected');
  802. this.env.log.error.resetHistory();
  803. }
  804. };
  805. this.setBuffered(videojs.createTimeRanges([[0, 30]]));
  806. loader.trigger('appendsdone');
  807. assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], 0, 'initial append 0 stalled downloads');
  808. let i = playlists.length;
  809. // exclude all playlists and verify
  810. while (i--) {
  811. excludeAndVerify();
  812. }
  813. });
  814. }
  815. QUnit.test(`resets ${type} exclusion on playlistupdate, tech seeking, tech seeked`, function(assert) {
  816. this.setup();
  817. const loader = this.mpc[`${type}SegmentLoader_`];
  818. this.setBuffered(videojs.createTimeRanges([[0, 30]]));
  819. loader.trigger('appendsdone');
  820. assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], 0, '1st append 0 stalled downloads');
  821. loader.trigger('appendsdone');
  822. assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], 1, '2nd append 1 stalled downloads');
  823. loader.trigger('playlistupdate');
  824. assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], 0, '0 stalled downloads after playlistupdate');
  825. loader.trigger('appendsdone');
  826. assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], 1, '1st append 1 stalled downloads');
  827. loader.trigger('appendsdone');
  828. assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], 2, '2nd append 2 stalled downloads');
  829. this.player.tech_.trigger('seeking');
  830. assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], 0, '0 stalled downloads after seeking');
  831. loader.trigger('appendsdone');
  832. assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], 1, '1st append 1 stalled downloads');
  833. loader.trigger('appendsdone');
  834. assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], 2, '2nd append 2 stalled downloads');
  835. this.player.tech_.trigger('seeked');
  836. assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], 0, '0 stalled downloads after seeked');
  837. loader.trigger('appendsdone');
  838. assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], 1, '1st append 1 stalled downloads');
  839. loader.trigger('appendsdone');
  840. assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], 2, '2nd append 2 stalled downloads');
  841. assert.deepEqual(this.usageEvents, {}, 'no usage events');
  842. });
  843. QUnit.test(`Resets ${type} exclusion on buffered change`, function(assert) {
  844. this.setup();
  845. const loader = this.mpc[`${type}SegmentLoader_`];
  846. this.setBuffered(videojs.createTimeRanges([[0, 30]]));
  847. loader.trigger('appendsdone');
  848. assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], 0, '1st append 0 stalled downloads');
  849. loader.trigger('appendsdone');
  850. assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], 1, '2nd append 1 stalled downloads');
  851. this.setBuffered(videojs.createTimeRanges([[0, 31]]));
  852. loader.trigger('appendsdone');
  853. assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], 0, '1st append 0 stalled downloads');
  854. loader.trigger('appendsdone');
  855. assert.equal(this.playbackWatcher[`${type}StalledDownloads_`], 1, '2nd append 1 stalled downloads');
  856. });
  857. });
  858. QUnit.module('PlaybackWatcher isolated functions', {
  859. beforeEach() {
  860. monitorCurrentTime_ = PlaybackWatcher.prototype.monitorCurrentTime_;
  861. PlaybackWatcher.prototype.monitorCurrentTime_ = () => {};
  862. this.playbackWatcher = new PlaybackWatcher({
  863. tech: {
  864. on: () => {},
  865. off: () => {},
  866. // needed to construct a playback watcher
  867. options_: {
  868. playerId: 'mock-player-id'
  869. }
  870. },
  871. masterPlaylistController: {
  872. mainSegmentLoader_: Object.assign(new videojs.EventTarget(), {buffered_: () => videojs.createTimeRanges()}),
  873. audioSegmentLoader_: Object.assign(new videojs.EventTarget(), {buffered_: () => videojs.createTimeRanges()}),
  874. subtitleSegmentLoader_: Object.assign(new videojs.EventTarget(), {buffered_: () => videojs.createTimeRanges()})
  875. }
  876. });
  877. },
  878. afterEach() {
  879. this.playbackWatcher.dispose();
  880. PlaybackWatcher.prototype.monitorCurrentTime_ = monitorCurrentTime_;
  881. }
  882. });
  883. QUnit.test('skips gap from video underflow', function(assert) {
  884. assert.equal(
  885. this.playbackWatcher.gapFromVideoUnderflow_(videojs.createTimeRanges(), 0),
  886. null,
  887. 'returns null when buffer is empty'
  888. );
  889. assert.equal(
  890. this.playbackWatcher.gapFromVideoUnderflow_(videojs.createTimeRanges([[0, 10]]), 13),
  891. null,
  892. 'returns null when there is only a previous buffer'
  893. );
  894. assert.equal(
  895. this.playbackWatcher.gapFromVideoUnderflow_(videojs.createTimeRanges([[0, 10], [10.1, 20]]), 15),
  896. null,
  897. 'returns null when gap is too far from current time'
  898. );
  899. assert.equal(
  900. this.playbackWatcher.gapFromVideoUnderflow_(videojs.createTimeRanges([[0, 10], [10.1, 20]]), 9.9),
  901. null,
  902. 'returns null when gap is after current time'
  903. );
  904. assert.equal(
  905. this.playbackWatcher.gapFromVideoUnderflow_(videojs.createTimeRanges([[0, 10.1], [10.2, 20]]), 12.1),
  906. null,
  907. 'returns null when time is less than or equal to 2 seconds ahead'
  908. );
  909. assert.equal(
  910. this.playbackWatcher.gapFromVideoUnderflow_(videojs.createTimeRanges([[0, 10], [10.1, 20]]), 14.1),
  911. null,
  912. 'returns null when time is greater than or equal to 4 seconds ahead'
  913. );
  914. assert.deepEqual(
  915. this.playbackWatcher.gapFromVideoUnderflow_(videojs.createTimeRanges([[0, 10], [10.1, 20]]), 12.2),
  916. {start: 10, end: 10.1},
  917. 'returns gap when gap is small and time is greater than 2 seconds ahead in a buffer'
  918. );
  919. assert.deepEqual(
  920. this.playbackWatcher.gapFromVideoUnderflow_(videojs.createTimeRanges([[0, 10], [10.1, 20]]), 13),
  921. {start: 10, end: 10.1},
  922. 'returns gap when gap is small and time is 3 seconds ahead in a buffer'
  923. );
  924. assert.deepEqual(
  925. this.playbackWatcher.gapFromVideoUnderflow_(videojs.createTimeRanges([[0, 10], [10.1, 20]]), 13.9),
  926. {start: 10, end: 10.1},
  927. 'returns gap when gap is small and time is less than 4 seconds ahead in a buffer'
  928. );
  929. // In a case where current time is outside of the buffered range, something odd must've
  930. // happened, but we should still allow the player to try to continue from that spot.
  931. assert.deepEqual(
  932. this.playbackWatcher.gapFromVideoUnderflow_(videojs.createTimeRanges([[0, 10], [10.1, 12.9]]), 13),
  933. {start: 10, end: 10.1},
  934. 'returns gap even when current time is not in buffered range'
  935. );
  936. });
  937. QUnit.test('detects live window falloff', function(assert) {
  938. const beforeSeekableWindow_ =
  939. this.playbackWatcher.beforeSeekableWindow_.bind(this.playbackWatcher);
  940. assert.ok(
  941. beforeSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 10),
  942. 'true if playlist live and current time before seekable'
  943. );
  944. assert.ok(
  945. !beforeSeekableWindow_(videojs.createTimeRanges([]), 10),
  946. 'false if no seekable range'
  947. );
  948. assert.ok(
  949. !beforeSeekableWindow_(videojs.createTimeRanges([[0, 10]]), -1),
  950. 'false if seekable range starts at 0'
  951. );
  952. assert.ok(
  953. !beforeSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 11),
  954. 'false if current time at seekable start'
  955. );
  956. assert.ok(
  957. !beforeSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 20),
  958. 'false if current time at seekable end'
  959. );
  960. assert.ok(
  961. !beforeSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 15),
  962. 'false if current time within seekable range'
  963. );
  964. assert.ok(
  965. !beforeSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 21),
  966. 'false if current time past seekable range'
  967. );
  968. assert.ok(
  969. beforeSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 0),
  970. 'true if current time is 0 and earlier than seekable range'
  971. );
  972. });
  973. QUnit.test('detects beyond seekable window for VOD', function(assert) {
  974. const playlist = {
  975. endList: true,
  976. targetDuration: 7
  977. };
  978. const afterSeekableWindow_ =
  979. this.playbackWatcher.afterSeekableWindow_.bind(this.playbackWatcher);
  980. assert.notOk(
  981. afterSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 10.8, playlist),
  982. 'false if before seekable range'
  983. );
  984. assert.ok(
  985. afterSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 20.2, playlist),
  986. 'true if after seekable range'
  987. );
  988. assert.notOk(
  989. afterSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 10.9, playlist),
  990. 'false if within starting seekable range buffer'
  991. );
  992. assert.notOk(
  993. afterSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 20.1, playlist),
  994. 'false if within ending seekable range buffer'
  995. );
  996. assert.notOk(
  997. afterSeekableWindow_(videojs.createTimeRanges(), 10, playlist),
  998. 'false if no seekable range'
  999. );
  1000. assert.notOk(
  1001. afterSeekableWindow_(videojs.createTimeRanges([[0, 10]]), -0.2, playlist),
  1002. 'false if current time is negative'
  1003. );
  1004. assert.notOk(
  1005. afterSeekableWindow_(videojs.createTimeRanges([[0, 10]]), 5, playlist),
  1006. 'false if within seekable range'
  1007. );
  1008. assert.notOk(
  1009. afterSeekableWindow_(videojs.createTimeRanges([[0, 10]]), 0, playlist),
  1010. 'false if within seekable range'
  1011. );
  1012. assert.notOk(
  1013. afterSeekableWindow_(videojs.createTimeRanges([[0, 10]]), 10, playlist),
  1014. 'false if within seekable range'
  1015. );
  1016. });
  1017. QUnit.test('detects beyond seekable window for LIVE', function(assert) {
  1018. // no endList means live
  1019. const playlist = {
  1020. targetDuration: 7
  1021. };
  1022. const afterSeekableWindow_ =
  1023. this.playbackWatcher.afterSeekableWindow_.bind(this.playbackWatcher);
  1024. assert.notOk(
  1025. afterSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 10.8, playlist),
  1026. 'false if before seekable range'
  1027. );
  1028. assert.ok(
  1029. afterSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 20.2, playlist),
  1030. 'true if after seekable range'
  1031. );
  1032. assert.notOk(
  1033. afterSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 10.9, playlist),
  1034. 'false if within starting seekable range buffer'
  1035. );
  1036. assert.notOk(
  1037. afterSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 20.1, playlist),
  1038. 'false if within ending seekable range buffer'
  1039. );
  1040. assert.notOk(
  1041. afterSeekableWindow_(videojs.createTimeRanges(), 10, playlist),
  1042. 'false if no seekable range'
  1043. );
  1044. assert.notOk(
  1045. afterSeekableWindow_(videojs.createTimeRanges([[0, 10]]), -0.2, playlist),
  1046. 'false if current time is negative'
  1047. );
  1048. assert.notOk(
  1049. afterSeekableWindow_(videojs.createTimeRanges([[0, 10]]), 5, playlist),
  1050. 'false if within seekable range'
  1051. );
  1052. assert.notOk(
  1053. afterSeekableWindow_(videojs.createTimeRanges([[0, 10]]), 0, playlist),
  1054. 'false if within seekable range'
  1055. );
  1056. assert.notOk(
  1057. afterSeekableWindow_(videojs.createTimeRanges([[0, 10]]), 10, playlist),
  1058. 'false if within seekable range'
  1059. );
  1060. });
  1061. QUnit.test('respects allowSeeksWithinUnsafeLiveWindow flag', function(assert) {
  1062. // no endList means live
  1063. const playlist = {
  1064. targetDuration: 7
  1065. };
  1066. const afterSeekableWindow_ =
  1067. this.playbackWatcher.afterSeekableWindow_.bind(this.playbackWatcher);
  1068. assert.notOk(
  1069. afterSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 10.8, playlist, true),
  1070. 'false if before seekable range'
  1071. );
  1072. assert.notOk(
  1073. afterSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 20.2, playlist, true),
  1074. 'false if after seekable range but within unsafe live window'
  1075. );
  1076. assert.notOk(
  1077. afterSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 40.9, playlist, true),
  1078. 'false if after seekable range but within unsafe live window'
  1079. );
  1080. assert.ok(
  1081. afterSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 41.1, playlist, true),
  1082. 'true if after seekable range and unsafe live window'
  1083. );
  1084. assert.notOk(
  1085. afterSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 10.9, playlist, true),
  1086. 'false if within starting seekable range buffer'
  1087. );
  1088. assert.notOk(
  1089. afterSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 20.1, playlist, true),
  1090. 'false if within ending seekable range buffer'
  1091. );
  1092. assert.notOk(
  1093. afterSeekableWindow_(videojs.createTimeRanges(), 10, playlist, true),
  1094. 'false if no seekable range'
  1095. );
  1096. assert.notOk(
  1097. afterSeekableWindow_(videojs.createTimeRanges([[0, 10]]), -0.2, playlist, true),
  1098. 'false if current time is negative'
  1099. );
  1100. assert.notOk(
  1101. afterSeekableWindow_(videojs.createTimeRanges([[0, 10]]), 5, playlist, true),
  1102. 'false if within seekable range'
  1103. );
  1104. assert.notOk(
  1105. afterSeekableWindow_(videojs.createTimeRanges([[0, 10]]), 0, playlist, true),
  1106. 'false if within seekable range'
  1107. );
  1108. assert.notOk(
  1109. afterSeekableWindow_(videojs.createTimeRanges([[0, 10]]), 10, playlist, true),
  1110. 'false if within seekable range'
  1111. );
  1112. playlist.endList = true;
  1113. assert.notOk(
  1114. afterSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 10.8, playlist, true),
  1115. 'false if before seekable range'
  1116. );
  1117. assert.ok(
  1118. afterSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 20.2, playlist, true),
  1119. 'true if after seekable range'
  1120. );
  1121. assert.notOk(
  1122. afterSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 10.9, playlist, true),
  1123. 'false if within starting seekable range buffer'
  1124. );
  1125. assert.notOk(
  1126. afterSeekableWindow_(videojs.createTimeRanges([[11, 20]]), 20.1, playlist, true),
  1127. 'false if within ending seekable range buffer'
  1128. );
  1129. assert.notOk(
  1130. afterSeekableWindow_(videojs.createTimeRanges(), 10, playlist, true),
  1131. 'false if no seekable range'
  1132. );
  1133. assert.notOk(
  1134. afterSeekableWindow_(videojs.createTimeRanges([[0, 10]]), -0.2, playlist, true),
  1135. 'false if current time is negative'
  1136. );
  1137. assert.notOk(
  1138. afterSeekableWindow_(videojs.createTimeRanges([[0, 10]]), 5, playlist, true),
  1139. 'false if within seekable range'
  1140. );
  1141. assert.notOk(
  1142. afterSeekableWindow_(videojs.createTimeRanges([[0, 10]]), 0, playlist, true),
  1143. 'false if within seekable range'
  1144. );
  1145. assert.notOk(
  1146. afterSeekableWindow_(videojs.createTimeRanges([[0, 10]]), 10, playlist, true),
  1147. 'false if within seekable range'
  1148. );
  1149. });
  1150. QUnit.module('closeToBufferedContent');
  1151. QUnit.test('false if no buffer', function(assert) {
  1152. assert.notOk(
  1153. closeToBufferedContent({
  1154. buffered: videojs.createTimeRanges(),
  1155. targetDuration: 4,
  1156. currentTime: 10
  1157. }),
  1158. 'returned false'
  1159. );
  1160. });
  1161. QUnit.test('false if buffer less than two times target duration', function(assert) {
  1162. assert.notOk(
  1163. closeToBufferedContent({
  1164. buffered: videojs.createTimeRanges([[11, 18.9]]),
  1165. targetDuration: 4,
  1166. currentTime: 10
  1167. }),
  1168. 'returned false'
  1169. );
  1170. });
  1171. QUnit.test('false if buffer is beyond target duration from current time', function(assert) {
  1172. assert.notOk(
  1173. closeToBufferedContent({
  1174. buffered: videojs.createTimeRanges([[14.1, 30]]),
  1175. targetDuration: 4,
  1176. currentTime: 10
  1177. }),
  1178. 'returned false'
  1179. );
  1180. });
  1181. QUnit.test('true if enough buffer and close to current time', function(assert) {
  1182. assert.ok(
  1183. closeToBufferedContent({
  1184. buffered: videojs.createTimeRanges([[13.9, 22]]),
  1185. targetDuration: 4,
  1186. currentTime: 10
  1187. }),
  1188. 'returned true'
  1189. );
  1190. });
  1191. QUnit.test('false if current time beyond buffer start', function(assert) {
  1192. assert.notOk(
  1193. closeToBufferedContent({
  1194. buffered: videojs.createTimeRanges([[13.9, 22]]),
  1195. targetDuration: 4,
  1196. currentTime: 14
  1197. }),
  1198. 'returned false'
  1199. );
  1200. });