2016-11-28 17:22:30 +00:00
|
|
|
class MediaSourceLoader {
|
|
|
|
constructor(url)
|
|
|
|
{
|
|
|
|
this._url = url;
|
|
|
|
this.onload = null;
|
|
|
|
this.onerror = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
loadManifest()
|
|
|
|
{
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
if (this._manifest) {
|
|
|
|
resolve();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var request = new XMLHttpRequest();
|
|
|
|
request.open('GET', this._url, true);
|
|
|
|
request.responseType = 'json';
|
|
|
|
request.onload = (event) => {
|
|
|
|
this.loadManifestSucceeded(event);
|
|
|
|
resolve();
|
|
|
|
}
|
|
|
|
request.onerror = (event) => {
|
|
|
|
this.loadManifestFailed(event);
|
|
|
|
reject(event);
|
|
|
|
}
|
|
|
|
request.send();
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
loadManifestSucceeded(event)
|
|
|
|
{
|
|
|
|
this._manifest = event.target.response;
|
|
|
|
|
|
|
|
if (!this._manifest || !this._manifest.url) {
|
|
|
|
if (this.onerror)
|
|
|
|
this.onerror();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
loadManifestFailed()
|
|
|
|
{
|
|
|
|
if (this.onerror)
|
|
|
|
this.onerror();
|
|
|
|
}
|
|
|
|
|
|
|
|
loadMediaData()
|
|
|
|
{
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
this.loadManifest().then(() => {
|
|
|
|
var request = new XMLHttpRequest();
|
|
|
|
request.open('GET', this._manifest.url, true);
|
|
|
|
request.responseType = 'arraybuffer';
|
|
|
|
request.onload = (event) => {
|
|
|
|
this.loadMediaDataSucceeded(event);
|
|
|
|
resolve();
|
|
|
|
}
|
|
|
|
request.onerror = (event) => {
|
|
|
|
this.loadMediaDataFailed(event);
|
|
|
|
reject(event);
|
|
|
|
}
|
|
|
|
request.send();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
loadMediaDataSucceeded(event)
|
|
|
|
{
|
|
|
|
this._mediaData = event.target.response;
|
|
|
|
|
|
|
|
if (this.onload)
|
|
|
|
this.onload();
|
|
|
|
}
|
|
|
|
|
|
|
|
loadMediaDataFailed()
|
|
|
|
{
|
|
|
|
if (this.onerror)
|
|
|
|
this.onerror();
|
|
|
|
}
|
|
|
|
|
|
|
|
get type()
|
|
|
|
{
|
|
|
|
return this._manifest ? this._manifest.type : "";
|
|
|
|
}
|
|
|
|
|
|
|
|
get duration()
|
|
|
|
{
|
Playback stalls when a SourceBuffer append causes frame eviction
https://bugs.webkit.org/show_bug.cgi?id=167834
Reviewed by Eric Carlson.
PerformanceTests:
Add an in-page performance test measuring the amount of time required
to append a large amount of media data to a SourceBuffer, and then to
completely remove that data 30s at a time.
Add a microbenchmark for MediaTime which measures the amount of time
required to create a 1M entry std::map and traverse the map 1M times.
* Media/MSERemoveCodedFrames.html: Added.
* Media/media-source-loader.js:
(MediaSourceLoader.prototype.get duration):
* MediaTime/Configurations/Base.xcconfig: Added.
* MediaTime/Configurations/DebugRelease.xcconfig: Added.
* MediaTime/Makefile: Added.
* MediaTime/MediaTime.xcodeproj/project.pbxproj: Added.
* MediaTime/main.cpp: Added.
(performTest):
(test):
(main):
* Skipped:
Source/WebCore:
Test: PerformanceTests/Media/MSERemoveCodedFrames.html
Optimize searching through SampleMap by presentationTime.
Many of the methods exposed by PresentationOrderSampleMap used the bare std::equal_range,
lower_bound, or upper_bound methods. Unlike those methods exposed on std::map, the bare
search methods perform a linear O(n) search, rather than a the binary O(log(n)) search used
by std::map. Rewrite those methods using the bare methods in terms of the std::map search
methods.
Drive-by fix: rename findSampleOnOrAfterPresentationTime to
findSampleStartingOnOrAfterPresentationTime to make the behavior of the method more
explicit.
* Modules/mediasource/SampleMap.cpp:
(WebCore::PresentationOrderSampleMap::findSampleContainingPresentationTime):
(WebCore::PresentationOrderSampleMap::findSampleStartingOnOrAfterPresentationTime):
(WebCore::PresentationOrderSampleMap::reverseFindSampleBeforePresentationTime):
(WebCore::DecodeOrderSampleMap::findSyncSampleAfterPresentationTime):
(WebCore::PresentationOrderSampleMap::findSamplesBetweenPresentationTimes):
(WebCore::PresentationOrderSampleMap::findSamplesWithinPresentationRange):
(WebCore::PresentationOrderSampleMap::findSampleOnOrAfterPresentationTime): Deleted.
* Modules/mediasource/SampleMap.h:
(WebCore::PresentationOrderSampleMap::begin):
(WebCore::PresentationOrderSampleMap::end):
(WebCore::PresentationOrderSampleMap::rbegin):
(WebCore::PresentationOrderSampleMap::rend):
(WebCore::DecodeOrderSampleMap::begin):
(WebCore::DecodeOrderSampleMap::end):
(WebCore::DecodeOrderSampleMap::rbegin):
(WebCore::DecodeOrderSampleMap::rend):
(WebCore::SampleMap::SampleMap):
(WebCore::SampleMap::sizeInBytes):
(WebCore::SampleMap::decodeOrder):
(WebCore::SampleMap::presentationOrder):
* Modules/mediasource/SourceBuffer.cpp:
(WebCore::removeSamplesFromTrackBuffer):
(WebCore::SourceBuffer::removeCodedFrames):
(WebCore::SourceBuffer::reenqueueMediaForTime):
* WebCore.xcodeproj/project.pbxproj:
Source/WTF:
Optimize the MediaTime class; specifically the compare() method. The class only
needs 6 bits to store the TimeFlags, so make that a uint8_t rather than uint32_t.
The implementation is slightly simpler if the TimeScale is unsigned, so make that
a uint32_t rather than int32_t. Inline the comparison operators. Optimize the equality
comparison by bitwise-and'ing the flags together and masking the result. Optimize for
common comparison scenarios (equal timeScales, equal timeValues(), etc.). Attempt the
mathematically simpler simpler method for comparing ratios, and only fall back to the
complex method if the results of multiplying the timeScale by the timeValue overflows.
* wtf/MediaTime.cpp:
(WTF::greatestCommonDivisor):
(WTF::leastCommonMultiple):
(WTF::signum):
(WTF::MediaTime::MediaTime):
(WTF::MediaTime::createWithFloat):
(WTF::MediaTime::createWithDouble):
(WTF::MediaTime::operator+):
(WTF::MediaTime::operator-):
(WTF::MediaTime::operator!):
(WTF::MediaTime::operator bool):
(WTF::MediaTime::compare):
(WTF::MediaTime::setTimeScale):
(WTF::abs):
(WTF::MediaTime::operator<): Deleted.
(WTF::MediaTime::operator>): Deleted.
(WTF::MediaTime::operator!=): Deleted.
(WTF::MediaTime::operator==): Deleted.
(WTF::MediaTime::operator>=): Deleted.
(WTF::MediaTime::operator<=): Deleted.
* wtf/MediaTime.h:
Tools:
Add new correctness tests for the Webcore::SampleMap class. Add additional subtests
for the WTF::MediaTime class.
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/MediaTime.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WebCore/SampleMap.cpp: Added.
(WTF::operator<<):
(TestWebKitAPI::TestSample::create):
(TestWebKitAPI::TestSample::TestSample):
(TestWebKitAPI::TEST_F):
Canonical link: https://commits.webkit.org/184921@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@211746 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-02-06 21:49:24 +00:00
|
|
|
if (!this._manifest)
|
|
|
|
return 0;
|
|
|
|
return this._manifest.media.reduce((duration, media) => { return duration + media.duration }, 0);
|
2016-11-28 17:22:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
get initSegment()
|
|
|
|
{
|
|
|
|
if (!this._manifest || !this._manifest.init || !this._mediaData)
|
|
|
|
return null;
|
|
|
|
var init = this._manifest.init;
|
|
|
|
return this._mediaData.slice(init.offset, init.offset + init.size);
|
|
|
|
}
|
|
|
|
|
|
|
|
get mediaSegmentsLength()
|
|
|
|
{
|
|
|
|
if (!this._manifest || !this._manifest.media)
|
|
|
|
return 0;
|
|
|
|
return this._manifest.media.length;
|
|
|
|
}
|
|
|
|
|
|
|
|
*mediaSegments()
|
|
|
|
{
|
|
|
|
if (!this._manifest || !this._manifest.media || !this._mediaData)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (var media of this._manifest.media)
|
|
|
|
yield this._mediaData.slice(media.offset, media.offset + media.size);
|
|
|
|
}
|
|
|
|
|
|
|
|
get everyMediaSegment()
|
|
|
|
{
|
|
|
|
if (!this._manifest || !this._manifest.media || !this._mediaData)
|
|
|
|
return null;
|
|
|
|
|
|
|
|
return this._mediaData.slice(this._manifest.media[0].offset);
|
|
|
|
}
|
|
|
|
};
|