Diff
Modified: trunk/PerformanceTests/ChangeLog (211745 => 211746)
--- trunk/PerformanceTests/ChangeLog 2017-02-06 20:49:25 UTC (rev 211745)
+++ trunk/PerformanceTests/ChangeLog 2017-02-06 21:49:24 UTC (rev 211746)
@@ -1,3 +1,30 @@
+2017-02-06 Jer Noble <jer.no...@apple.com>
+
+ Playback stalls when a SourceBuffer append causes frame eviction
+ https://bugs.webkit.org/show_bug.cgi?id=167834
+
+ Reviewed by Eric Carlson.
+
+ 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:
+
2017-02-06 Saam Barati <sbar...@apple.com>
Make ARES-6 work from the CLI again
Added: trunk/PerformanceTests/Media/MSERemoveCodedFrames.html (0 => 211746)
--- trunk/PerformanceTests/Media/MSERemoveCodedFrames.html (rev 0)
+++ trunk/PerformanceTests/Media/MSERemoveCodedFrames.html 2017-02-06 21:49:24 UTC (rev 211746)
@@ -0,0 +1,122 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script src=""
+<script>
+var loader;
+var video;
+var longMediaSegment;
+
+function concatArrayBuffers() {
+ var byteLength = 0;
+ Array.prototype.forEach.call(arguments, arrayBuffer => {
+ if (!arrayBuffer.byteLength)
+ throw "Not an ArrayBuffer!";
+ byteLength += arrayBuffer.byteLength;
+ });
+
+
+ var view = new Uint8Array(byteLength);
+ var offset = 0;
+ Array.prototype.forEach.call(arguments, arrayBuffer => {
+ view.set(new Uint8Array(arrayBuffer), offset);
+ offset += arrayBuffer.byteLength;
+ });
+ return view.buffer;
+}
+
+function concatMediaData() {
+ return new Promise((resolve, reject) => {
+ var segments = new Array(100);
+ segments.fill(loader.everyMediaSegment);
+ longMediaSegment = concatArrayBuffers.apply(this, segments);
+ resolve(longMediaSegment);
+ });
+}
+
+window.addEventListener('load', () => {
+ PerfTestRunner.prepareToMeasureValuesAsync({
+ unit: 'ms',
+ done: function () {
+ if (video) {
+ video.src = ""
+ video.load();
+ }
+ }
+ });
+
+ loader = new MediaSourceLoader('test-fragmented-video.json');
+ loader.loadMediaData().then(concatMediaData).then(runTest);
+});
+
+function remove30SecondsAtATimeTillEmpty(sourceBuffer) {
+ return new Promise(resolve => {
+ var removeNext30Seconds = () => {
+ var start = sourceBuffer.buffered.start(0);
+ sourceBuffer.remove(start, start + 30)
+ }
+ sourceBuffer._onupdate_ = () => {
+ if (sourceBuffer.buffered.length == 0 || sourceBuffer.buffered.start(0) - sourceBuffer.buffered.end(0) == 0) {
+ sourceBuffer._onupdate_ = null;
+ resolve();
+ return;
+ }
+
+ removeNext30Seconds();
+ };
+ removeNext30Seconds();
+ });
+}
+
+function runTest() {
+ video = document.createElement('video');
+
+ loadMediaDataIntoVideo(video).then(sourceBuffer => {
+ startTime = PerfTestRunner.now();
+ return remove30SecondsAtATimeTillEmpty(sourceBuffer);
+ }).then(() => {
+ if (PerfTestRunner.measureValueAsync(PerfTestRunner.now() - startTime))
+ setTimeout(runTest, 0);
+ });
+}
+
+function loadMediaDataIntoVideo(video, segmentCount) {
+ return new Promise((resolve, reject) => {
+ var source = new MediaSource();
+ source._onsourceopen_ = () => {
+ source._onsourceopen_ = null;
+ source.duration = loader.duration * 100;
+ var currentMediaSegment = 0;
+ var sourceBuffer = source.addSourceBuffer(loader.type);
+ sourceBuffer.mode = 'sequence';
+ sourceBuffer.appendBuffer(loader.initSegment);
+
+ var appendedMediaSegment = false;
+ sourceBuffer._onupdate_ = () => {
+
+ if (appendedMediaSegment) {
+ if (source.readyState !== 'ended') {
+ source.endOfStream();
+ sourceBuffer._onupdate_ = null;
+ sourceBuffer._onerror_ = null;
+ resolve(sourceBuffer);
+ }
+ return;
+ }
+
+ sourceBuffer.appendBuffer(longMediaSegment);
+ appendedMediaSegment = true;
+ };
+ sourceBuffer._onerror_ = error => {
+ reject(error);
+ };
+ };
+ video.src = ""
+ });
+}
+</script>
+</head>
+<body>
+</body>
+</html>
\ No newline at end of file
Modified: trunk/PerformanceTests/Media/media-source-loader.js (211745 => 211746)
--- trunk/PerformanceTests/Media/media-source-loader.js 2017-02-06 20:49:25 UTC (rev 211745)
+++ trunk/PerformanceTests/Media/media-source-loader.js 2017-02-06 21:49:24 UTC (rev 211746)
@@ -87,7 +87,9 @@
get duration()
{
- return this._manifest ? this._manifest.duration : 0
+ if (!this._manifest)
+ return 0;
+ return this._manifest.media.reduce((duration, media) => { return duration + media.duration }, 0);
}
get initSegment()
Added: trunk/PerformanceTests/MediaTime/Configurations/Base.xcconfig (0 => 211746)
--- trunk/PerformanceTests/MediaTime/Configurations/Base.xcconfig (rev 0)
+++ trunk/PerformanceTests/MediaTime/Configurations/Base.xcconfig 2017-02-06 21:49:24 UTC (rev 211746)
@@ -0,0 +1,119 @@
+// Copyright (C) 2009, 2010, 2011, 2013 Apple Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "../../../../Internal/Configurations/HaveInternalSDK.xcconfig"
+
+USE_INTERNAL_SDK = $(USE_INTERNAL_SDK_$(CONFIGURATION));
+USE_INTERNAL_SDK_Production = YES;
+USE_INTERNAL_SDK_Debug = $(HAVE_INTERNAL_SDK);
+USE_INTERNAL_SDK_Release = $(HAVE_INTERNAL_SDK);
+
+CLANG_CXX_LANGUAGE_STANDARD = gnu++14;
+CLANG_CXX_LIBRARY = libc++;
+CLANG_WARN_BOOL_CONVERSION = YES;
+CLANG_WARN_CONSTANT_CONVERSION = YES;
+CLANG_WARN_CXX0X_EXTENSIONS = NO;
+CLANG_WARN_EMPTY_BODY = YES;
+CLANG_WARN_ENUM_CONVERSION = YES;
+CLANG_WARN_INFINITE_RECURSION = YES;
+CLANG_WARN_INT_CONVERSION = YES;
+CLANG_WARN_SUSPICIOUS_MOVE = YES;
+CLANG_WARN_UNREACHABLE_CODE = YES;
+CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+COMBINE_HIDPI_IMAGES = NO;
+DEBUG_INFORMATION_FORMAT = dwarf-with-dsym;
+ENABLE_STRICT_OBJC_MSGSEND = YES;
+GCC_C_LANGUAGE_STANDARD = gnu99;
+GCC_DEBUGGING_SYMBOLS = default;
+GCC_DYNAMIC_NO_PIC = NO;
+GCC_ENABLE_CPP_EXCEPTIONS = NO;
+GCC_ENABLE_CPP_RTTI = NO;
+GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+GCC_ENABLE_SYMBOL_SEPARATION = NO;
+GCC_FAST_OBJC_DISPATCH = YES;
+GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
+GCC_NO_COMMON_BLOCKS = YES;
+GCC_OBJC_CALL_CXX_CDTORS = YES;
+GCC_PRECOMPILE_PREFIX_HEADER = YES;
+GCC_PREPROCESSOR_DEFINITIONS = $(DEBUG_DEFINES) $(inherited);
+GCC_STRICT_ALIASING = YES;
+GCC_THREADSAFE_STATICS = NO;
+GCC_TREAT_WARNINGS_AS_ERRORS = YES;
+GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+// FIXME: <http://webkit.org/b/107093> WTF should build with -Wshorten-64-to-32
+GCC_WARN_64_TO_32_BIT_CONVERSION = $(GCC_WARN_64_TO_32_BIT_CONVERSION_$(CURRENT_ARCH));
+GCC_WARN_64_TO_32_BIT_CONVERSION_ = YES;
+GCC_WARN_64_TO_32_BIT_CONVERSION_armv7 = YES;
+GCC_WARN_64_TO_32_BIT_CONVERSION_armv7k = YES;
+GCC_WARN_64_TO_32_BIT_CONVERSION_armv7s = YES;
+GCC_WARN_64_TO_32_BIT_CONVERSION_arm64 = NO;
+GCC_WARN_64_TO_32_BIT_CONVERSION_i386 = YES;
+GCC_WARN_64_TO_32_BIT_CONVERSION_x86_64 = NO;
+GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
+GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
+GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+GCC_WARN_ABOUT_RETURN_TYPE = YES;
+GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
+GCC_WARN_SIGN_COMPARE = YES;
+GCC_WARN_UNDECLARED_SELECTOR = YES;
+GCC_WARN_UNINITIALIZED_AUTOS = YES;
+GCC_WARN_UNUSED_FUNCTION = YES;
+GCC_WARN_UNUSED_VARIABLE = YES;
+PREBINDING = NO;
+WARNING_CFLAGS = -Wall -Wextra -Wcast-qual -Wchar-subscripts -Wextra-tokens -Wformat=2 -Winit-self -Wmissing-format-attribute -Wmissing-noreturn -Wpacked -Wpointer-arith -Wredundant-decls -Wundef -Wwrite-strings -Wexit-time-destructors -Wglobal-constructors -Wtautological-compare -Wimplicit-fallthrough;
+HEADER_SEARCH_PATHS = $(BUILT_PRODUCTS_DIR)/usr/local/include $(DSTROOT)/usr/local/include icu $(HEADER_SEARCH_PATHS);
+
+TARGET_MAC_OS_X_VERSION_MAJOR = $(TARGET_MAC_OS_X_VERSION_MAJOR$(MACOSX_DEPLOYMENT_TARGET:suffix:identifier));
+TARGET_MAC_OS_X_VERSION_MAJOR_10 = 101000;
+TARGET_MAC_OS_X_VERSION_MAJOR_11 = 101100;
+TARGET_MAC_OS_X_VERSION_MAJOR_12 = 101200;
+TARGET_MAC_OS_X_VERSION_MAJOR_13 = 101300;
+
+SUPPORTED_PLATFORMS = iphoneos iphonesimulator macosx appletvos appletvsimulator watchos watchsimulator;
+
+_javascript_CORE_FRAMEWORKS_DIR = $(SYSTEM_LIBRARY_DIR)/Frameworks;
+
+// DEBUG_DEFINES, GCC_OPTIMIZATION_LEVEL, STRIP_INSTALLED_PRODUCT and DEAD_CODE_STRIPPING vary between the debug and normal variants.
+// We set up the values for each variant here, and have the Debug configuration in the Xcode project use the _debug variant.
+DEBUG_DEFINES_debug = ;
+DEBUG_DEFINES_normal = NDEBUG;
+DEBUG_DEFINES = $(DEBUG_DEFINES_$(CURRENT_VARIANT));
+
+GCC_OPTIMIZATION_LEVEL = $(GCC_OPTIMIZATION_LEVEL_$(CURRENT_VARIANT));
+GCC_OPTIMIZATION_LEVEL_normal = 3;
+GCC_OPTIMIZATION_LEVEL_debug = 0;
+
+STRIP_INSTALLED_PRODUCT = $(STRIP_INSTALLED_PRODUCT_$(CURRENT_VARIANT));
+STRIP_INSTALLED_PRODUCT_normal = YES;
+STRIP_INSTALLED_PRODUCT_debug = NO;
+
+DEAD_CODE_STRIPPING_debug = NO;
+DEAD_CODE_STRIPPING_normal = YES;
+DEAD_CODE_STRIPPING = $(DEAD_CODE_STRIPPING_$(CURRENT_VARIANT));
+
+SDKROOT = macosx.internal;
+
+OTHER_CFLAGS = $(ASAN_OTHER_CFLAGS);
+OTHER_CPLUSPLUSFLAGS = $(ASAN_OTHER_CPLUSPLUSFLAGS);
+OTHER_LDFLAGS = $(ASAN_OTHER_LDFLAGS);
Added: trunk/PerformanceTests/MediaTime/Configurations/DebugRelease.xcconfig (0 => 211746)
--- trunk/PerformanceTests/MediaTime/Configurations/DebugRelease.xcconfig (rev 0)
+++ trunk/PerformanceTests/MediaTime/Configurations/DebugRelease.xcconfig 2017-02-06 21:49:24 UTC (rev 211746)
@@ -0,0 +1,42 @@
+// Copyright (C) 2009, 2010, 2013 Apple Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "Base.xcconfig"
+
+ARCHS = $(ARCHS_STANDARD_32_64_BIT);
+_ONLY_ACTIVE_ARCH_ = YES;
+
+TARGET_MAC_OS_X_VERSION_MAJOR = $(MAC_OS_X_VERSION_MAJOR);
+
+MACOSX_DEPLOYMENT_TARGET = $(MACOSX_DEPLOYMENT_TARGET_$(PLATFORM_NAME)_$(TARGET_MAC_OS_X_VERSION_MAJOR));
+MACOSX_DEPLOYMENT_TARGET_macosx_101000 = 10.10;
+MACOSX_DEPLOYMENT_TARGET_macosx_101100 = 10.11;
+MACOSX_DEPLOYMENT_TARGET_macosx_101200 = 10.12;
+MACOSX_DEPLOYMENT_TARGET_macosx_101300 = 10.13;
+
+GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES;
+DEBUG_INFORMATION_FORMAT = dwarf;
+
+SDKROOT = $(SDKROOT_$(USE_INTERNAL_SDK));
+SDKROOT_ = macosx;
+SDKROOT_YES = macosx.internal;
Added: trunk/PerformanceTests/MediaTime/Makefile (0 => 211746)
--- trunk/PerformanceTests/MediaTime/Makefile (rev 0)
+++ trunk/PerformanceTests/MediaTime/Makefile 2017-02-06 21:49:24 UTC (rev 211746)
@@ -0,0 +1,2 @@
+SCRIPTS_PATH ?= ../../Tools/Scripts
+include ../../Makefile.shared
Added: trunk/PerformanceTests/MediaTime/MediaTime.xcodeproj/project.pbxproj (0 => 211746)
--- trunk/PerformanceTests/MediaTime/MediaTime.xcodeproj/project.pbxproj (rev 0)
+++ trunk/PerformanceTests/MediaTime/MediaTime.xcodeproj/project.pbxproj 2017-02-06 21:49:24 UTC (rev 211746)
@@ -0,0 +1,256 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ CDB099E11E4308470039E198 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDB099E01E4308470039E198 /* main.cpp */; };
+ CDB099E91E4308700039E198 /* libWTF.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CDB099E81E4308700039E198 /* libWTF.a */; };
+ CDB099EB1E430B250039E198 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDB099EA1E430B250039E198 /* CoreFoundation.framework */; };
+ CDB099ED1E430B440039E198 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDB099EC1E430B440039E198 /* Foundation.framework */; };
+ CDB099EF1E430B550039E198 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CDB099EE1E430B550039E198 /* libicucore.dylib */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ CDB099DB1E4308470039E198 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ CD836CFE1E43BDB4009F8091 /* Base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Base.xcconfig; sourceTree = "<group>"; };
+ CD836D001E43BDB4009F8091 /* DebugRelease.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = DebugRelease.xcconfig; sourceTree = "<group>"; };
+ CDB099DD1E4308470039E198 /* MediaTime */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = MediaTime; sourceTree = BUILT_PRODUCTS_DIR; };
+ CDB099E01E4308470039E198 /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = ../../../../Testcases/MediaTimeTestcase/MediaTime/main.cpp; sourceTree = "<group>"; };
+ CDB099E81E4308700039E198 /* libWTF.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libWTF.a; path = ../../WebKit.git/OpenSource/WebKitBuild/Debug/libWTF.a; sourceTree = "<group>"; };
+ CDB099EA1E430B250039E198 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
+ CDB099EC1E430B440039E198 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ CDB099EE1E430B550039E198 /* libicucore.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libicucore.dylib; path = usr/lib/libicucore.dylib; sourceTree = SDKROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ CDB099DA1E4308470039E198 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ CDB099EF1E430B550039E198 /* libicucore.dylib in Frameworks */,
+ CDB099ED1E430B440039E198 /* Foundation.framework in Frameworks */,
+ CDB099EB1E430B250039E198 /* CoreFoundation.framework in Frameworks */,
+ CDB099E91E4308700039E198 /* libWTF.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ CD836CFD1E43BDB4009F8091 /* Configurations */ = {
+ isa = PBXGroup;
+ children = (
+ CD836CFE1E43BDB4009F8091 /* Base.xcconfig */,
+ CD836D001E43BDB4009F8091 /* DebugRelease.xcconfig */,
+ );
+ path = Configurations;
+ sourceTree = "<group>";
+ };
+ CDB099D41E4308470039E198 = {
+ isa = PBXGroup;
+ children = (
+ CDB099E01E4308470039E198 /* main.cpp */,
+ CD836CFD1E43BDB4009F8091 /* Configurations */,
+ CDB099DE1E4308470039E198 /* Products */,
+ CDB099E71E43086F0039E198 /* Frameworks */,
+ );
+ sourceTree = "<group>";
+ };
+ CDB099DE1E4308470039E198 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ CDB099DD1E4308470039E198 /* MediaTime */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ CDB099E71E43086F0039E198 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ CDB099EE1E430B550039E198 /* libicucore.dylib */,
+ CDB099EC1E430B440039E198 /* Foundation.framework */,
+ CDB099EA1E430B250039E198 /* CoreFoundation.framework */,
+ CDB099E81E4308700039E198 /* libWTF.a */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ CDB099DC1E4308470039E198 /* MediaTime */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = CDB099E41E4308470039E198 /* Build configuration list for PBXNativeTarget "MediaTime" */;
+ buildPhases = (
+ CDB099D91E4308470039E198 /* Sources */,
+ CDB099DA1E4308470039E198 /* Frameworks */,
+ CDB099DB1E4308470039E198 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = MediaTime;
+ productName = MediaTimeTestcase;
+ productReference = CDB099DD1E4308470039E198 /* MediaTime */;
+ productType = "com.apple.product-type.tool";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ CDB099D51E4308470039E198 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0830;
+ ORGANIZATIONNAME = "Jeremy Noble";
+ TargetAttributes = {
+ CDB099DC1E4308470039E198 = {
+ CreatedOnToolsVersion = 8.3;
+ DevelopmentTeam = G5UYP5CS7K;
+ ProvisioningStyle = Automatic;
+ };
+ };
+ };
+ buildConfigurationList = CDB099D81E4308470039E198 /* Build configuration list for PBXProject "MediaTime" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = CDB099D41E4308470039E198;
+ productRefGroup = CDB099DE1E4308470039E198 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ CDB099DC1E4308470039E198 /* MediaTime */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+ CDB099D91E4308470039E198 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ CDB099E11E4308470039E198 /* main.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ CDB099E21E4308470039E198 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = CD836D001E43BDB4009F8091 /* DebugRelease.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_TESTABILITY = YES;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ _ONLY_ACTIVE_ARCH_ = YES;
+ };
+ name = Debug;
+ };
+ CDB099E31E4308470039E198 /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = CD836D001E43BDB4009F8091 /* DebugRelease.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_NO_COMMON_BLOCKS = YES;
+ };
+ name = Release;
+ };
+ CDB099E51E4308470039E198 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+ DEVELOPMENT_TEAM = G5UYP5CS7K;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ CDB099E61E4308470039E198 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+ DEVELOPMENT_TEAM = G5UYP5CS7K;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ CDB099F01E4394540039E198 /* Control */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_NO_COMMON_BLOCKS = YES;
+ HEADER_SEARCH_PATHS = /usr/local/include;
+ LIBRARY_SEARCH_PATHS = /usr/local/lib;
+ };
+ name = Control;
+ };
+ CDB099F11E4394540039E198 /* Control */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+ DEVELOPMENT_TEAM = G5UYP5CS7K;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Control;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ CDB099D81E4308470039E198 /* Build configuration list for PBXProject "MediaTime" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ CDB099E21E4308470039E198 /* Debug */,
+ CDB099E31E4308470039E198 /* Release */,
+ CDB099F01E4394540039E198 /* Control */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ CDB099E41E4308470039E198 /* Build configuration list for PBXNativeTarget "MediaTime" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ CDB099E51E4308470039E198 /* Debug */,
+ CDB099E61E4308470039E198 /* Release */,
+ CDB099F11E4394540039E198 /* Control */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = CDB099D51E4308470039E198 /* Project object */;
+}
Added: trunk/PerformanceTests/MediaTime/main.cpp (0 => 211746)
--- trunk/PerformanceTests/MediaTime/main.cpp (rev 0)
+++ trunk/PerformanceTests/MediaTime/main.cpp 2017-02-06 21:49:24 UTC (rev 211746)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <chrono>
+#include <random>
+#include <set>
+#include <wtf/MediaTime.h>
+
+using namespace std;
+using namespace std::chrono;
+
+static const size_t setSize = 100000;
+
+void performTest(const char* name, function<void()> test)
+{
+ vector<double> runtimes(21);
+ for (auto& runtime : runtimes) {
+ auto start = steady_clock::now();
+ test();
+ runtime = duration_cast<milliseconds>(steady_clock::now() - start).count();
+ }
+ sort(runtimes.begin(), runtimes.end());
+ double sum = std::accumulate(runtimes.begin(), runtimes.end(), 0);
+ double mean = sum / runtimes.size();
+ double median = runtimes[(runtimes.size() + 1) / 2];
+ double min = runtimes.front();
+ double max = runtimes.back();
+ double sqSum = std::inner_product(runtimes.begin(), runtimes.end(), runtimes.begin(), 0);
+ double stdev = std::sqrt(sqSum / runtimes.size() - mean * mean);
+
+ printf("RESULT %s: Time= %g ms", name, sum);
+ printf("median= %g ms, stdev= %g ms, min= %g ms, max = %g ms", median, stdev, min, max);
+}
+
+void test(int32_t count, function<MediaTime(int32_t)> generator)
+{
+ set<MediaTime> times;
+
+ for (int32_t i = 0; i < count; ++i)
+ times.insert(generator(i));
+
+ for (int32_t i = 0; i < count; ++i)
+ times.upper_bound(generator(i));
+}
+
+int main(int argc, const char * argv[])
+{
+ performTest("Equal TimeScales", [] { test(setSize, [] (int32_t i) { return MediaTime(i, 1); }); });
+ performTest("Equal TimeValues", [] { test(setSize, [] (int32_t i) { return MediaTime(1, i + 1); }); });
+ performTest("Disparate TimeValues & TimeScales", [] { test(setSize, [] (int32_t i) { return MediaTime(i, i + 1); }); });
+ performTest("Non-uniform", [] {
+ test(setSize, [] (int32_t i) {
+ switch (i % 6) {
+ case 0:
+ return MediaTime::invalidTime();
+ case 1:
+ return MediaTime::positiveInfiniteTime();
+ case 2:
+ return MediaTime::negativeInfiniteTime();
+ case 3:
+ return MediaTime::indefiniteTime();
+ case 4:
+ return MediaTime(i, 1);
+ case 5:
+ default:
+ return MediaTime(i, i + 1);
+ }
+ });
+ });
+
+ return 0;
+}
Modified: trunk/PerformanceTests/Skipped (211745 => 211746)
--- trunk/PerformanceTests/Skipped 2017-02-06 20:49:25 UTC (rev 211745)
+++ trunk/PerformanceTests/Skipped 2017-02-06 21:49:24 UTC (rev 211746)
@@ -107,6 +107,7 @@
# Media tests take too long to run; require MSE, HLS which are not supported on all ports;
# and require a webserver (run-webkit-httpd) which is not part of normal performance testing.
Media/
+MediaTime/
# Bugs 167622, 167637, 167638 and 167640 - Some IndexedDB test deadlock on the GTK+ perf bot.
[GTK] IndexedDB/index-get.html
Modified: trunk/Source/WTF/ChangeLog (211745 => 211746)
--- trunk/Source/WTF/ChangeLog 2017-02-06 20:49:25 UTC (rev 211745)
+++ trunk/Source/WTF/ChangeLog 2017-02-06 21:49:24 UTC (rev 211746)
@@ -1,3 +1,41 @@
+2017-02-06 Jer Noble <jer.no...@apple.com>
+
+ Playback stalls when a SourceBuffer append causes frame eviction
+ https://bugs.webkit.org/show_bug.cgi?id=167834
+
+ Reviewed by Eric Carlson.
+
+ 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:
+
2017-02-04 Michael Catanzaro <mcatanz...@igalia.com>
[GTK] Fix huge ENABLE_RESOURCE_USAGE warning spam
Modified: trunk/Source/WTF/wtf/MediaTime.cpp (211745 => 211746)
--- trunk/Source/WTF/wtf/MediaTime.cpp 2017-02-06 20:49:25 UTC (rev 211745)
+++ trunk/Source/WTF/wtf/MediaTime.cpp 2017-02-06 21:49:24 UTC (rev 211746)
@@ -30,6 +30,7 @@
#include "MediaTime.h"
#include <algorithm>
+#include <cstdlib>
#include <wtf/CheckedArithmetic.h>
#include <wtf/MathExtras.h>
#include <wtf/PrintStream.h>
@@ -36,10 +37,10 @@
namespace WTF {
-static int32_t greatestCommonDivisor(int32_t a, int32_t b)
+static uint32_t greatestCommonDivisor(uint32_t a, uint32_t b)
{
// Euclid's Algorithm
- int32_t temp = 0;
+ uint32_t temp = 0;
while (b) {
temp = b;
b = a % b;
@@ -48,17 +49,17 @@
return a;
}
-static int32_t leastCommonMultiple(int32_t a, int32_t b, int32_t &result)
+static uint32_t leastCommonMultiple(uint32_t a, uint32_t b, uint32_t &result)
{
return safeMultiply(a, b / greatestCommonDivisor(a, b), result);
}
-static int32_t signum(int64_t val)
+static int64_t signum(int64_t val)
{
return (0 < val) - (val < 0);
}
-const int32_t MediaTime::MaximumTimeScale = 0x7fffffffL;
+const uint32_t MediaTime::MaximumTimeScale = 0x7fffffffL;
MediaTime::MediaTime()
: m_timeValue(0)
@@ -67,7 +68,7 @@
{
}
-MediaTime::MediaTime(int64_t value, int32_t scale, uint32_t flags)
+MediaTime::MediaTime(int64_t value, uint32_t scale, uint8_t flags)
: m_timeValue(value)
, m_timeScale(scale)
, m_timeFlags(flags)
@@ -99,7 +100,7 @@
return value;
}
-MediaTime MediaTime::createWithFloat(float floatTime, int32_t timeScale)
+MediaTime MediaTime::createWithFloat(float floatTime, uint32_t timeScale)
{
if (floatTime != floatTime)
return invalidTime();
@@ -131,7 +132,7 @@
return value;
}
-MediaTime MediaTime::createWithDouble(double doubleTime, int32_t timeScale)
+MediaTime MediaTime::createWithDouble(double doubleTime, uint32_t timeScale)
{
if (doubleTime != doubleTime)
return invalidTime();
@@ -212,7 +213,7 @@
else if (b.hasDoubleValue())
b.setTimeScale(DefaultTimeScale);
- int32_t commonTimeScale;
+ uint32_t commonTimeScale;
if (!leastCommonMultiple(a.m_timeScale, b.m_timeScale, commonTimeScale) || commonTimeScale > MaximumTimeScale)
commonTimeScale = MaximumTimeScale;
a.setTimeScale(commonTimeScale);
@@ -258,7 +259,7 @@
else if (b.hasDoubleValue())
b.setTimeScale(DefaultTimeScale);
- int32_t commonTimeScale;
+ uint32_t commonTimeScale;
if (!leastCommonMultiple(this->m_timeScale, rhs.m_timeScale, commonTimeScale) || commonTimeScale > MaximumTimeScale)
commonTimeScale = MaximumTimeScale;
a.setTimeScale(commonTimeScale);
@@ -334,73 +335,41 @@
return a;
}
-bool MediaTime::operator<(const MediaTime& rhs) const
-{
- return compare(rhs) == LessThan;
-}
-
-bool MediaTime::operator>(const MediaTime& rhs) const
-{
- return compare(rhs) == GreaterThan;
-}
-
-bool MediaTime::operator!=(const MediaTime& rhs) const
-{
- return compare(rhs) != EqualTo;
-}
-
-bool MediaTime::operator==(const MediaTime& rhs) const
-{
- return compare(rhs) == EqualTo;
-}
-
-bool MediaTime::operator>=(const MediaTime& rhs) const
-{
- return compare(rhs) >= EqualTo;
-}
-
-bool MediaTime::operator<=(const MediaTime& rhs) const
-{
- return compare(rhs) <= EqualTo;
-}
-
bool MediaTime::operator!() const
{
- return compare(zeroTime()) == EqualTo;
+ return (m_timeFlags == Valid && !m_timeValue)
+ || (m_timeFlags == (Valid | DoubleValue) && !m_timeValueAsDouble);
}
MediaTime::operator bool() const
{
- return compare(zeroTime()) != EqualTo;
+ return !(m_timeFlags == Valid && !m_timeValue)
+ && !(m_timeFlags == (Valid | DoubleValue) && !m_timeValueAsDouble);
}
MediaTime::ComparisonFlags MediaTime::compare(const MediaTime& rhs) const
{
- if ((isPositiveInfinite() && rhs.isPositiveInfinite())
- || (isNegativeInfinite() && rhs.isNegativeInfinite())
- || (isInvalid() && rhs.isInvalid())
- || (isIndefinite() && rhs.isIndefinite()))
+ auto andFlags = m_timeFlags & rhs.m_timeFlags;
+ if (andFlags & (PositiveInfinite | NegativeInfinite | Indefinite))
return EqualTo;
- if (isInvalid())
- return GreaterThan;
+ auto orFlags = m_timeFlags | rhs.m_timeFlags;
+ if (!(orFlags & Valid))
+ return EqualTo;
- if (rhs.isInvalid())
- return LessThan;
+ if (!(andFlags & Valid))
+ return isInvalid() ? GreaterThan : LessThan;
- if (rhs.isNegativeInfinite() || isPositiveInfinite())
- return GreaterThan;
+ if (orFlags & NegativeInfinite)
+ return isNegativeInfinite() ? LessThan : GreaterThan;
- if (rhs.isPositiveInfinite() || isNegativeInfinite())
- return LessThan;
+ if (orFlags & PositiveInfinite)
+ return isPositiveInfinite() ? GreaterThan : LessThan;
- if (isIndefinite())
- return GreaterThan;
+ if (orFlags & Indefinite)
+ return isIndefinite() ? GreaterThan : LessThan;
- if (rhs.isIndefinite())
- return LessThan;
-
- if (hasDoubleValue() && rhs.hasDoubleValue()) {
+ if (andFlags & DoubleValue) {
if (m_timeValueAsDouble == rhs.m_timeValueAsDouble)
return EqualTo;
@@ -407,7 +376,7 @@
return m_timeValueAsDouble < rhs.m_timeValueAsDouble ? LessThan : GreaterThan;
}
- if (hasDoubleValue() || rhs.hasDoubleValue()) {
+ if (orFlags & DoubleValue) {
double a = toDouble();
double b = rhs.toDouble();
if (a > b)
@@ -417,20 +386,47 @@
return EqualTo;
}
- MediaTime a = *this;
- MediaTime b = rhs;
+ if ((m_timeValue < 0) != (rhs.m_timeValue < 0))
+ return m_timeValue < 0 ? LessThan : GreaterThan;
- int64_t rhsWhole = b.m_timeValue / b.m_timeScale;
- int64_t lhsWhole = a.m_timeValue / a.m_timeScale;
+ if (!m_timeValue && !rhs.m_timeValue)
+ return EqualTo;
+
+ if (m_timeScale == rhs.m_timeScale) {
+ if (m_timeValue == rhs.m_timeValue)
+ return EqualTo;
+ return m_timeValue < rhs.m_timeValue ? LessThan : GreaterThan;
+ }
+
+ if (m_timeValue == rhs.m_timeValue)
+ return m_timeScale < rhs.m_timeScale ? GreaterThan : LessThan;
+
+ if (m_timeValue < rhs.m_timeValue && m_timeScale > rhs.m_timeScale)
+ return LessThan;
+
+ if (m_timeValue > rhs.m_timeValue && m_timeScale < rhs.m_timeScale)
+ return GreaterThan;
+
+ int64_t lhsFactor;
+ int64_t rhsFactor;
+ if (safeMultiply(m_timeValue, static_cast<int64_t>(rhs.m_timeScale), lhsFactor)
+ && safeMultiply(rhs.m_timeValue, static_cast<int64_t>(m_timeScale), rhsFactor)) {
+ if (lhsFactor == rhsFactor)
+ return EqualTo;
+ return lhsFactor < rhsFactor ? LessThan : GreaterThan;
+ }
+
+ int64_t rhsWhole = rhs.m_timeValue / rhs.m_timeScale;
+ int64_t lhsWhole = m_timeValue / m_timeScale;
if (lhsWhole > rhsWhole)
return GreaterThan;
if (lhsWhole < rhsWhole)
return LessThan;
- int64_t rhsRemain = b.m_timeValue % b.m_timeScale;
- int64_t lhsRemain = a.m_timeValue % a.m_timeScale;
- int64_t lhsFactor = lhsRemain * b.m_timeScale;
- int64_t rhsFactor = rhsRemain * a.m_timeScale;
+ int64_t rhsRemain = rhs.m_timeValue % rhs.m_timeScale;
+ int64_t lhsRemain = m_timeValue % m_timeScale;
+ lhsFactor = lhsRemain * rhs.m_timeScale;
+ rhsFactor = rhsRemain * m_timeScale;
if (lhsFactor == rhsFactor)
return EqualTo;
@@ -474,7 +470,7 @@
return *time;
}
-void MediaTime::setTimeScale(int32_t timeScale)
+void MediaTime::setTimeScale(uint32_t timeScale)
{
if (hasDoubleValue()) {
*this = MediaTime::createWithDouble(m_timeValueAsDouble, timeScale);
@@ -490,7 +486,7 @@
// timescale by two until the number will fit, and round the
// result.
int64_t newWholePart;
- while (!safeMultiply(wholePart, timeScale, newWholePart))
+ while (!safeMultiply(wholePart, static_cast<int64_t>(timeScale), newWholePart))
timeScale /= 2;
int64_t remainder = m_timeValue % m_timeScale;
@@ -513,7 +509,7 @@
return MediaTime::createWithDouble(fabs(rhs.m_timeValueAsDouble));
MediaTime val = rhs;
- val.m_timeValue *= signum(rhs.m_timeScale) * signum(rhs.m_timeValue);
+ val.m_timeValue = std::abs(rhs.m_timeValue);
return val;
}
Modified: trunk/Source/WTF/wtf/MediaTime.h (211745 => 211746)
--- trunk/Source/WTF/wtf/MediaTime.h 2017-02-06 20:49:25 UTC (rev 211745)
+++ trunk/Source/WTF/wtf/MediaTime.h 2017-02-06 21:49:24 UTC (rev 211746)
@@ -53,14 +53,14 @@
};
MediaTime();
- MediaTime(int64_t value, int32_t scale, uint32_t flags = Valid);
+ MediaTime(int64_t value, uint32_t scale, uint8_t flags = Valid);
MediaTime(const MediaTime& rhs);
~MediaTime();
static MediaTime createWithFloat(float floatTime);
- static MediaTime createWithFloat(float floatTime, int32_t timeScale);
+ static MediaTime createWithFloat(float floatTime, uint32_t timeScale);
static MediaTime createWithDouble(double doubleTime);
- static MediaTime createWithDouble(double doubleTime, int32_t timeScale);
+ static MediaTime createWithDouble(double doubleTime, uint32_t timeScale);
float toFloat() const;
double toDouble() const;
@@ -72,12 +72,12 @@
MediaTime operator-(const MediaTime& rhs) const;
MediaTime operator-() const;
MediaTime operator*(int32_t) const;
- bool operator<(const MediaTime& rhs) const;
- bool operator>(const MediaTime& rhs) const;
- bool operator!=(const MediaTime& rhs) const;
- bool operator==(const MediaTime& rhs) const;
- bool operator>=(const MediaTime& rhs) const;
- bool operator<=(const MediaTime& rhs) const;
+ bool operator<(const MediaTime& rhs) const { return compare(rhs) == LessThan; }
+ bool operator>(const MediaTime& rhs) const { return compare(rhs) == GreaterThan; }
+ bool operator!=(const MediaTime& rhs) const { return compare(rhs) != EqualTo; }
+ bool operator==(const MediaTime& rhs) const { return compare(rhs) == EqualTo; }
+ bool operator>=(const MediaTime& rhs) const { return compare(rhs) >= EqualTo; }
+ bool operator<=(const MediaTime& rhs) const { return compare(rhs) <= EqualTo; }
bool operator!() const;
explicit operator bool() const;
@@ -105,7 +105,7 @@
static const MediaTime& indefiniteTime();
const int64_t& timeValue() const { return m_timeValue; }
- const int32_t& timeScale() const { return m_timeScale; }
+ const uint32_t& timeScale() const { return m_timeScale; }
void dump(PrintStream& out) const;
@@ -117,18 +117,18 @@
friend WTF_EXPORT_PRIVATE MediaTime abs(const MediaTime& rhs);
- static const int32_t DefaultTimeScale = 10000000;
- static const int32_t MaximumTimeScale;
+ static const uint32_t DefaultTimeScale = 10000000;
+ static const uint32_t MaximumTimeScale;
private:
- void setTimeScale(int32_t);
+ void setTimeScale(uint32_t);
union {
int64_t m_timeValue;
double m_timeValueAsDouble;
};
- int32_t m_timeScale;
- uint32_t m_timeFlags;
+ uint32_t m_timeScale;
+ uint8_t m_timeFlags;
};
inline MediaTime operator*(int32_t lhs, const MediaTime& rhs) { return rhs.operator*(lhs); }
Modified: trunk/Source/WebCore/ChangeLog (211745 => 211746)
--- trunk/Source/WebCore/ChangeLog 2017-02-06 20:49:25 UTC (rev 211745)
+++ trunk/Source/WebCore/ChangeLog 2017-02-06 21:49:24 UTC (rev 211746)
@@ -1,3 +1,51 @@
+2017-02-06 Jer Noble <jer.no...@apple.com>
+
+ Playback stalls when a SourceBuffer append causes frame eviction
+ https://bugs.webkit.org/show_bug.cgi?id=167834
+
+ Reviewed by Eric Carlson.
+
+ 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:
+
2017-02-06 Said Abou-Hallawa <sabouhall...@apple.com>
Rename AnimationController to CSSAnimationController
Modified: trunk/Source/WebCore/Modules/mediasource/SampleMap.cpp (211745 => 211746)
--- trunk/Source/WebCore/Modules/mediasource/SampleMap.cpp 2017-02-06 20:49:25 UTC (rev 211745)
+++ trunk/Source/WebCore/Modules/mediasource/SampleMap.cpp 2017-02-06 21:49:24 UTC (rev 211746)
@@ -142,13 +142,21 @@
PresentationOrderSampleMap::iterator PresentationOrderSampleMap::findSampleContainingPresentationTime(const MediaTime& time)
{
- auto range = std::equal_range(begin(), end(), time, SampleIsLessThanMediaTimeComparator<MapType>());
- if (range.first == range.second)
+ // upper_bound will return the first sample whose presentation start time is greater than the search time.
+ // If this is the first sample, that means no sample in the map contains the requested time.
+ auto iter = m_samples.upper_bound(time);
+ if (iter == begin())
return end();
- return range.first;
+
+ // Look at the previous sample; does it contain the requested time?
+ --iter;
+ MediaSample& sample = *iter->second;
+ if (sample.presentationTime() + sample.duration() > time)
+ return iter;
+ return end();
}
-PresentationOrderSampleMap::iterator PresentationOrderSampleMap::findSampleOnOrAfterPresentationTime(const MediaTime& time)
+PresentationOrderSampleMap::iterator PresentationOrderSampleMap::findSampleStartingOnOrAfterPresentationTime(const MediaTime& time)
{
return m_samples.lower_bound(time);
}
@@ -168,7 +176,22 @@
PresentationOrderSampleMap::reverse_iterator PresentationOrderSampleMap::reverseFindSampleBeforePresentationTime(const MediaTime& time)
{
- return std::lower_bound(rbegin(), rend(), time, SampleIsGreaterThanMediaTimeComparator<MapType>());
+ if (m_samples.empty())
+ return rend();
+
+ // upper_bound will return the first sample whose presentation start time is greater than the search time.
+ auto found = m_samples.upper_bound(time);
+
+ // If no sample was found with a time greater than the search time, return the last sample.
+ if (found == end())
+ return rbegin();
+
+ // If the first sample has a time grater than the search time, no samples will have a presentation time before the search time.
+ if (found == begin())
+ return rend();
+
+ // Otherwise, return the sample immediately previous to the one found.
+ return --reverse_iterator(--found);
}
DecodeOrderSampleMap::reverse_iterator DecodeOrderSampleMap::reverseFindSampleWithDecodeKey(const KeyType& key)
@@ -203,7 +226,7 @@
DecodeOrderSampleMap::iterator DecodeOrderSampleMap::findSyncSampleAfterPresentationTime(const MediaTime& time, const MediaTime& threshold)
{
- PresentationOrderSampleMap::iterator currentSamplePTS = m_presentationOrder.findSampleOnOrAfterPresentationTime(time);
+ PresentationOrderSampleMap::iterator currentSamplePTS = m_presentationOrder.findSampleStartingOnOrAfterPresentationTime(time);
if (currentSamplePTS == m_presentationOrder.end())
return end();
@@ -228,14 +251,24 @@
PresentationOrderSampleMap::iterator_range PresentationOrderSampleMap::findSamplesBetweenPresentationTimes(const MediaTime& beginTime, const MediaTime& endTime)
{
- std::pair<MediaTime, MediaTime> range(beginTime, endTime);
- return std::equal_range(begin(), end(), range, SamplePresentationTimeIsInsideRangeComparator());
+ // startTime is inclusive, so use lower_bound to include samples wich start exactly at startTime.
+ // endTime is not inclusive, so use lower_bound to exclude samples which start exactly at endTime.
+ auto lower_bound = m_samples.lower_bound(beginTime);
+ auto upper_bound = m_samples.lower_bound(endTime);
+ if (lower_bound == upper_bound)
+ return { end(), end() };
+ return { lower_bound, upper_bound };
}
PresentationOrderSampleMap::iterator_range PresentationOrderSampleMap::findSamplesWithinPresentationRange(const MediaTime& beginTime, const MediaTime& endTime)
{
- std::pair<MediaTime, MediaTime> range(beginTime, endTime);
- return std::equal_range(begin(), end(), range, SamplePresentationTimeIsWithinRangeComparator());
+ // startTime is not inclusive, so use upper_bound to exclude samples which start exactly at startTime.
+ // endTime is inclusive, so use upper_bound to include samples which start exactly at endTime.
+ auto lower_bound = m_samples.upper_bound(beginTime);
+ auto upper_bound = m_samples.upper_bound(endTime);
+ if (lower_bound == upper_bound)
+ return { end(), end() };
+ return { lower_bound, upper_bound };
}
PresentationOrderSampleMap::iterator_range PresentationOrderSampleMap::findSamplesWithinPresentationRangeFromEnd(const MediaTime& beginTime, const MediaTime& endTime)
Modified: trunk/Source/WebCore/Modules/mediasource/SampleMap.h (211745 => 211746)
--- trunk/Source/WebCore/Modules/mediasource/SampleMap.h 2017-02-06 20:49:25 UTC (rev 211745)
+++ trunk/Source/WebCore/Modules/mediasource/SampleMap.h 2017-02-06 21:49:24 UTC (rev 211746)
@@ -46,23 +46,23 @@
typedef MapType::const_reverse_iterator const_reverse_iterator;
typedef std::pair<iterator, iterator> iterator_range;
- iterator begin() { return m_samples.begin(); }
- const_iterator begin() const { return m_samples.begin(); }
- iterator end() { return m_samples.end(); }
- const_iterator end() const { return m_samples.end(); }
- reverse_iterator rbegin() { return m_samples.rbegin(); }
- const_reverse_iterator rbegin() const { return m_samples.rbegin(); }
- reverse_iterator rend() { return m_samples.rend(); }
- const_reverse_iterator rend() const { return m_samples.rend(); }
+ WEBCORE_EXPORT iterator begin() { return m_samples.begin(); }
+ WEBCORE_EXPORT const_iterator begin() const { return m_samples.begin(); }
+ WEBCORE_EXPORT iterator end() { return m_samples.end(); }
+ WEBCORE_EXPORT const_iterator end() const { return m_samples.end(); }
+ WEBCORE_EXPORT reverse_iterator rbegin() { return m_samples.rbegin(); }
+ WEBCORE_EXPORT const_reverse_iterator rbegin() const { return m_samples.rbegin(); }
+ WEBCORE_EXPORT reverse_iterator rend() { return m_samples.rend(); }
+ WEBCORE_EXPORT const_reverse_iterator rend() const { return m_samples.rend(); }
- iterator findSampleWithPresentationTime(const MediaTime&);
- iterator findSampleContainingPresentationTime(const MediaTime&);
- iterator findSampleOnOrAfterPresentationTime(const MediaTime&);
- reverse_iterator reverseFindSampleContainingPresentationTime(const MediaTime&);
- reverse_iterator reverseFindSampleBeforePresentationTime(const MediaTime&);
- iterator_range findSamplesBetweenPresentationTimes(const MediaTime&, const MediaTime&);
- iterator_range findSamplesWithinPresentationRange(const MediaTime&, const MediaTime&);
- iterator_range findSamplesWithinPresentationRangeFromEnd(const MediaTime&, const MediaTime&);
+ WEBCORE_EXPORT iterator findSampleWithPresentationTime(const MediaTime&);
+ WEBCORE_EXPORT iterator findSampleContainingPresentationTime(const MediaTime&);
+ WEBCORE_EXPORT iterator findSampleStartingOnOrAfterPresentationTime(const MediaTime&);
+ WEBCORE_EXPORT reverse_iterator reverseFindSampleContainingPresentationTime(const MediaTime&);
+ WEBCORE_EXPORT reverse_iterator reverseFindSampleBeforePresentationTime(const MediaTime&);
+ WEBCORE_EXPORT iterator_range findSamplesBetweenPresentationTimes(const MediaTime&, const MediaTime&);
+ WEBCORE_EXPORT iterator_range findSamplesWithinPresentationRange(const MediaTime&, const MediaTime&);
+ WEBCORE_EXPORT iterator_range findSamplesWithinPresentationRangeFromEnd(const MediaTime&, const MediaTime&);
private:
MapType m_samples;
@@ -79,22 +79,22 @@
typedef MapType::const_reverse_iterator const_reverse_iterator;
typedef std::pair<reverse_iterator, reverse_iterator> reverse_iterator_range;
- iterator begin() { return m_samples.begin(); }
- const_iterator begin() const { return m_samples.begin(); }
- iterator end() { return m_samples.end(); }
- const_iterator end() const { return m_samples.end(); }
- reverse_iterator rbegin() { return m_samples.rbegin(); }
- const_reverse_iterator rbegin() const { return m_samples.rbegin(); }
- reverse_iterator rend() { return m_samples.rend(); }
- const_reverse_iterator rend() const { return m_samples.rend(); }
+ WEBCORE_EXPORT iterator begin() { return m_samples.begin(); }
+ WEBCORE_EXPORT const_iterator begin() const { return m_samples.begin(); }
+ WEBCORE_EXPORT iterator end() { return m_samples.end(); }
+ WEBCORE_EXPORT const_iterator end() const { return m_samples.end(); }
+ WEBCORE_EXPORT reverse_iterator rbegin() { return m_samples.rbegin(); }
+ WEBCORE_EXPORT const_reverse_iterator rbegin() const { return m_samples.rbegin(); }
+ WEBCORE_EXPORT reverse_iterator rend() { return m_samples.rend(); }
+ WEBCORE_EXPORT const_reverse_iterator rend() const { return m_samples.rend(); }
- iterator findSampleWithDecodeKey(const KeyType&);
- reverse_iterator reverseFindSampleWithDecodeKey(const KeyType&);
- reverse_iterator findSyncSamplePriorToPresentationTime(const MediaTime&, const MediaTime& threshold = MediaTime::positiveInfiniteTime());
- reverse_iterator findSyncSamplePriorToDecodeIterator(reverse_iterator);
- iterator findSyncSampleAfterPresentationTime(const MediaTime&, const MediaTime& threshold = MediaTime::positiveInfiniteTime());
- iterator findSyncSampleAfterDecodeIterator(iterator);
- reverse_iterator_range findDependentSamples(MediaSample*);
+ WEBCORE_EXPORT iterator findSampleWithDecodeKey(const KeyType&);
+ WEBCORE_EXPORT reverse_iterator reverseFindSampleWithDecodeKey(const KeyType&);
+ WEBCORE_EXPORT reverse_iterator findSyncSamplePriorToPresentationTime(const MediaTime&, const MediaTime& threshold = MediaTime::positiveInfiniteTime());
+ WEBCORE_EXPORT reverse_iterator findSyncSamplePriorToDecodeIterator(reverse_iterator);
+ WEBCORE_EXPORT iterator findSyncSampleAfterPresentationTime(const MediaTime&, const MediaTime& threshold = MediaTime::positiveInfiniteTime());
+ WEBCORE_EXPORT iterator findSyncSampleAfterDecodeIterator(iterator);
+ WEBCORE_EXPORT reverse_iterator_range findDependentSamples(MediaSample*);
private:
MapType m_samples;
@@ -103,24 +103,24 @@
class SampleMap {
public:
- SampleMap()
+ WEBCORE_EXPORT SampleMap()
: m_totalSize(0)
{
}
- bool empty() const;
- void clear();
- void addSample(MediaSample&);
- void removeSample(MediaSample*);
- size_t sizeInBytes() const { return m_totalSize; }
+ WEBCORE_EXPORT bool empty() const;
+ WEBCORE_EXPORT void clear();
+ WEBCORE_EXPORT void addSample(MediaSample&);
+ WEBCORE_EXPORT void removeSample(MediaSample*);
+ WEBCORE_EXPORT size_t sizeInBytes() const { return m_totalSize; }
template<typename I>
void addRange(I begin, I end);
- DecodeOrderSampleMap& decodeOrder() { return m_decodeOrder; }
- const DecodeOrderSampleMap& decodeOrder() const { return m_decodeOrder; }
- PresentationOrderSampleMap& presentationOrder() { return m_decodeOrder.m_presentationOrder; }
- const PresentationOrderSampleMap& presentationOrder() const { return m_decodeOrder.m_presentationOrder; }
+ WEBCORE_EXPORT DecodeOrderSampleMap& decodeOrder() { return m_decodeOrder; }
+ WEBCORE_EXPORT const DecodeOrderSampleMap& decodeOrder() const { return m_decodeOrder; }
+ WEBCORE_EXPORT PresentationOrderSampleMap& presentationOrder() { return m_decodeOrder.m_presentationOrder; }
+ WEBCORE_EXPORT const PresentationOrderSampleMap& presentationOrder() const { return m_decodeOrder.m_presentationOrder; }
private:
DecodeOrderSampleMap m_decodeOrder;
Modified: trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp (211745 => 211746)
--- trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp 2017-02-06 20:49:25 UTC (rev 211745)
+++ trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp 2017-02-06 21:49:24 UTC (rev 211746)
@@ -705,7 +705,7 @@
additionalErasedRanges.add(previousSample.presentationTime() + previousSample.duration(), erasedStart);
}
- auto endIterator = trackBuffer.samples.presentationOrder().findSampleOnOrAfterPresentationTime(erasedEnd);
+ auto endIterator = trackBuffer.samples.presentationOrder().findSampleStartingOnOrAfterPresentationTime(erasedEnd);
if (endIterator == trackBuffer.samples.presentationOrder().end())
additionalErasedRanges.add(erasedEnd, MediaTime::positiveInfiniteTime());
else {
@@ -775,7 +775,7 @@
else
removePresentationEnd = trackBuffer.samples.presentationOrder().findSampleWithPresentationTime(removeDecodeEnd->second->presentationTime());
- PresentationOrderSampleMap::iterator removePresentationStart = trackBuffer.samples.presentationOrder().findSampleOnOrAfterPresentationTime(start);
+ PresentationOrderSampleMap::iterator removePresentationStart = trackBuffer.samples.presentationOrder().findSampleStartingOnOrAfterPresentationTime(start);
if (removePresentationStart == removePresentationEnd)
continue;
@@ -1842,7 +1842,7 @@
auto currentSamplePTSIterator = trackBuffer.samples.presentationOrder().findSampleContainingPresentationTime(time);
if (currentSamplePTSIterator == trackBuffer.samples.presentationOrder().end())
- currentSamplePTSIterator = trackBuffer.samples.presentationOrder().findSampleOnOrAfterPresentationTime(time);
+ currentSamplePTSIterator = trackBuffer.samples.presentationOrder().findSampleStartingOnOrAfterPresentationTime(time);
if (currentSamplePTSIterator == trackBuffer.samples.presentationOrder().end()
|| (currentSamplePTSIterator->first - time) > MediaSource::currentTimeFudgeFactor())
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (211745 => 211746)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2017-02-06 20:49:25 UTC (rev 211745)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2017-02-06 21:49:24 UTC (rev 211746)
@@ -5929,7 +5929,7 @@
CDCFABBD18C0AF78006F8450 /* SelectionSubtreeRoot.h in Headers */ = {isa = PBXBuildFile; fileRef = CDCFABBB18C0AE31006F8450 /* SelectionSubtreeRoot.h */; settings = {ATTRIBUTES = (Private, ); }; };
CDCFABBE18C0AF84006F8450 /* SelectionSubtreeRoot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDCFABBC18C0AF19006F8450 /* SelectionSubtreeRoot.cpp */; };
CDD7089618359F6F002B3DC6 /* SampleMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDD7089418359F6E002B3DC6 /* SampleMap.cpp */; };
- CDD7089718359F6F002B3DC6 /* SampleMap.h in Headers */ = {isa = PBXBuildFile; fileRef = CDD7089518359F6F002B3DC6 /* SampleMap.h */; };
+ CDD7089718359F6F002B3DC6 /* SampleMap.h in Headers */ = {isa = PBXBuildFile; fileRef = CDD7089518359F6F002B3DC6 /* SampleMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
CDDC1E7A18A952F30027A9D4 /* MediaSourcePrivateClient.h in Headers */ = {isa = PBXBuildFile; fileRef = CDDC1E7918A952F30027A9D4 /* MediaSourcePrivateClient.h */; };
CDDE02ED18B3ED6D00CF7FF1 /* CDMSessionAVFoundationObjC.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDDE02EB18B3ED6D00CF7FF1 /* CDMSessionAVFoundationObjC.mm */; };
CDDE02F018B5651300CF7FF1 /* CDMSessionAVStreamSession.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDDE02EF18B5651200CF7FF1 /* CDMSessionAVStreamSession.mm */; };
Modified: trunk/Tools/ChangeLog (211745 => 211746)
--- trunk/Tools/ChangeLog 2017-02-06 20:49:25 UTC (rev 211745)
+++ trunk/Tools/ChangeLog 2017-02-06 21:49:24 UTC (rev 211746)
@@ -1,3 +1,22 @@
+2017-02-06 Jer Noble <jer.no...@apple.com>
+
+ Playback stalls when a SourceBuffer append causes frame eviction
+ https://bugs.webkit.org/show_bug.cgi?id=167834
+
+ Reviewed by Eric Carlson.
+
+ 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):
+
2017-02-06 Ryan Haddad <ryanhad...@apple.com>
Change capitalization in platform name after r211735.
Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (211745 => 211746)
--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2017-02-06 20:49:25 UTC (rev 211745)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2017-02-06 21:49:24 UTC (rev 211746)
@@ -531,6 +531,7 @@
CDC8E4951BC6F10800594FEC /* video-with-audio.mp4 in Copy Resources */ = {isa = PBXBuildFile; fileRef = CDC8E48A1BC5C96200594FEC /* video-with-audio.mp4 */; };
CDC8E4961BC6F10800594FEC /* video-without-audio.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = CDC8E48B1BC5C96200594FEC /* video-without-audio.html */; };
CDC8E4971BC6F10800594FEC /* video-without-audio.mp4 in Copy Resources */ = {isa = PBXBuildFile; fileRef = CDC8E48C1BC5C96200594FEC /* video-without-audio.mp4 */; };
+ CDCFA7AA1E45183200C2433D /* SampleMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDCFA7A91E45122F00C2433D /* SampleMap.cpp */; };
CDE195B51CFE0B880053D256 /* FullscreenTopContentInset.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = CDE195B21CFE0ADE0053D256 /* FullscreenTopContentInset.html */; };
CE06DF9B1E1851F200E570C9 /* SecurityOrigin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CE06DF9A1E1851F200E570C9 /* SecurityOrigin.cpp */; };
CE14F1A4181873B0001C2705 /* WillPerformClientRedirectToURLCrash.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = CE14F1A2181873B0001C2705 /* WillPerformClientRedirectToURLCrash.html */; };
@@ -1328,6 +1329,7 @@
CDC8E48A1BC5C96200594FEC /* video-with-audio.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = "video-with-audio.mp4"; sourceTree = "<group>"; };
CDC8E48B1BC5C96200594FEC /* video-without-audio.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "video-without-audio.html"; sourceTree = "<group>"; };
CDC8E48C1BC5C96200594FEC /* video-without-audio.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = "video-without-audio.mp4"; sourceTree = "<group>"; };
+ CDCFA7A91E45122F00C2433D /* SampleMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SampleMap.cpp; sourceTree = "<group>"; };
CDE195B21CFE0ADE0053D256 /* FullscreenTopContentInset.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = FullscreenTopContentInset.html; sourceTree = "<group>"; };
CDE195B31CFE0ADE0053D256 /* FullscreenTopContentInset.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FullscreenTopContentInset.mm; sourceTree = "<group>"; };
CE06DF9A1E1851F200E570C9 /* SecurityOrigin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecurityOrigin.cpp; sourceTree = "<group>"; };
@@ -1626,6 +1628,7 @@
83B88A331C80056D00BB2418 /* HTMLParserIdioms.cpp */,
14464012167A8305000BD218 /* LayoutUnit.cpp */,
CD225C071C45A69200140761 /* ParsedContentRange.cpp */,
+ CDCFA7A91E45122F00C2433D /* SampleMap.cpp */,
CE06DF9A1E1851F200E570C9 /* SecurityOrigin.cpp */,
41973B5C1AF22875006C7B36 /* SharedBuffer.cpp */,
A17991891E1CA24100A505ED /* SharedBufferTest.cpp */,
@@ -2754,6 +2757,7 @@
7CCE7F191A411AE600447C4C /* WebArchive.cpp in Sources */,
2D4CF8BD1D8360CC0001CE8D /* WKThumbnailView.mm in Sources */,
7C83E04C1D0A641800FEBCF3 /* WebCoreNSURLSession.mm in Sources */,
+ CDCFA7AA1E45183200C2433D /* SampleMap.cpp in Sources */,
7CCE7F1A1A411AE600447C4C /* WebCoreStatisticsWithNoWebProcess.cpp in Sources */,
7CCE7EAB1A411A2400447C4C /* WebKitAgnosticTest.mm in Sources */,
51714EB81CF8CA17004723C4 /* WebProcessKillIDBCleanup.mm in Sources */,
Modified: trunk/Tools/TestWebKitAPI/Tests/WTF/MediaTime.cpp (211745 => 211746)
--- trunk/Tools/TestWebKitAPI/Tests/WTF/MediaTime.cpp 2017-02-06 20:49:25 UTC (rev 211745)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/MediaTime.cpp 2017-02-06 21:49:24 UTC (rev 211746)
@@ -85,6 +85,8 @@
EXPECT_EQ(MediaTime(1, 1) != MediaTime(2, 1), true);
EXPECT_EQ(MediaTime(2, 1) == MediaTime(2, 1), true);
EXPECT_EQ(MediaTime(2, 1) == MediaTime(4, 2), true);
+ EXPECT_TRUE((bool)MediaTime(1, 1));
+ EXPECT_TRUE(!MediaTime(0, 1));
// Addition Operators
EXPECT_EQ(MediaTime::positiveInfiniteTime() + MediaTime::positiveInfiniteTime(), MediaTime::positiveInfiniteTime());
@@ -158,8 +160,6 @@
EXPECT_EQ(abs(MediaTime::invalidTime()), MediaTime::invalidTime());
EXPECT_EQ(abs(MediaTime(1, 1)), MediaTime(1, 1));
EXPECT_EQ(abs(MediaTime(-1, 1)), MediaTime(1, 1));
- EXPECT_EQ(abs(MediaTime(-1, -1)), MediaTime(-1, -1));
- EXPECT_EQ(abs(MediaTime(1, -1)), MediaTime(-1, -1));
// Floating Point Functions
EXPECT_EQ(MediaTime::createWithFloat(1.0f), MediaTime(1, 1));
@@ -200,14 +200,14 @@
// Overflow Behavior
EXPECT_EQ(MediaTime::createWithFloat(pow(2.0f, 64.0f)), MediaTime::positiveInfiniteTime());
EXPECT_EQ(MediaTime::createWithFloat(-pow(2.0f, 64.0f)), MediaTime::negativeInfiniteTime());
- EXPECT_EQ(MediaTime::createWithFloat(pow(2.0f, 63.0f), 2).timeScale(), 1);
- EXPECT_EQ(MediaTime::createWithFloat(pow(2.0f, 63.0f), 3).timeScale(), 1);
+ EXPECT_EQ(MediaTime::createWithFloat(pow(2.0f, 63.0f), 2).timeScale(), 1U);
+ EXPECT_EQ(MediaTime::createWithFloat(pow(2.0f, 63.0f), 3).timeScale(), 1U);
EXPECT_EQ(MediaTime::createWithDouble(pow(2.0, 64.0)), MediaTime::positiveInfiniteTime());
EXPECT_EQ(MediaTime::createWithDouble(-pow(2.0, 64.0)), MediaTime::negativeInfiniteTime());
- EXPECT_EQ(MediaTime::createWithDouble(pow(2.0, 63.0), 2).timeScale(), 1);
- EXPECT_EQ(MediaTime::createWithDouble(pow(2.0, 63.0), 3).timeScale(), 1);
- EXPECT_EQ((MediaTime(numeric_limits<int64_t>::max(), 2) + MediaTime(numeric_limits<int64_t>::max(), 2)).timeScale(), 1);
- EXPECT_EQ((MediaTime(numeric_limits<int64_t>::min(), 2) - MediaTime(numeric_limits<int64_t>::max(), 2)).timeScale(), 1);
+ EXPECT_EQ(MediaTime::createWithDouble(pow(2.0, 63.0), 2).timeScale(), 1U);
+ EXPECT_EQ(MediaTime::createWithDouble(pow(2.0, 63.0), 3).timeScale(), 1U);
+ EXPECT_EQ((MediaTime(numeric_limits<int64_t>::max(), 2) + MediaTime(numeric_limits<int64_t>::max(), 2)).timeScale(), 1U);
+ EXPECT_EQ((MediaTime(numeric_limits<int64_t>::min(), 2) - MediaTime(numeric_limits<int64_t>::max(), 2)).timeScale(), 1U);
EXPECT_EQ(MediaTime(numeric_limits<int64_t>::max(), 1) + MediaTime(numeric_limits<int64_t>::max(), 1), MediaTime::positiveInfiniteTime());
EXPECT_EQ(MediaTime(numeric_limits<int64_t>::min(), 1) + MediaTime(numeric_limits<int64_t>::min(), 1), MediaTime::negativeInfiniteTime());
EXPECT_EQ(MediaTime(numeric_limits<int64_t>::min(), 1) - MediaTime(numeric_limits<int64_t>::max(), 1), MediaTime::negativeInfiniteTime());
Added: trunk/Tools/TestWebKitAPI/Tests/WebCore/SampleMap.cpp (0 => 211746)
--- trunk/Tools/TestWebKitAPI/Tests/WebCore/SampleMap.cpp (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/SampleMap.cpp 2017-02-06 21:49:24 UTC (rev 211746)
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(MEDIA_SOURCE)
+
+#include "Test.h"
+#include <WebCore/MediaSample.h>
+#include <WebCore/SampleMap.h>
+
+namespace WTF {
+inline std::ostream& operator<<(std::ostream& os, const MediaTime& time)
+{
+ if (time.hasDoubleValue())
+ os << "{ " << time.toDouble() << " }";
+ else
+ os << "{ " << time.timeValue() << " / " << time.timeScale() << ", " << time.toDouble() << " }";
+ return os;
+}
+}
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+class TestSample : public MediaSample {
+public:
+ static Ref<TestSample> create(const MediaTime& presentationTime, const MediaTime& decodeTime, const MediaTime& duration, SampleFlags flags)
+ {
+ return adoptRef(*new TestSample(presentationTime, decodeTime, duration, flags));
+ }
+
+ MediaTime presentationTime() const final { return m_presentationTime; }
+ MediaTime decodeTime() const final { return m_decodeTime; }
+ MediaTime duration() const final { return m_duration; }
+ AtomicString trackID() const final { return m_trackID; }
+ void setTrackID(const String& trackID) final { m_trackID = trackID; }
+ size_t sizeInBytes() const final { return m_sizeInBytes; }
+ FloatSize presentationSize() const final { return m_presentationSize; }
+ void offsetTimestampsBy(const MediaTime& offset) final { m_presentationTime += offset; m_decodeTime += offset; }
+ void setTimestamps(const MediaTime& presentationTime, const MediaTime& decodeTime) final {
+ m_presentationTime = presentationTime;
+ m_decodeTime = decodeTime;
+ };
+ bool isDivisable() const final { return false; }
+ std::pair<RefPtr<MediaSample>, RefPtr<MediaSample>> divide(const MediaTime& presentationTime) final { return { }; }
+ Ref<MediaSample> createNonDisplayingCopy() const final {
+ return create(m_presentationTime, m_decodeTime, m_duration, static_cast<SampleFlags>(m_flags | IsNonDisplaying));
+ }
+ SampleFlags flags() const final { return m_flags; }
+ PlatformSample platformSample() final { return { PlatformSample::None, {nullptr}}; }
+ void dump(PrintStream&) const final { }
+
+private:
+ TestSample(const MediaTime& presentationTime, const MediaTime& decodeTime, const MediaTime& duration, SampleFlags flags)
+ : m_presentationTime(presentationTime)
+ , m_decodeTime(decodeTime)
+ , m_duration(duration)
+ , m_flags(flags)
+ {
+ }
+
+ MediaTime m_presentationTime;
+ MediaTime m_decodeTime;
+ MediaTime m_duration;
+ FloatSize m_presentationSize;
+ AtomicString m_trackID;
+ size_t m_sizeInBytes { 0 };
+ SampleFlags m_flags { None };
+};
+
+class SampleMapTest : public testing::Test {
+public:
+ void SetUp() final {
+ map.addSample(TestSample::create(MediaTime(0, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::IsSync));
+ map.addSample(TestSample::create(MediaTime(1, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ map.addSample(TestSample::create(MediaTime(2, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ map.addSample(TestSample::create(MediaTime(3, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ map.addSample(TestSample::create(MediaTime(4, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ map.addSample(TestSample::create(MediaTime(5, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::IsSync));
+ map.addSample(TestSample::create(MediaTime(6, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ map.addSample(TestSample::create(MediaTime(7, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ map.addSample(TestSample::create(MediaTime(8, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ map.addSample(TestSample::create(MediaTime(9, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ // Gap at MediaTime(10, 1) -> MediaTime(11, 1);
+ map.addSample(TestSample::create(MediaTime(11, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::IsSync));
+ map.addSample(TestSample::create(MediaTime(12, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ map.addSample(TestSample::create(MediaTime(13, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ map.addSample(TestSample::create(MediaTime(14, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ map.addSample(TestSample::create(MediaTime(15, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::IsSync));
+ map.addSample(TestSample::create(MediaTime(16, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ map.addSample(TestSample::create(MediaTime(17, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ map.addSample(TestSample::create(MediaTime(18, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ map.addSample(TestSample::create(MediaTime(19, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ }
+
+ SampleMap map;
+};
+
+TEST_F(SampleMapTest, findSampleWithPresentationTime)
+{
+ auto& presentationMap = map.presentationOrder();
+ EXPECT_EQ(MediaTime(0, 1), presentationMap.findSampleWithPresentationTime(MediaTime(0, 1))->second->presentationTime());
+ EXPECT_EQ(MediaTime(19, 1), presentationMap.findSampleWithPresentationTime(MediaTime(19, 1))->second->presentationTime());
+ EXPECT_TRUE(presentationMap.end() == presentationMap.findSampleWithPresentationTime(MediaTime(-1, 1)));
+ EXPECT_TRUE(presentationMap.end() == presentationMap.findSampleWithPresentationTime(MediaTime(10, 1)));
+ EXPECT_TRUE(presentationMap.end() == presentationMap.findSampleWithPresentationTime(MediaTime(20, 1)));
+ EXPECT_TRUE(presentationMap.end() == presentationMap.findSampleWithPresentationTime(MediaTime(1, 2)));
+}
+
+TEST_F(SampleMapTest, findSampleContainingPresentationTime)
+{
+ auto& presentationMap = map.presentationOrder();
+ EXPECT_EQ(MediaTime(0, 1), presentationMap.findSampleContainingPresentationTime(MediaTime(0, 1))->second->presentationTime());
+ EXPECT_EQ(MediaTime(19, 1), presentationMap.findSampleContainingPresentationTime(MediaTime(19, 1))->second->presentationTime());
+ EXPECT_EQ(MediaTime(0, 1), presentationMap.findSampleContainingPresentationTime(MediaTime(1, 2))->second->presentationTime());
+ EXPECT_TRUE(presentationMap.end() == presentationMap.findSampleContainingPresentationTime(MediaTime(-1, 1)));
+ EXPECT_TRUE(presentationMap.end() == presentationMap.findSampleContainingPresentationTime(MediaTime(10, 1)));
+ EXPECT_TRUE(presentationMap.end() == presentationMap.findSampleContainingPresentationTime(MediaTime(20, 1)));
+}
+
+TEST_F(SampleMapTest, findSampleStartingOnOrAfterPresentationTime)
+{
+ auto& presentationMap = map.presentationOrder();
+ EXPECT_EQ(MediaTime(0, 1), presentationMap.findSampleStartingOnOrAfterPresentationTime(MediaTime(0, 1))->second->presentationTime());
+ EXPECT_EQ(MediaTime(19, 1), presentationMap.findSampleStartingOnOrAfterPresentationTime(MediaTime(19, 1))->second->presentationTime());
+ EXPECT_EQ(MediaTime(1, 1), presentationMap.findSampleStartingOnOrAfterPresentationTime(MediaTime(1, 2))->second->presentationTime());
+ EXPECT_EQ(MediaTime(0, 1), presentationMap.findSampleStartingOnOrAfterPresentationTime(MediaTime(-1, 1))->second->presentationTime());
+ EXPECT_EQ(MediaTime(11, 1), presentationMap.findSampleStartingOnOrAfterPresentationTime(MediaTime(10, 1))->second->presentationTime());
+ EXPECT_TRUE(presentationMap.end() == presentationMap.findSampleContainingPresentationTime(MediaTime(20, 1)));
+}
+
+TEST_F(SampleMapTest, findSamplesBetweenPresentationTimes)
+{
+ auto& presentationMap = map.presentationOrder();
+ auto iterator_range = presentationMap.findSamplesBetweenPresentationTimes(MediaTime(0, 1), MediaTime(1, 1));
+ EXPECT_EQ(MediaTime(0, 1), iterator_range.first->second->presentationTime());
+ EXPECT_EQ(MediaTime(1, 1), iterator_range.second->second->presentationTime());
+
+ iterator_range = presentationMap.findSamplesBetweenPresentationTimes(MediaTime(1, 2), MediaTime(3, 2));
+ EXPECT_EQ(MediaTime(1, 1), iterator_range.first->second->presentationTime());
+ EXPECT_EQ(MediaTime(2, 1), iterator_range.second->second->presentationTime());
+
+ iterator_range = presentationMap.findSamplesBetweenPresentationTimes(MediaTime(9, 1), MediaTime(21, 1));
+ EXPECT_EQ(MediaTime(9, 1), iterator_range.first->second->presentationTime());
+ EXPECT_TRUE(presentationMap.end() == iterator_range.second);
+
+ iterator_range = presentationMap.findSamplesBetweenPresentationTimes(MediaTime(-1, 1), MediaTime(0, 1));
+ EXPECT_TRUE(presentationMap.end() == iterator_range.first);
+ EXPECT_TRUE(presentationMap.end() == iterator_range.second);
+
+ iterator_range = presentationMap.findSamplesBetweenPresentationTimes(MediaTime(19, 2), MediaTime(10, 1));
+ EXPECT_TRUE(presentationMap.end() == iterator_range.first);
+ EXPECT_TRUE(presentationMap.end() == iterator_range.second);
+
+ iterator_range = presentationMap.findSamplesBetweenPresentationTimes(MediaTime(20, 1), MediaTime(21, 1));
+ EXPECT_TRUE(presentationMap.end() == iterator_range.first);
+ EXPECT_TRUE(presentationMap.end() == iterator_range.second);
+}
+
+TEST_F(SampleMapTest, findSamplesWithinPresentationRange)
+{
+ auto& presentationMap = map.presentationOrder();
+ auto iterator_range = presentationMap.findSamplesWithinPresentationRange(MediaTime(0, 1), MediaTime(1, 1));
+ EXPECT_EQ(MediaTime(1, 1), iterator_range.first->second->presentationTime());
+ EXPECT_EQ(MediaTime(2, 1), iterator_range.second->second->presentationTime());
+
+ iterator_range = presentationMap.findSamplesWithinPresentationRange(MediaTime(1, 2), MediaTime(3, 2));
+ EXPECT_EQ(MediaTime(1, 1), iterator_range.first->second->presentationTime());
+ EXPECT_EQ(MediaTime(2, 1), iterator_range.second->second->presentationTime());
+
+ iterator_range = presentationMap.findSamplesWithinPresentationRange(MediaTime(9, 1), MediaTime(21, 1));
+ EXPECT_EQ(MediaTime(11, 1), iterator_range.first->second->presentationTime());
+ EXPECT_TRUE(presentationMap.end() == iterator_range.second);
+
+ iterator_range = presentationMap.findSamplesWithinPresentationRange(MediaTime(-1, 1), MediaTime(0, 1));
+ EXPECT_EQ(MediaTime(0, 1), iterator_range.first->second->presentationTime());
+ EXPECT_EQ(MediaTime(1, 1), iterator_range.second->second->presentationTime());
+
+ iterator_range = presentationMap.findSamplesWithinPresentationRange(MediaTime(10, 1), MediaTime(21, 2));
+ EXPECT_TRUE(presentationMap.end() == iterator_range.first);
+ EXPECT_TRUE(presentationMap.end() == iterator_range.second);
+
+ iterator_range = presentationMap.findSamplesWithinPresentationRange(MediaTime(20, 1), MediaTime(21, 1));
+ EXPECT_TRUE(presentationMap.end() == iterator_range.first);
+ EXPECT_TRUE(presentationMap.end() == iterator_range.second);
+}
+
+TEST_F(SampleMapTest, reverseFindSampleBeforePresentationTime)
+{
+ auto& presentationMap = map.presentationOrder();
+ EXPECT_EQ(MediaTime(0, 1), presentationMap.reverseFindSampleBeforePresentationTime(MediaTime(0, 1))->second->presentationTime());
+ EXPECT_EQ(MediaTime(9, 1), presentationMap.reverseFindSampleBeforePresentationTime(MediaTime(10, 1))->second->presentationTime());
+ EXPECT_EQ(MediaTime(19, 1), presentationMap.reverseFindSampleBeforePresentationTime(MediaTime(19, 1))->second->presentationTime());
+ EXPECT_EQ(MediaTime(19, 1), presentationMap.reverseFindSampleBeforePresentationTime(MediaTime(21, 1))->second->presentationTime());
+ EXPECT_TRUE(presentationMap.rend() == presentationMap.reverseFindSampleBeforePresentationTime(MediaTime(-1, 1)));
+}
+
+}
+
+#endif // ENABLE(MEDIA_SOURCE)