Import Cobalt 21.master.0.260628
diff --git a/src/starboard/CHANGELOG.md b/src/starboard/CHANGELOG.md
index b4e9fe3..7217425 100644
--- a/src/starboard/CHANGELOG.md
+++ b/src/starboard/CHANGELOG.md
@@ -6,7 +6,7 @@
this file describes the changes made to the Starboard interface since the
version previous to it.
-**NOTE: Starboard versions 3 and below are no longer supported.**
+**NOTE: Starboard versions 9 and below are no longer supported.**
## Experimental Version
@@ -353,289 +353,3 @@
Please see [contrib/README.md](contrib/README.md) for description of
expectations for contents in this directory.
-
-## Version 9
-
-### Add string label to `SbMicrophoneInfo`.
-
-This should indicate the friendly name of the microphone type.
-
-### Introduce additional SbSocketError enum values.
-
-Instead of the single generic kSbSocketErrorFailed to indicate socket errors,
-the enum kSbSocketErrorConnectionReset has been introduced corresponding to
-various dropped TCP connection errors. This is particularly useful in
-identifying socket errors that can be retried.
-
-### Add new keycode kSbKeyInstantReplay
-
-Identical to OCAP's `VK_INSTANT_REPLAY`
-
-## Version 8
-
-### Add `SbPlayerCreateWithUrl()`, `SbPlayerSetDrmSystem()`, `SbPlayerOutputModeSupportedWithUrl()`
-
-For platform media players that rely on using a URL (like an m3u playlist URL)
-for playback, add `SbPlayerCreateWithUrl()` which takes in a URL, no video or
-audio configs, and no DRM system. Allow the DRM system to be set on a running
-SbPlayer exactly once for SbPlayers created with a URL. Also, since URL players
-will not expose codec information, use a custom
-`SbPlayerOutputModeSupportedWithUrl()` to query player output mode support.
-
-### Add `kSbEventTypeWindowSizeChanged`
-
-An event indicating that an `SbWindow`'s size has changed. The event data is
-`SbEventWindowSizeChangedData`, containing a `SbWindow` and `SbWindowSize`.
-
-### Add `SbWindowShowOnScreenKeyboard()`, `SbWindowHideOnScreenKeyboard()`, `SbWindowFocusOnScreenKeyboard()`, `SbWindowBlurOnScreenKeyboard()`, `SbWindowIsOnScreenKeyboardShown()`, `SbWindowSetOnScreenKeyboardKeepFocus()`
-
-These methods show, hide, focus, and blur a native on screen keyboard,
-determine if the on screen keyboard is shown, and set whether focus is kept to
-the on screen keyboard. The on screen keyboard also handles
-`kSbInputEventTypeInput`, which use a new field `input_text` of `SbInputData`.
-
-## Version 7
-
-### `SbDecodeTargetInfoPlane` can specify color plane information
-
-Previously: Planes of type `kSbDecodeTargetFormat2PlaneYUVNV12`
-were assumed to have the luma mapped to the alpha channel (`GL_ALPHA`)
-and the chroma mapped to blue and alpha (`GL_LUMINANCE_ALPHA`). However,
-some graphics systems require that luma is on `GL_RED_EXT` and the chroma
-is on `GL_RG_EXT`.
-
-## Version 6
-
-### Named `SbStorageRecord`s
-
-This extends the `SbStorage` interface with the ability to open named
-`SbStorageRecord`s. Calling `SbStorageOpenRecord` and `SbStorageDeleteRecord`
-with a `NULL` `name` parameter provides access to the old "default" record.
-
-### Introduce pointer (mouse) input support
-
-This extends the `SbInput` interface with some enum values and data members to
-allow mouse, wheel, and more generic pointer input.
-
-### Flexible audio specific config
-
-`SbMediaAudioHeader::audio_specific_config` will be a pointer instead of an
-array.
-
-### Time Zone API Cleanup
-
-Removes `SbTimeZoneGetDstName()` -- The Daylight Savings Time version of the
-time zone.
-
-Changes `SbTimeZoneGetName()` to be more flexible in what it is allowed to
-return.
-
-### `SbDecodeTargetNumberOfPlanesForFormat`
-
-Adds the convenience inline function, SbDecodeTargetNumberOfPlanesForFormat() to
-`starboard/decode_target.h`.
-
-### Preload Support
-
-Adds the `kSbEventTypePreload` event, and modifies the application state machine
-to utilize it.
-
-### Platform Error Cleanup
-
-Removes `SbSystemPlatformErrorType` values specific to user status.
-
-### `SbDecodeTarget` support for the UYVY (i.e. YUV 422) format
-
-Add support for UYVY decode targets (e.g. YUV 422) via the
-`kSbDecodeTargetFormat1PlaneUYVY` enum.
-
-### Add More Remote Keys
-
-This adds SbKey codes for:
-
- * Color keys
- * Closed Caption key
- * Application launch key
- * Channel Up/Down keys
- * Info key
- * Guide key
- * Last/Previous Channel key
- * Media audio track select key
-
-### `kSbEventTypeLowMemory`
-
-Adds a new event type -- `kSbEventTypeLowMemory` -- to allow a platform to
-signal that the application may soon be terminated due to low memory
-availability.
-
-### Interface change to `SbPlayerWriteSample()`
-`const` is added to `sample_buffers` and `sample_buffer_sizes` parameters.
-
-### Support key status change
-Add `key_statuses_changed_callback` parameter to `SbDrmCreateSystem()` to
-support MediaKeySession::keyStatuses and MediaKeySession::onkeystatuseschange.
-
-### Changes thumbstick direction
-
-Change the meaning of negative values for thumbstick position from bottom
-right to upper left.
-
-## Version 5
-
-### Add Speech Recognizer API
-Introduce `starboard/speech_recognizer.h`.
-This newly-introduced `starboard/speech_recognizer.h` adds the on-device speech
-recognizer feature.
-
-### Added new system property to allow platform-specific user agent suffixes
-Adds `kSbSystemPropertyUserAgentAuxField` to the `SbSystemPropertyId` enum to
-allow platform-specific User-Agent suffix.
-
-### Remove unused enums from `starboard/input.h`
-The following unused enum values are removed from `starboard/input.h`:
- * `kSbInputDeviceTypeMicrophone`
- * `kSbInputDeviceTypeSpeechCommand`
- * `kSbInputEventTypeAudio`
- * `kSbInputEventTypeCommand`
- * `kSbInputEventTypeGrab`
- * `kSbInputEventTypeUngrab`
-
-## Version 4
-
-### Decode-to-Texture Player Output Mode
-Feature introducing support for decode-to-texture player output mode, and
-runtime player output mode selection and detection.
-In `starboard/configuration.h`,
- * `SB_IS_PLAYER_PUNCHED_OUT`, `SB_IS_PLAYER_PRODUCING_TEXTURE`, and
- `SB_IS_PLAYER_COMPOSITED` now no longer need to be defined (and should not
- be defined) by platforms. Instead, these capabilities are detected at
- runtime via `SbPlayerOutputModeSupported()`.
-
-In `starboard/player.h`,
- * The enum `SbPlayerOutputMode` is introduced.
- * `SbPlayerOutputModeSupported()` is introduced to let applications query
- for player output mode support.
- * `SbPlayerCreate()` now takes an additional parameter that specifies the
- desired output mode.
- * The punch out specific function `SbPlayerSetBounds()` must now be
- defined on all platforms, even if they don't support punch out (in which
- case they can implement a stub).
- * The function `SbPlayerGetCompositionHandle()` is removed.
- * The function `SbPlayerGetTextureId()` is replaced by the new
- `SbPlayerGetCurrentFrame()`, which returns a `SbDecodeTarget`.
-
-In `starboard/decode_target.h`,
- * All get methods (`SbDecodeTargetGetPlane()` and `SbDecodeTargetGetFormat()`,
- `SbDecodeTargetIsOpaque()`) are now replaced with `SbDecodeTargetGetInfo()`.
- * The `SbDecodeTargetInfo` structure is introduced and is the return value
- type of `SbDecodeTargetGetInfo()`.
- * `SbDecdodeTargetCreate()` is now responsible for creating all its internal
- planes, and so its `planes` parameter is replaced by `width` and
- `height` parameters.
- * The GLES2 version of `SbDecdodeTargetCreate()` has its EGL types
- (`EGLDisplay`, `EGLContext`) replaced by `void*` types, so that
- `decode_target.h` can avoid #including EGL/GLES2 headers.
- * `SbDecodeTargetDestroy()` is renamed to `SbDecodeTargetRelease()`.
-
-In `starboard/player.h`, `starboard/image.h` and `starboard/decode_target.h`,
- * Replace `SbDecodeTargetProvider` with
- `SbDecodeTargetGraphicsContextProvider`.
- * Instead of restricting Starboard implementations to only be able to run
- `SbDecodeTarget` creation and destruction code on the application's
- renderer's thread with the application's renderer's `EGLContext` current,
- Starboard implementations can now run arbitrary code on the application's
- renderer's thread with its `EGLContext` current.
- * Remove `SbDecodeTargetCreate()`, `SbDecodeTarget` creation is now an
- implementation detail to be dealt with in other Starboard API functions
- that create `SbDecodeTargets`, like `SbImageDecode()` or `SbPlayerCreate()`.
-
-### Playback Rate
-Support for setting the playback rate on an SbPlayer. This allows for control
-of the playback speed of video at runtime.
-
-### Floating Point Input Vector
-Change `input.h`'s `SbInputVector` structure to contain float members instead of
-ints.
-
-### Delete SbUserApplicationTokenResults
-Deleted the vestigal struct `SbUserApplicationTokenResults` from `user.h`.
-
-### Storage Options for Encoded Audio/Video Data
-Enables the SbPlayer implementation to provide instructions to its user on
-how to store audio/video data. Encoded audio/video data is cached once being
-demuxed and may occupy a significant amount of memory. Enabling this feature
-allows the SbPlayer implementation to have better control on where encoded
-audio/video data is stored.
-
-### Unified implementation of `SbMediaCanPlayMimeAndKeySystem()`
-Use a unified implementation of `SbMediaCanPlayMimeAndKeySystem()` based on
-`SbMediaIsSupported()`, `SbMediaIsAudioSupported()`, and
-`SbMediaIsVideoSupported()`.
-
-### Introduce `ticket` parameter to `SbDrmGenerateSessionUpdateRequest()`
-Introduce `ticket` parameter to `SbDrmGenerateSessionUpdateRequest()`
-and `SbDrmSessionUpdateRequestFunc` to allow distinguishing between callbacks
-from multiple concurrent calls.
-
-### Introduce `SbSocketGetInterfaceAddress()`
-`SbSocketGetInterfaceAddress()` is introduced to let applications find out
-which source IP address and the associated netmask will be used to connect to
-the destination. This is very important for multi-homed devices, and for
-certain conditions in IPv6.
-
-### Introduce `starboard/cryptography.h`
-In newly-introduced `starboard/cryptography.h`,
- * Optional support for accelerated cryptography, which can, in
- particular, be used for accelerating SSL.
-
-### Introduce z-index parameter to `SbPlayerSetBounds()`
-Allow `SbPlayerSetBounds` to use an extra parameter to indicate the z-index of
-the video so multiple overlapping videos can be rendered.
-
-### Media source buffer settings removed from `configuration.h`
-Media source buffer settings in Starboard.
-
-### Introduce `starboard/accessibility.h`
-In particular, the functions `SbAccessibilityGetDisplaySettings()` and
-`SbAccessibilityGetTextToSpeechSettings()` have now been introduced.
-
-Additionally, a new Starboard event, `kSbEventTypeAccessiblitySettingsChanged`,
-has been defined in `starboard/event.h`.
-
-### HDR decode support
-In `starboard/media.h`, `SbMediaColorMetadata` is now defined and it contains
-HDR metadata. The field `SbMediaColorMetadata color_metadata` is now added to
-`SbMediaVideoSampleInfo`.
-
-### Add `kSbSystemDeviceTypeAndroidTV` to `starboard/system.h`
-A new device type, `kSbSystemDeviceTypeAndroidTV`, is added to
-starboard/system.h.
-
-### Deprecate `SbSpeechSynthesisSetLanguage()`
-SbSpeechSynthesisSetLanguage() has been deprecated.
-
-### Request State Change Support
-Added `SbSystemRequestPause()`, `SbSystemRequestUnpause()`,
-`SbSystemRequestSuspend()`.
-
-`SbSystemRequestSuspend()` in particular can be hooked into a platform's "hide"
-or "minimize" window functionality.
-
-### Font Directory Path Support
-Added `kSbSystemPathFontDirectory` and `kSbSystemPathFontConfigurationDirectory`
-which can be optionally specified for platforms that want to provide system
-fonts to Starboard applications. The font and font configuration formats
-supported are application-specific.
-
-### Add `SB_NORETURN` to `starboard/configuration.h`.
-Added attribute macro `SB_NORETURN` to allow functions to be marked as noreturn.
-
-### Mark `SbSystemBreakIntoDebugger` `SB_NORETURN`.
-Add `SB_NORETURN` to declaration of `SbSystemBreakIntoDebugger`, to allow it to
-be used in a manner similar to `abort`.
-
-### Introduce `SbAudioSinkGetMinBufferSizeInFrames()`
-
-Introduce `SbAudioSinkGetMinBufferSizeInFrames()` to `starboard/audio_sink.h`
-which communicates to the platform how many audio frames are required to ensure
-that audio sink can keep playing without underflow.
diff --git a/src/starboard/android/apk/app/CMakeLists.txt b/src/starboard/android/apk/app/CMakeLists.txt
index 3e0fd3c..539ef3d 100644
--- a/src/starboard/android/apk/app/CMakeLists.txt
+++ b/src/starboard/android/apk/app/CMakeLists.txt
@@ -17,7 +17,7 @@
# be started:
# Run -> Edit Configurations -> "app" -> Debugger -> Debug Type = Dual
-cmake_minimum_required(VERSION 3.4.1)
+cmake_minimum_required(VERSION 3.10.2)
# Map Android ABI to Cobalt architecture
if(ANDROID_ABI STREQUAL x86)
@@ -92,3 +92,25 @@
# Add a dependency to run the external cobalt build as a side effect of
# building the phony native library.
add_dependencies(native external_cobalt_build)
+
+if (ENABLE_VULKAN)
+ # Add angle shared libraries.
+ list(APPEND angle_libs EGL_angle GLESv1_CM_angle
+ GLESv2_angle feature_support_angle c++_shared)
+
+ # Copy each library into APK.
+ foreach(angle_lib IN LISTS angle_libs)
+ add_dependencies(native ${angle_lib}_lib)
+ add_library(${angle_lib} SHARED IMPORTED)
+ set_target_properties(${angle_lib} PROPERTIES
+ IMPORTED_LOCATION
+ ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib${angle_lib}.so
+ )
+ add_custom_target(${angle_lib}_lib
+ DEPENDS external_cobalt_build
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${COBALT_PRODUCT_DIR}/lib/lib${angle_lib}.so
+ ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib${angle_lib}.so
+ )
+ endforeach()
+endif()
\ No newline at end of file
diff --git a/src/starboard/android/apk/app/build.gradle b/src/starboard/android/apk/app/build.gradle
index 231fbb9..07ab31a 100644
--- a/src/starboard/android/apk/app/build.gradle
+++ b/src/starboard/android/apk/app/build.gradle
@@ -17,6 +17,11 @@
final DEFAULT_COBALT_TARGET = 'cobalt'
final String[] SUPPORTED_ABIS = [ 'x86', 'armeabi-v7a', 'arm64-v8a' ]
+// Parse the NDK_VERSION and CMAKE_VERSION defined in sdk_utils.py
+final SDK_UTILS = project.rootProject.file('../shared/sdk_utils.py')
+final NDK_VERSION = SDK_UTILS.find { it.startsWith('_NDK_VERSION =') }.split("'")[1]
+final CMAKE_VERSION = SDK_UTILS.find { it.startsWith('_CMAKE_VERSION =') }.split("'")[1]
+
ext {
// Provide defaults if these properties aren't specified on the command line.
buildAbi = project.hasProperty('cobaltBuildAbi') ? cobaltBuildAbi : SUPPORTED_ABIS
@@ -25,6 +30,8 @@
project.hasProperty('cobaltProductDir') ? new File(cobaltProductDir).canonicalPath : ''
cobaltContentDir =
project.hasProperty('cobaltContentDir') ? new File(cobaltContentDir).canonicalPath : ''
+ enableVulkan =
+ project.hasProperty('enableVulkan') ? enableVulkan : 0
buildIdFile = rootProject.file('build.id')
buildId = buildIdFile.exists() ? buildIdFile.text.trim() : '0'
@@ -35,6 +42,7 @@
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
+ ndkVersion NDK_VERSION
signingConfigs {
// A signing config that matches what is implicitly used for the "debug" build type.
@@ -58,6 +66,7 @@
arguments "-DCOBALT_PRODUCT_DIR=${cobaltProductDir}"
arguments "-DCOBALT_CONTENT_DIR=${cobaltContentDir}"
arguments "-DCOBALT_PLATFORM_DEPLOY=${project.hasProperty('cobaltDeployApk')}"
+ arguments "-DENABLE_VULKAN=${enableVulkan}"
}
}
}
@@ -129,6 +138,7 @@
}
externalNativeBuild {
cmake {
+ version CMAKE_VERSION
path 'CMakeLists.txt'
// Move the staging directory to be a sibling of the build directory, which we moved
// in the top-level build.gradle to be in a common top-level 'build' directory. Get
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecBridge.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecBridge.java
index ed92953..f487c65 100644
--- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecBridge.java
+++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecBridge.java
@@ -467,10 +467,12 @@
boolean findHDRDecoder = android.os.Build.VERSION.SDK_INT >= 24 && colorInfo != null;
// On first pass, try to find a decoder with HDR if the color info is non-null.
MediaCodecUtil.FindVideoDecoderResult findVideoDecoderResult =
- MediaCodecUtil.findVideoDecoder(mime, isSecure, 0, 0, 0, 0, findHDRDecoder);
+ MediaCodecUtil.findVideoDecoder(
+ mime, isSecure, 0, 0, 0, 0, findHDRDecoder, requireSoftwareCodec);
if (findVideoDecoderResult.name.equals("") && findHDRDecoder) {
// On second pass, forget HDR.
- findVideoDecoderResult = MediaCodecUtil.findVideoDecoder(mime, isSecure, 0, 0, 0, 0, false);
+ findVideoDecoderResult =
+ MediaCodecUtil.findVideoDecoder(mime, isSecure, 0, 0, 0, 0, false, requireSoftwareCodec);
}
try {
String decoderName = findVideoDecoderResult.name;
@@ -496,7 +498,7 @@
boolean shouldConfigureHdr =
android.os.Build.VERSION.SDK_INT >= 24
&& colorInfo != null
- && MediaCodecUtil.isHdrCapableVp9Decoder(findVideoDecoderResult);
+ && MediaCodecUtil.isHdrCapableVideoDecoder(mime, findVideoDecoderResult);
if (shouldConfigureHdr) {
Log.d(TAG, "Setting HDR info.");
mediaFormat.setInteger(MediaFormat.KEY_COLOR_TRANSFER, colorInfo.colorTransfer);
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecUtil.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecUtil.java
index b7fdad8..de35fb4 100644
--- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecUtil.java
+++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/MediaCodecUtil.java
@@ -38,12 +38,16 @@
// A high priority white list of brands/model that should always attempt to
// play vp9.
private static final Map<String, Set<String>> vp9WhiteList = new HashMap<>();
+ // A white list of software codec names that can be used.
+ private static final Set<String> softwareCodecWhiteList = new HashSet<>();
+
// Whether we should report vp9 codecs as supported or not. Will be set
// based on whether vp9WhiteList contains our brand/model. If this is set
// to true, then codecBlackList will be ignored.
private static boolean isVp9WhiteListed;
private static final String SECURE_DECODER_SUFFIX = ".secure";
private static final String VP9_MIME_TYPE = "video/x-vnd.on2.vp9";
+ private static final String AV1_MIME_TYPE = "video/av01";
/**
* A simple "struct" to bundle up the results from findVideoDecoder, as its clients may require
@@ -369,6 +373,8 @@
isVp9WhiteListed =
vp9WhiteList.containsKey(Build.BRAND)
&& vp9WhiteList.get(Build.BRAND).contains(Build.MODEL);
+
+ softwareCodecWhiteList.add("OMX.google.h264.decoder");
}
private MediaCodecUtil() {}
@@ -390,9 +396,10 @@
int fps,
boolean mustSupportHdr) {
FindVideoDecoderResult findVideoDecoderResult =
- findVideoDecoder(mimeType, secure, frameWidth, frameHeight, bitrate, fps, mustSupportHdr);
+ findVideoDecoder(
+ mimeType, secure, frameWidth, frameHeight, bitrate, fps, mustSupportHdr, false);
return !findVideoDecoderResult.name.equals("")
- && (!mustSupportHdr || isHdrCapableVp9Decoder(findVideoDecoderResult));
+ && (!mustSupportHdr || isHdrCapableVideoDecoder(mimeType, findVideoDecoderResult));
}
/**
@@ -405,23 +412,32 @@
return !findAudioDecoder(mimeType, bitrate).equals("");
}
- /** Determine whether the system has a decoder capable of playing HDR VP9. */
+ /**
+ * Determine whether the system has a decoder capable of playing HDR. Currently VP9 and AV1 are
+ * HDR supported codecs
+ */
@SuppressWarnings("unused")
@UsedByNative
- public static boolean hasHdrCapableVp9Decoder() {
+ public static boolean hasHdrCapableVideoDecoder(String mimeType) {
// VP9Profile* values were not added until API level 24. See
// https://developer.android.com/reference/android/media/MediaCodecInfo.CodecProfileLevel.html.
if (Build.VERSION.SDK_INT < 24) {
return false;
}
+ // AV1ProfileMain10HDR10 value was not added until API level 29. See
+ // https://developer.android.com/reference/android/media/MediaCodecInfo.CodecProfileLevel.html.
+ if (mimeType.equals(AV1_MIME_TYPE) && Build.VERSION.SDK_INT < 29) {
+ return false;
+ }
FindVideoDecoderResult findVideoDecoderResult =
- findVideoDecoder(VP9_MIME_TYPE, false, 0, 0, 0, 0, true);
- return isHdrCapableVp9Decoder(findVideoDecoderResult);
+ findVideoDecoder(mimeType, false, 0, 0, 0, 0, true, false);
+ return isHdrCapableVideoDecoder(mimeType, findVideoDecoderResult);
}
- /** Determine whether findVideoDecoderResult is capable of playing HDR VP9 */
- public static boolean isHdrCapableVp9Decoder(FindVideoDecoderResult findVideoDecoderResult) {
+ /** Determine whether findVideoDecoderResult is capable of playing HDR */
+ public static boolean isHdrCapableVideoDecoder(
+ String mimeType, FindVideoDecoderResult findVideoDecoderResult) {
CodecCapabilities codecCapabilities = findVideoDecoderResult.codecCapabilities;
if (codecCapabilities == null) {
return false;
@@ -431,9 +447,15 @@
return false;
}
for (CodecProfileLevel codecProfileLevel : codecProfileLevels) {
- if (codecProfileLevel.profile == CodecProfileLevel.VP9Profile2HDR
- || codecProfileLevel.profile == CodecProfileLevel.VP9Profile3HDR) {
- return true;
+ if (mimeType.equals(VP9_MIME_TYPE)) {
+ if (codecProfileLevel.profile == CodecProfileLevel.VP9Profile2HDR
+ || codecProfileLevel.profile == CodecProfileLevel.VP9Profile3HDR) {
+ return true;
+ }
+ } else if (mimeType.equals(AV1_MIME_TYPE)) {
+ if (codecProfileLevel.profile == CodecProfileLevel.AV1ProfileMain10HDR10) {
+ return true;
+ }
}
}
@@ -451,13 +473,15 @@
int frameHeight,
int bitrate,
int fps,
- boolean hdr) {
+ boolean hdr,
+ boolean requireSoftwareCodec) {
Log.v(
TAG,
String.format(
"Searching for video decoder with parameters "
- + "mimeType: %s, secure: %b, frameWidth: %d, frameHeight: %d, bitrate: %d, fps: %d",
- mimeType, secure, frameWidth, frameHeight, bitrate, fps));
+ + "mimeType: %s, secure: %b, frameWidth: %d, frameHeight: %d,"
+ + " bitrate: %d, fps: %d, hdr: %b, requireSoftwareCodec: %b",
+ mimeType, secure, frameWidth, frameHeight, bitrate, fps, hdr, requireSoftwareCodec));
Log.v(
TAG,
String.format(
@@ -477,8 +501,11 @@
if (!supportedType.equalsIgnoreCase(mimeType)) {
continue;
}
-
String name = info.getName();
+ if (requireSoftwareCodec && !softwareCodecWhiteList.contains(name)) {
+ Log.v(TAG, String.format("Rejecting %s, reason: require software codec", name));
+ continue;
+ }
if (!isVp9WhiteListed && codecBlackList.contains(name)) {
Log.v(TAG, String.format("Rejecting %s, reason: codec is black listed", name));
continue;
@@ -569,7 +596,8 @@
: name;
FindVideoDecoderResult findVideoDecoderResult =
new FindVideoDecoderResult(resultName, videoCapabilities, codecCapabilities);
- if (hdr && !isHdrCapableVp9Decoder(findVideoDecoderResult)) {
+ if (hdr && !isHdrCapableVideoDecoder(mimeType, findVideoDecoderResult)) {
+ Log.v(TAG, String.format("Rejecting %s, reason: codec does not support HDR", name));
continue;
}
Log.v(TAG, String.format("Found suitable decoder, %s", name));
diff --git a/src/starboard/android/apk/build.gradle b/src/starboard/android/apk/build.gradle
index 525c56b..c21ed86 100644
--- a/src/starboard/android/apk/build.gradle
+++ b/src/starboard/android/apk/build.gradle
@@ -20,7 +20,7 @@
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.5.3'
+ classpath 'com.android.tools.build:gradle:3.6.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
diff --git a/src/starboard/android/apk/cobalt-gradle.sh b/src/starboard/android/apk/cobalt-gradle.sh
index d135b4b..156c8f2 100755
--- a/src/starboard/android/apk/cobalt-gradle.sh
+++ b/src/starboard/android/apk/cobalt-gradle.sh
@@ -22,7 +22,6 @@
while [ "$1" ]; do
case "$1" in
--sdk) shift; ANDROID_HOME="$1" ;;
- --ndk) shift; ANDROID_NDK_HOME="$1" ;;
--cache) shift; mkdir -p "$1";
GRADLE_ARGS+=("--project-cache-dir" $(cd "$1"; pwd)) ;;
--reset) RESET_GRADLE=1 ;;
@@ -34,7 +33,7 @@
# Cleanup Gradle from previous builds. Used as part of the GYP step.
if [[ "${RESET_GRADLE}" ]]; then
- echo "Cleaning Gradle deamons and locks."
+ echo "Cleaning Gradle daemons and locks."
# If there are any lock files, kill any hung processes still waiting on them.
if compgen -G '/var/lock/cobalt-gradle.lock.*'; then
lsof -t /var/lock/cobalt-gradle.lock.* | xargs -rt kill
@@ -50,15 +49,22 @@
fi
export ANDROID_HOME
-export ANDROID_NDK_HOME
echo "ANDROID_HOME=${ANDROID_HOME}"
-echo "ANDROID_NDK_HOME=${ANDROID_NDK_HOME}"
-echo "TASK: ${GRADLE_ARGS[-1]}"
# Allow parallel gradle builds, as defined by a COBALT_GRADLE_BUILD_COUNT envvar
# or default to 1 if that's not set (so buildbot only runs 1 gradle at a time).
BUCKETS=${COBALT_GRADLE_BUILD_COUNT:-1}
+if [ "$BUCKETS"==1 ]; then
+ echo "Gradle daemon and parallel gradle disabled for Cobalt build"
+ GRADLE_ARGS+=(
+ "-Dorg.gradle.parallel=false"
+ "-Dorg.gradle.workers.max=1"
+ "-Dorg.gradle.daemon=false"
+ )
+fi
+
MD5=$(echo "${GRADLE_ARGS[@]}" | md5sum)
LOCKNUM=$(( ${BUCKETS} * 0x${MD5:0:6} / 0x1000000 ))
+echo "TASK: ${GRADLE_ARGS[-1]}"
flock /var/lock/cobalt-gradle.lock.${LOCKNUM} $(dirname "$0")/gradlew "${GRADLE_ARGS[@]}"
diff --git a/src/starboard/android/apk/gradle/wrapper/gradle-wrapper.jar b/src/starboard/android/apk/gradle/wrapper/gradle-wrapper.jar
index 13372ae..5c2d1cf 100644
--- a/src/starboard/android/apk/gradle/wrapper/gradle-wrapper.jar
+++ b/src/starboard/android/apk/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/src/starboard/android/apk/gradle/wrapper/gradle-wrapper.properties b/src/starboard/android/apk/gradle/wrapper/gradle-wrapper.properties
index cb820ac..0ebb310 100644
--- a/src/starboard/android/apk/gradle/wrapper/gradle-wrapper.properties
+++ b/src/starboard/android/apk/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,5 @@
-#Thu Jan 02 11:15:25 PST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
diff --git a/src/starboard/android/apk/gradlew b/src/starboard/android/apk/gradlew
index 9d82f78..b0d6d0a 100755
--- a/src/starboard/android/apk/gradlew
+++ b/src/starboard/android/apk/gradlew
@@ -1,4 +1,20 @@
-#!/usr/bin/env bash
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
##############################################################################
##
@@ -6,42 +22,6 @@
##
##############################################################################
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
-
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
-
-warn ( ) {
- echo "$*"
-}
-
-die ( ) {
- echo
- echo "$*"
- echo
- exit 1
-}
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-case "`uname`" in
- CYGWIN* )
- cygwin=true
- ;;
- Darwin* )
- darwin=true
- ;;
- MINGW* )
- msys=true
- ;;
-esac
-
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
@@ -60,6 +40,46 @@
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
@@ -85,7 +105,7 @@
fi
# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
@@ -150,11 +170,19 @@
esac
fi
-# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
-function splitJvmOpts() {
- JVM_OPTS=("$@")
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
}
-eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
-JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+APP_ARGS=$(save "$@")
-exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/src/starboard/android/apk/gradlew.bat b/src/starboard/android/apk/gradlew.bat
index aec9973..15e1ee3 100644
--- a/src/starboard/android/apk/gradlew.bat
+++ b/src/starboard/android/apk/gradlew.bat
@@ -1,3 +1,19 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem http://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@@ -8,14 +24,14 @@
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
-
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
@@ -46,10 +62,9 @@
goto fail
:init
-@rem Get command-line arguments, handling Windowz variants
+@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
-if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
@@ -60,11 +75,6 @@
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
-goto execute
-
-:4NT_args
-@rem Get arguments from the 4NT Shell from JP Software
-set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
diff --git a/src/starboard/android/arm/gyp_configuration.gypi b/src/starboard/android/arm/gyp_configuration.gypi
index d3302b1..4a8ef2d 100644
--- a/src/starboard/android/arm/gyp_configuration.gypi
+++ b/src/starboard/android/arm/gyp_configuration.gypi
@@ -14,7 +14,6 @@
{
'variables': {
- 'target_arch': 'arm',
'arm_version': 7,
'armv7': 1,
'arm_thumb': 0,
diff --git a/src/starboard/android/arm64/gyp_configuration.gypi b/src/starboard/android/arm64/gyp_configuration.gypi
index d865017..1d30080 100644
--- a/src/starboard/android/arm64/gyp_configuration.gypi
+++ b/src/starboard/android/arm64/gyp_configuration.gypi
@@ -14,7 +14,6 @@
{
'variables': {
- 'target_arch': 'arm64',
'arm_version': 8,
'armv7': 0,
'arm_thumb': 0,
diff --git a/src/starboard/android/arm64/vulkan/gyp_configuration.gypi b/src/starboard/android/arm64/vulkan/gyp_configuration.gypi
index f37376b..54e206a 100644
--- a/src/starboard/android/arm64/vulkan/gyp_configuration.gypi
+++ b/src/starboard/android/arm64/vulkan/gyp_configuration.gypi
@@ -14,12 +14,31 @@
{
'variables': {
- 'target_arch': 'arm64',
'arm_version': 8,
'armv7': 0,
'arm_thumb': 0,
'arm_neon': 0,
'arm_fpu': 'vfpv3-d16',
+
+ 'enable_vulkan': 1,
+
+ 'platform_libraries': [
+ '-lc++_shared',
+ '-lEGL_angle',
+ '-lGLESv2_angle',
+ '-lGLESv1_CM_angle',
+ '-lfeature_support_angle',
+ '-lOpenSLES',
+ '-landroid',
+ '-llog',
+ '-lmediandk',
+ ],
+
+ 'linker_flags': [
+ '-Wl',
+ '--verbose',
+ '-Llib',
+ ],
},
'target_defaults': {
diff --git a/src/starboard/android/shared/cobalt/configuration.py b/src/starboard/android/shared/cobalt/configuration.py
index 3633045..8fac1a4 100644
--- a/src/starboard/android/shared/cobalt/configuration.py
+++ b/src/starboard/android/shared/cobalt/configuration.py
@@ -60,6 +60,7 @@
# Disabled because of: Fail (Tests do not account for player with url?).
('csp/WebPlatformTest.Run/'
'content_security_policy_media_src_media_src_allowed_html'),
+ ('websockets/WebPlatformTest.Run/websockets_*'),
]
return filters
diff --git a/src/starboard/android/shared/configuration.cc b/src/starboard/android/shared/configuration.cc
new file mode 100644
index 0000000..374d0ed
--- /dev/null
+++ b/src/starboard/android/shared/configuration.cc
@@ -0,0 +1,73 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/android/shared/configuration.h"
+
+#include "cobalt/extension/configuration.h"
+#include "starboard/common/configuration_defaults.h"
+
+namespace starboard {
+namespace android {
+namespace shared {
+
+namespace {
+
+const char* CobaltUserOnExitStrategy() {
+ return "suspend";
+}
+
+int CobaltEglSwapInterval() {
+ return 0;
+}
+
+bool CobaltEnableJit() {
+ return true;
+}
+
+const CobaltExtensionConfigurationApi kConfigurationApi = {
+ kCobaltExtensionConfigurationName,
+ 1,
+ &CobaltUserOnExitStrategy,
+ &common::CobaltRenderDirtyRegionOnlyDefault,
+ &CobaltEglSwapInterval,
+ &common::CobaltFallbackSplashScreenUrlDefault,
+ &common::CobaltEnableQuicDefault,
+ &common::CobaltSkiaCacheSizeInBytesDefault,
+ &common::CobaltOffscreenTargetCacheSizeInBytesDefault,
+ &common::CobaltEncodedImageCacheSizeInBytesDefault,
+ &common::CobaltImageCacheSizeInBytesDefault,
+ &common::CobaltLocalTypefaceCacheSizeInBytesDefault,
+ &common::CobaltRemoteTypefaceCacheSizeInBytesDefault,
+ &common::CobaltMeshCacheSizeInBytesDefault,
+ &common::CobaltSoftwareSurfaceCacheSizeInBytesDefault,
+ &common::CobaltImageCacheCapacityMultiplierWhenPlayingVideoDefault,
+ &common::CobaltSkiaGlyphAtlasWidthDefault,
+ &common::CobaltSkiaGlyphAtlasHeightDefault,
+ &common::CobaltJsGarbageCollectionThresholdInBytesDefault,
+ &common::CobaltReduceCpuMemoryByDefault,
+ &common::CobaltReduceGpuMemoryByDefault,
+ &common::CobaltGcZealDefault,
+ &common::CobaltRasterizerTypeDefault,
+ &CobaltEnableJit,
+};
+
+} // namespace
+
+const void* GetConfigurationApi() {
+ return &kConfigurationApi;
+}
+
+} // namespace shared
+} // namespace android
+} // namespace starboard
diff --git a/src/starboard/android/shared/configuration.h b/src/starboard/android/shared/configuration.h
new file mode 100644
index 0000000..b6196e4
--- /dev/null
+++ b/src/starboard/android/shared/configuration.h
@@ -0,0 +1,28 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_ANDROID_SHARED_CONFIGURATION_H_
+#define STARBOARD_ANDROID_SHARED_CONFIGURATION_H_
+
+namespace starboard {
+namespace android {
+namespace shared {
+
+const void* GetConfigurationApi();
+
+} // namespace shared
+} // namespace android
+} // namespace starboard
+
+#endif // STARBOARD_ANDROID_SHARED_CONFIGURATION_H_
diff --git a/src/starboard/android/shared/configuration_constants.cc b/src/starboard/android/shared/configuration_constants.cc
index 62e403d..a70e4db 100644
--- a/src/starboard/android/shared/configuration_constants.cc
+++ b/src/starboard/android/shared/configuration_constants.cc
@@ -55,9 +55,6 @@
// Specifies whether this platform updates audio frames asynchronously.
const bool kSbHasAsyncAudioFramesReporting = true;
-// Allow playing audioless video.
-const bool kSbHasAudiolessVideo = true;
-
// Specifies whether this platform has webm/vp9 support. This should be set to
// non-zero on platforms with webm/vp9 support.
const bool kSbHasMediaWebmVp9Support = true;
@@ -141,5 +138,10 @@
// The string form of SB_PATH_SEP_CHAR.
const char* kSbPathSepString = ":";
+// Specifies the preferred byte order of color channels in a pixel. Refer to
+// starboard/configuration.h for the possible values. EGL/GLES platforms should
+// generally prefer a byte order of RGBA, regardless of endianness.
+const int kSbPreferredRgbaByteOrder = SB_PREFERRED_RGBA_BYTE_ORDER_RGBA;
+
// The maximum number of users that can be signed in at the same time.
const uint32_t kSbUserMaxSignedIn = 1;
diff --git a/src/starboard/android/shared/configuration_public.h b/src/starboard/android/shared/configuration_public.h
index 27a6b7f..4c1c8e9 100644
--- a/src/starboard/android/shared/configuration_public.h
+++ b/src/starboard/android/shared/configuration_public.h
@@ -159,11 +159,6 @@
// API. The basic requirement is a scaled, clipped, alpha-blended blit.
#define SB_HAS_BLITTER 0
-// Specifies the preferred byte order of color channels in a pixel. Refer to
-// starboard/configuration.h for the possible values. EGL/GLES platforms should
-// generally prefer a byte order of RGBA, regardless of endianness.
-#define SB_PREFERRED_RGBA_BYTE_ORDER SB_PREFERRED_RGBA_BYTE_ORDER_RGBA
-
// Indicates whether or not the given platform supports bilinear filtering.
// This can be checked to enable/disable renderer tests that verify that this is
// working properly.
diff --git a/src/starboard/android/shared/gyp_configuration.gypi b/src/starboard/android/shared/gyp_configuration.gypi
index d5f23e0..4267214 100644
--- a/src/starboard/android/shared/gyp_configuration.gypi
+++ b/src/starboard/android/shared/gyp_configuration.gypi
@@ -26,6 +26,8 @@
'gl_type': 'system_gles2',
'enable_remote_debugging': 0,
+ 'enable_vulkan%': 0,
+
'linker_flags': [
# The NDK default "ld" is actually the gold linker for all architectures
# except arm64 (aarch64) where it's the bfd linker. Don't use either of
diff --git a/src/starboard/android/shared/media_codec_bridge.cc b/src/starboard/android/shared/media_codec_bridge.cc
index 398f3b5..c3c599d 100644
--- a/src/starboard/android/shared/media_codec_bridge.cc
+++ b/src/starboard/android/shared/media_codec_bridge.cc
@@ -177,7 +177,8 @@
Handler* handler,
jobject j_surface,
jobject j_media_crypto,
- const SbMediaColorMetadata* color_metadata) {
+ const SbMediaColorMetadata* color_metadata,
+ bool require_software_codec) {
const char* mime = SupportedVideoCodecToMimeType(video_codec);
if (!mime) {
return scoped_ptr<MediaCodecBridge>(NULL);
@@ -221,8 +222,8 @@
"Ldev/cobalt/media/MediaCodecBridge$ColorInfo;)"
"Ldev/cobalt/media/MediaCodecBridge;",
reinterpret_cast<jlong>(native_media_codec_bridge.get()), j_mime.Get(),
- !!j_media_crypto, false, width, height, j_surface, j_media_crypto,
- j_color_info.Get());
+ !!j_media_crypto, require_software_codec, width, height, j_surface,
+ j_media_crypto, j_color_info.Get());
if (!j_media_codec_bridge) {
return scoped_ptr<MediaCodecBridge>(NULL);
@@ -394,7 +395,6 @@
JniEnvExt* env = JniEnvExt::Get();
SB_DCHECK(env->GetObjectRefType(j_media_codec_bridge_) == JNIGlobalRefType);
-
j_reused_get_output_format_result_ = env->NewObjectOrAbort(
"dev/cobalt/media/MediaCodecBridge$GetOutputFormatResult", "()V");
SB_DCHECK(j_reused_get_output_format_result_);
diff --git a/src/starboard/android/shared/media_codec_bridge.h b/src/starboard/android/shared/media_codec_bridge.h
index 0329f06..0937860 100644
--- a/src/starboard/android/shared/media_codec_bridge.h
+++ b/src/starboard/android/shared/media_codec_bridge.h
@@ -106,7 +106,8 @@
Handler* handler,
jobject j_surface,
jobject j_media_crypto,
- const SbMediaColorMetadata* color_metadata);
+ const SbMediaColorMetadata* color_metadata,
+ bool require_software_codec);
~MediaCodecBridge();
diff --git a/src/starboard/android/shared/media_decoder.cc b/src/starboard/android/shared/media_decoder.cc
index 24ed8a4..b9ade2d 100644
--- a/src/starboard/android/shared/media_decoder.cc
+++ b/src/starboard/android/shared/media_decoder.cc
@@ -106,7 +106,8 @@
int height,
jobject j_output_surface,
SbDrmSystem drm_system,
- const SbMediaColorMetadata* color_metadata)
+ const SbMediaColorMetadata* color_metadata,
+ bool require_software_codec)
: media_type_(kSbMediaTypeVideo),
host_(host),
drm_system_(static_cast<DrmSystem*>(drm_system)),
@@ -115,7 +116,7 @@
SB_DCHECK(!drm_system_ || j_media_crypto);
media_codec_bridge_ = MediaCodecBridge::CreateVideoMediaCodecBridge(
video_codec, width, height, this, j_output_surface, j_media_crypto,
- color_metadata);
+ color_metadata, require_software_codec);
if (!media_codec_bridge_) {
SB_LOG(ERROR) << "Failed to create video media codec bridge.";
}
diff --git a/src/starboard/android/shared/media_decoder.h b/src/starboard/android/shared/media_decoder.h
index ca05791..a474746 100644
--- a/src/starboard/android/shared/media_decoder.h
+++ b/src/starboard/android/shared/media_decoder.h
@@ -77,7 +77,8 @@
int height,
jobject j_output_surface,
SbDrmSystem drm_system,
- const SbMediaColorMetadata* color_metadata);
+ const SbMediaColorMetadata* color_metadata,
+ bool require_software_codec);
~MediaDecoder();
void Initialize(const ErrorCB& error_cb);
diff --git a/src/starboard/android/shared/media_is_audio_supported.cc b/src/starboard/android/shared/media_is_audio_supported.cc
index 4677b00..9952bf2 100644
--- a/src/starboard/android/shared/media_is_audio_supported.cc
+++ b/src/starboard/android/shared/media_is_audio_supported.cc
@@ -24,7 +24,11 @@
using starboard::android::shared::ScopedLocalJavaRef;
using starboard::android::shared::SupportedAudioCodecToMimeType;
-bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec, int64_t bitrate) {
+bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec,
+ const char* content_type,
+ int64_t bitrate) {
+ SB_UNREFERENCED_PARAMETER(content_type);
+
// Android now uses libopus based opus decoder.
if (audio_codec == kSbMediaAudioCodecOpus &&
bitrate < kSbMediaMaxAudioBitrateInBitsPerSecond) {
diff --git a/src/starboard/android/shared/media_is_video_supported.cc b/src/starboard/android/shared/media_is_video_supported.cc
index 15ff35b..fb9900a 100644
--- a/src/starboard/android/shared/media_is_video_supported.cc
+++ b/src/starboard/android/shared/media_is_video_supported.cc
@@ -33,15 +33,21 @@
const jint HDR_TYPE_HDR10 = 2;
const jint HDR_TYPE_HLG = 3;
-bool IsHDRTransferCharacteristicsSupported(SbMediaTransferId transfer_id) {
- SB_DCHECK(transfer_id != kSbMediaTransferIdBt709 &&
- transfer_id != kSbMediaTransferIdUnspecified);
- // An HDR capable VP9 decoder is needed to handle HDR at all.
- bool has_hdr_capable_vp9_decoder =
+bool IsHDRTransferCharacteristicsSupported(SbMediaVideoCodec video_codec,
+ SbMediaTransferId transfer_id) {
+ const char* mime = SupportedVideoCodecToMimeType(video_codec);
+ if (!mime) {
+ return false;
+ }
+ JniEnvExt* env = JniEnvExt::Get();
+
+ // An HDR capable VP9 or AV1 decoder is needed to handle HDR at all.
+ bool has_hdr_capable_decoder =
JniEnvExt::Get()->CallStaticBooleanMethodOrAbort(
- "dev/cobalt/media/MediaCodecUtil", "hasHdrCapableVp9Decoder",
- "()Z") == JNI_TRUE;
- if (!has_hdr_capable_vp9_decoder) {
+ "dev/cobalt/media/MediaCodecUtil", "hasHdrCapableVideoDecoder",
+ "(Ljava/lang/String;)Z",
+ env->NewStringStandardUTFOrAbort(mime)) == JNI_TRUE;
+ if (!has_hdr_capable_decoder) {
return false;
}
@@ -63,6 +69,7 @@
} // namespace
bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec,
+ const char* content_type,
int profile,
int level,
int bit_depth,
@@ -75,14 +82,15 @@
int fps,
bool decode_to_texture_required) {
if (!IsSDRVideo(bit_depth, primary_id, transfer_id, matrix_id)) {
- if (!IsHDRTransferCharacteristicsSupported(transfer_id)) {
+ if (!IsHDRTransferCharacteristicsSupported(video_codec, transfer_id)) {
return false;
}
}
- // While not necessarily true, for now we assume that all Android devices
- // can play decode-to-texture video just as well as normal video.
+ SB_UNREFERENCED_PARAMETER(content_type);
SB_UNREFERENCED_PARAMETER(profile);
SB_UNREFERENCED_PARAMETER(level);
+ // While not necessarily true, for now we assume that all Android devices
+ // can play decode-to-texture video just as well as normal video.
SB_UNREFERENCED_PARAMETER(decode_to_texture_required);
const char* mime = SupportedVideoCodecToMimeType(video_codec);
diff --git a/src/starboard/android/shared/platform_deploy.gypi b/src/starboard/android/shared/platform_deploy.gypi
index 3d6e60f..d00db17 100644
--- a/src/starboard/android/shared/platform_deploy.gypi
+++ b/src/starboard/android/shared/platform_deploy.gypi
@@ -40,15 +40,15 @@
'action': [
'<(DEPTH)/starboard/android/apk/cobalt-gradle.sh',
'--sdk', '<(ANDROID_HOME)',
- '--ndk', '<(NDK_HOME)',
- '--cache', '<(GRADLE_FILES_DIR)/cache',
- '--project-dir', '<(DEPTH)/starboard/android/apk/',
+ '--cache', '$${PWD}/<(GRADLE_FILES_DIR)/cache',
+ '--project-dir', '$${PWD}/<(DEPTH)/starboard/android/apk/',
'-P', 'cobaltBuildAbi=<(ANDROID_ABI)',
- '-P', 'cobaltDeployApk=<(apk)',
- '-P', 'cobaltContentDir=<(content_deploy_dir)',
- '-P', 'cobaltGradleDir=<(GRADLE_FILES_DIR)',
- '-P', 'cobaltProductDir=<(PRODUCT_DIR)',
+ '-P', 'cobaltDeployApk=$${PWD}/<(apk)',
+ '-P', 'cobaltContentDir=$${PWD}/<(content_deploy_dir)',
+ '-P', 'cobaltGradleDir=$${PWD}/<(GRADLE_FILES_DIR)',
+ '-P', 'cobaltProductDir=$${PWD}/<(PRODUCT_DIR)',
'-P', 'cobaltTarget=<(executable_name)',
+ '-P', 'enableVulkan=<(enable_vulkan)',
'assembleCobalt_<(GRADLE_BUILD_TYPE)',
],
'message': 'Build APK: <(apk)',
diff --git a/src/starboard/android/shared/player_components_factory.cc b/src/starboard/android/shared/player_components_factory.cc
index 414f317..ebddae0 100644
--- a/src/starboard/android/shared/player_components_factory.cc
+++ b/src/starboard/android/shared/player_components_factory.cc
@@ -55,18 +55,16 @@
auto decoder_creator = [](const SbMediaAudioSampleInfo& audio_sample_info,
SbDrmSystem drm_system) {
- using AacAudioDecoder = ::starboard::android::shared::AudioDecoder;
- using OpusAudioDecoder = ::starboard::shared::opus::OpusAudioDecoder;
-
if (audio_sample_info.codec == kSbMediaAudioCodecAac) {
- scoped_ptr<AacAudioDecoder> audio_decoder_impl(new AacAudioDecoder(
- audio_sample_info.codec, audio_sample_info, drm_system));
+ scoped_ptr<android::shared::AudioDecoder> audio_decoder_impl(
+ new android::shared::AudioDecoder(audio_sample_info.codec,
+ audio_sample_info, drm_system));
if (audio_decoder_impl->is_valid()) {
return audio_decoder_impl.PassAs<AudioDecoder>();
}
} else if (audio_sample_info.codec == kSbMediaAudioCodecOpus) {
- scoped_ptr<OpusAudioDecoder> audio_decoder_impl(
- new OpusAudioDecoder(audio_sample_info));
+ scoped_ptr<opus::OpusAudioDecoder> audio_decoder_impl(
+ new opus::OpusAudioDecoder(audio_sample_info));
if (audio_decoder_impl->is_valid()) {
return audio_decoder_impl.PassAs<AudioDecoder>();
}
@@ -83,19 +81,18 @@
}
if (creation_parameters.video_codec() != kSbMediaVideoCodecNone) {
- using VideoDecoderImpl = ::starboard::android::shared::VideoDecoder;
- using VideoRenderAlgorithmImpl =
- ::starboard::android::shared::VideoRenderAlgorithm;
-
SB_DCHECK(video_decoder);
SB_DCHECK(video_render_algorithm);
SB_DCHECK(video_renderer_sink);
SB_DCHECK(error_message);
- scoped_ptr<VideoDecoderImpl> video_decoder_impl(new VideoDecoderImpl(
- creation_parameters.video_codec(), creation_parameters.drm_system(),
- creation_parameters.output_mode(),
- creation_parameters.decode_target_graphics_context_provider()));
+ scoped_ptr<android::shared::VideoDecoder> video_decoder_impl(
+ new android::shared::VideoDecoder(
+ creation_parameters.video_codec(),
+ creation_parameters.drm_system(),
+ creation_parameters.output_mode(),
+ creation_parameters.decode_target_graphics_context_provider(),
+ creation_parameters.max_video_capabilities()));
if (video_decoder_impl->is_valid()) {
*video_renderer_sink = video_decoder_impl->GetSink();
video_decoder->reset(video_decoder_impl.release());
@@ -106,7 +103,7 @@
return false;
}
- video_render_algorithm->reset(new VideoRenderAlgorithmImpl);
+ video_render_algorithm->reset(new android::shared::VideoRenderAlgorithm);
}
return true;
diff --git a/src/starboard/android/shared/player_create.cc b/src/starboard/android/shared/player_create.cc
index d832483..2b3e80c 100644
--- a/src/starboard/android/shared/player_create.cc
+++ b/src/starboard/android/shared/player_create.cc
@@ -15,12 +15,15 @@
#include "starboard/player.h"
#include "starboard/android/shared/cobalt/android_media_session_client.h"
+#include "starboard/android/shared/video_decoder.h"
+#include "starboard/android/shared/video_window.h"
#include "starboard/common/log.h"
#include "starboard/configuration.h"
#include "starboard/decode_target.h"
#include "starboard/shared/starboard/player/filter/filter_based_player_worker_handler.h"
#include "starboard/shared/starboard/player/player_internal.h"
#include "starboard/shared/starboard/player/player_worker.h"
+#include "starboard/string.h"
using starboard::shared::starboard::player::filter::
FilterBasedPlayerWorkerHandler;
@@ -28,6 +31,7 @@
using starboard::android::shared::cobalt::kPlaying;
using starboard::android::shared::cobalt::
UpdateActiveSessionPlatformPlaybackState;
+using starboard::android::shared::VideoDecoder;
SbPlayer SbPlayerCreate(SbWindow window,
const SbPlayerCreationParam* creation_param,
@@ -76,9 +80,7 @@
<< "\".";
if (!sample_deallocate_func || !decoder_status_func || !player_status_func
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
|| !player_error_func
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
) {
return kSbPlayerInvalid;
}
@@ -115,13 +117,31 @@
return kSbPlayerInvalid;
}
- // TODO: increase this once we support multiple video windows.
- const int kMaxNumberOfPlayers = 1;
- if (SbPlayerPrivate::number_of_players() >= kMaxNumberOfPlayers) {
- return kSbPlayerInvalid;
+ if (SbStringGetLength(max_video_capabilities) == 0) {
+ // Check the availability of hardware video decoder. Main player must use a
+ // hardware codec, but Android doesn't support multiple concurrent hardware
+ // codecs. Since it's not safe to have multiple hardware codecs, we only
+ // support one main player on Android, which can be either in punch out mode
+ // or decode to target mode.
+ const int kMaxNumberOfHardwareDecoders = 1;
+ if (VideoDecoder::number_of_hardware_decoders() >=
+ kMaxNumberOfHardwareDecoders) {
+ return kSbPlayerInvalid;
+ }
+ // Only update session state for main player.
+ UpdateActiveSessionPlatformPlaybackState(kPlaying);
}
- UpdateActiveSessionPlatformPlaybackState(kPlaying);
+ if (creation_param->output_mode != kSbPlayerOutputModeDecodeToTexture) {
+ // Check the availability of the video window. As we only support one main
+ // player, and sub players are in decode to texture mode on Android, a
+ // single video window should be enough.
+ if (!starboard::android::shared::VideoSurfaceHolder::
+ IsVideoSurfaceAvailable()) {
+ SB_LOG(ERROR) << "Video surface is not available now.";
+ return kSbPlayerInvalid;
+ }
+ }
starboard::scoped_ptr<PlayerWorker::Handler> handler(
new FilterBasedPlayerWorkerHandler(creation_param, provider));
@@ -130,10 +150,12 @@
sample_deallocate_func, decoder_status_func, player_status_func,
player_error_func, context, handler.Pass());
- // TODO: accomplish this through more direct means.
- // Set the bounds to initialize the VideoSurfaceView. The initial values don't
- // matter.
- SbPlayerSetBounds(player, 0, 0, 0, 0, 0);
+ if (creation_param->output_mode != kSbPlayerOutputModeDecodeToTexture) {
+ // TODO: accomplish this through more direct means.
+ // Set the bounds to initialize the VideoSurfaceView. The initial values
+ // don't matter.
+ SbPlayerSetBounds(player, 0, 0, 0, 0, 0);
+ }
return player;
}
diff --git a/src/starboard/android/shared/player_get_preferred_output_mode.cc b/src/starboard/android/shared/player_get_preferred_output_mode.cc
new file mode 100644
index 0000000..70c29cf
--- /dev/null
+++ b/src/starboard/android/shared/player_get_preferred_output_mode.cc
@@ -0,0 +1,92 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/player.h"
+
+#include <algorithm>
+
+#include "starboard/configuration.h"
+#include "starboard/shared/starboard/player/filter/video_decoder_internal.h"
+#include "starboard/string.h"
+
+#if SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
+
+SbPlayerOutputMode SbPlayerGetPreferredOutputMode(
+ const SbPlayerCreationParam* creation_param) {
+ using starboard::shared::starboard::player::filter::VideoDecoder;
+
+ if (!creation_param) {
+ SB_LOG(ERROR) << "creation_param cannot be NULL";
+ return kSbPlayerOutputModeInvalid;
+ }
+
+ if (creation_param->audio_sample_info.codec != kSbMediaAudioCodecNone &&
+ !creation_param->audio_sample_info.mime) {
+ SB_LOG(ERROR) << "creation_param->audio_sample_info.mime cannot be NULL";
+ return kSbPlayerOutputModeInvalid;
+ }
+
+ if (creation_param->video_sample_info.codec != kSbMediaVideoCodecNone &&
+ !creation_param->video_sample_info.mime) {
+ SB_LOG(ERROR) << "creation_param->video_sample_info.mime cannot be NULL";
+ return kSbPlayerOutputModeInvalid;
+ }
+
+ if (creation_param->video_sample_info.codec != kSbMediaVideoCodecNone &&
+ !creation_param->video_sample_info.max_video_capabilities) {
+ SB_LOG(ERROR) << "creation_param->video_sample_info.max_video_capabilities"
+ << " cannot be NULL";
+ return kSbPlayerOutputModeInvalid;
+ }
+
+ auto codec = creation_param->video_sample_info.codec;
+ auto drm_system = creation_param->drm_system;
+ auto max_video_capabilities =
+ creation_param->video_sample_info.max_video_capabilities;
+
+ // Sub players must use decode-to-texture on Android.
+ if (max_video_capabilities && SbStringGetLength(max_video_capabilities) > 0) {
+ if (VideoDecoder::OutputModeSupported(kSbPlayerOutputModeDecodeToTexture,
+ codec, drm_system)) {
+ return kSbPlayerOutputModeDecodeToTexture;
+ }
+ SB_NOTREACHED();
+ return kSbPlayerOutputModeInvalid;
+ }
+
+ // The main player may use any output mode.
+ SbPlayerOutputMode output_modes_to_check[] = {
+ kSbPlayerOutputModePunchOut, kSbPlayerOutputModeDecodeToTexture,
+ };
+
+ // Check |kSbPlayerOutputModeDecodeToTexture| first if the caller prefers it.
+ if (creation_param->output_mode == kSbPlayerOutputModeDecodeToTexture) {
+ std::swap(output_modes_to_check[0], output_modes_to_check[1]);
+ }
+
+ if (VideoDecoder::OutputModeSupported(output_modes_to_check[0], codec,
+ drm_system)) {
+ return output_modes_to_check[0];
+ }
+
+ if (VideoDecoder::OutputModeSupported(output_modes_to_check[1], codec,
+ drm_system)) {
+ return output_modes_to_check[1];
+ }
+
+ SB_NOTREACHED();
+ return kSbPlayerOutputModeInvalid;
+}
+
+#endif // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
diff --git a/src/starboard/android/shared/sdk_utils.py b/src/starboard/android/shared/sdk_utils.py
index 3457efb..dee8241d 100644
--- a/src/starboard/android/shared/sdk_utils.py
+++ b/src/starboard/android/shared/sdk_utils.py
@@ -13,14 +13,11 @@
# limitations under the License.
"""Utilities to use the toolchain from the Android NDK."""
-import ConfigParser
import fcntl
-import hashlib
import logging
import os
import re
import shutil
-import StringIO
import subprocess
import sys
import time
@@ -29,20 +26,26 @@
from starboard.tools import build
+# Which version of the Android NDK and CMake to install and build with.
+# Note that build.gradle parses these out of this file too.
+_NDK_VERSION = '21.0.6113669'
+_CMAKE_VERSION = '3.10.2.4988404'
+
# Packages to install in the Android SDK.
# We download ndk-bundle separately, so it's not in this list.
# Get available packages from "sdkmanager --list --verbose"
_ANDROID_SDK_PACKAGES = [
'build-tools;29.0.2',
- 'cmake;3.10.2.4988404',
+ 'cmake;' + _CMAKE_VERSION,
+ 'cmdline-tools;1.0',
'emulator',
'extras;android;m2repository',
'extras;google;m2repository',
'lldb;3.1',
+ 'ndk;' + _NDK_VERSION,
'patcher;v4',
'platforms;android-29',
'platform-tools',
- 'tools',
]
# Seconds to sleep before writing "y" for android sdk update license prompt.
@@ -50,7 +53,7 @@
# Location from which to download the SDK command-line tools
# see https://developer.android.com/studio/index.html#command-tools
-_SDK_URL = 'https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip'
+_SDK_URL = 'https://dl.google.com/android/repository/commandlinetools-linux-6200805_latest.zip'
# Location from which to download the Android NDK.
# see https://developer.android.com/ndk/downloads (perhaps in "NDK archives")
@@ -70,44 +73,10 @@
else:
_SDK_PATH = _STARBOARD_TOOLCHAINS_SDK_DIR
-_ANDROID_NDK_HOME = os.environ.get('ANDROID_NDK_HOME')
-if _ANDROID_NDK_HOME:
- _NDK_PATH = _ANDROID_NDK_HOME
-else:
- _NDK_PATH = os.path.join(_SDK_PATH, 'ndk-bundle')
+_NDK_PATH = os.path.join(_SDK_PATH, 'ndk', _NDK_VERSION)
-_SDKMANAGER_TOOL = os.path.join(_SDK_PATH, 'tools', 'bin', 'sdkmanager')
-
-# Maps the Android ABI to the architecture name of the toolchain.
-_TOOLS_ABI_ARCH_MAP = {
- 'x86': 'x86',
- 'armeabi': 'arm',
- 'armeabi-v7a': 'arm',
- 'arm64-v8a': 'arm64',
-}
-
-_SCRIPT_HASH_PROPERTY = 'SdkUtils.Hash'
-
-with open(__file__, 'rb') as script:
- _SCRIPT_HASH = hashlib.md5(script.read()).hexdigest()
-
-
-def _CheckStamp(dir_path):
- """Checks that the specified directory is up-to-date with the NDK."""
- stamp_path = os.path.join(dir_path, 'ndk.stamp')
- return (os.path.exists(stamp_path) and
- _ReadNdkRevision(stamp_path) == _GetInstalledNdkRevision() and
- _ReadProperty(stamp_path, _SCRIPT_HASH_PROPERTY) == _SCRIPT_HASH)
-
-
-def _UpdateStamp(dir_path):
- """Updates the stamp file in the specified directory to the NDK revision."""
- path = GetNdkPath()
- properties_path = os.path.join(path, 'source.properties')
- stamp_path = os.path.join(dir_path, 'ndk.stamp')
- shutil.copyfile(properties_path, stamp_path)
- with open(stamp_path, 'a') as stamp:
- stamp.write('{} = {}\n'.format(_SCRIPT_HASH_PROPERTY, _SCRIPT_HASH))
+_SDKMANAGER_TOOL = os.path.join(_SDK_PATH, 'cmdline-tools', '1.0', 'bin',
+ 'sdkmanager')
def GetNdkPath():
@@ -118,32 +87,6 @@
return _SDK_PATH
-def _ReadNdkRevision(properties_path):
- return _ReadProperty(properties_path, 'pkg.revision')
-
-
-def _ReadProperty(properties_path, property_key):
- with open(properties_path, 'r') as f:
- ini_str = '[properties]\n' + f.read()
- config = ConfigParser.RawConfigParser()
- config.readfp(StringIO.StringIO(ini_str))
- try:
- return config.get('properties', property_key)
- except ConfigParser.NoOptionError:
- return None
-
-
-def _GetInstalledNdkRevision():
- """Returns the installed NDK's revision."""
- path = GetNdkPath()
- properties_path = os.path.join(path, 'source.properties')
- try:
- return _ReadNdkRevision(properties_path)
- except IOError:
- logging.error("Error: Can't read NDK properties in %s", properties_path)
- sys.exit(1)
-
-
def _DownloadAndUnzipFile(url, destination_path):
dl_file, dummy_headers = urllib.urlretrieve(url)
_UnzipFile(dl_file, destination_path)
@@ -165,49 +108,34 @@
toolchains_dir_fd = os.open(_STARBOARD_TOOLCHAINS_DIR, os.O_RDONLY)
fcntl.flock(toolchains_dir_fd, fcntl.LOCK_EX)
+ if os.environ.get('ANDROID_NDK_HOME'):
+ logging.warning('Warning: ANDROID_NDK_HOME is deprecated and ignored.')
+
if _ANDROID_HOME:
if not os.access(_SDKMANAGER_TOOL, os.X_OK):
- logging.error('Error: ANDROID_HOME is set but SDK is not present!')
+ logging.error('Error: ANDROID_HOME is set but SDK is not present.')
sys.exit(1)
logging.warning('Warning: Using Android SDK in ANDROID_HOME,'
' which is not automatically updated.\n'
' The following package versions are installed:')
installed_packages = _GetInstalledSdkPackages()
for package in _ANDROID_SDK_PACKAGES:
- version = installed_packages.get(package, '< MISSING! >')
+ version = installed_packages.get(package, '< NOT INSTALLED >')
msg = ' {:30} : {}'.format(package, version)
logging.warning(msg)
- else:
- logging.warning('Checking Android SDK.')
- _DownloadInstallOrUpdateSdk()
- ndk_path = GetNdkPath()
- if _ANDROID_NDK_HOME:
- logging.warning('Warning: ANDROID_NDK_HOME references NDK %s in %s,'
- ' which is not automatically updated.',
- _GetInstalledNdkRevision(), ndk_path)
+ if not os.path.exists(GetNdkPath()):
+ logging.error('Error: ANDROID_HOME is is missing NDK %s.',
+ _NDK_VERSION)
+ sys.exit(1)
- if _ANDROID_HOME or _ANDROID_NDK_HOME:
reply = raw_input(
'Do you want to continue using your custom Android tools? [y/N]')
if reply.upper() != 'Y':
sys.exit(1)
- elif not _CheckStamp(ndk_path):
- logging.warning('Downloading NDK from %s to %s', _NDK_URL, ndk_path)
- if os.path.exists(ndk_path):
- shutil.rmtree(ndk_path)
- # Download the NDK into _STARBOARD_TOOLCHAINS_DIR and move the top
- # _NDK_ZIP_REVISION directory that is in the zip to 'ndk-bundle'.
- ndk_unzip_path = os.path.join(_STARBOARD_TOOLCHAINS_DIR,
- _NDK_ZIP_REVISION)
- if os.path.exists(ndk_unzip_path):
- shutil.rmtree(ndk_unzip_path)
- _DownloadAndUnzipFile(_NDK_URL, _STARBOARD_TOOLCHAINS_DIR)
- # Move NDK into its proper final place.
- os.rename(ndk_unzip_path, ndk_path)
- _UpdateStamp(ndk_path)
-
- logging.warning('Using Android NDK version %s', _GetInstalledNdkRevision())
+ else:
+ logging.warning('Checking Android SDK.')
+ _DownloadInstallOrUpdateSdk()
finally:
fcntl.flock(toolchains_dir_fd, fcntl.LOCK_UN)
os.close(toolchains_dir_fd)
@@ -242,7 +170,8 @@
new_style = False
old_style = False
for line in iter(p.stdout.readline, ''):
-
+ # Throw away loading progress indicators up to the last CR.
+ line = line.split('\r')[-1]
if section_re.match(line):
if new_style or old_style:
# We left the new/old style installed packages section
@@ -292,6 +221,14 @@
if os.path.exists(_STARBOARD_TOOLCHAINS_SDK_DIR):
shutil.rmtree(_STARBOARD_TOOLCHAINS_SDK_DIR)
_DownloadAndUnzipFile(_SDK_URL, _STARBOARD_TOOLCHAINS_SDK_DIR)
+ # TODO: Remove this workaround for sdkmanager incorrectly picking up the
+ # "tools" directory from the ZIP as the name of its component.
+ if not os.access(_SDKMANAGER_TOOL, os.X_OK):
+ old_tools_dir = os.path.join(_STARBOARD_TOOLCHAINS_SDK_DIR, 'tools')
+ new_tools_dir = os.path.join(_STARBOARD_TOOLCHAINS_SDK_DIR,
+ 'cmdline-tools', '1.0')
+ os.mkdir(os.path.dirname(new_tools_dir))
+ os.rename(old_tools_dir, new_tools_dir)
if not os.access(_SDKMANAGER_TOOL, os.X_OK):
logging.error('SDK download failed.')
sys.exit(1)
diff --git a/src/starboard/android/shared/starboard_platform.gypi b/src/starboard/android/shared/starboard_platform.gypi
index 23150de..aa9fe4e 100644
--- a/src/starboard/android/shared/starboard_platform.gypi
+++ b/src/starboard/android/shared/starboard_platform.gypi
@@ -77,6 +77,8 @@
'bionic/net_if.cpp',
'bionic/private/bionic_macros.h',
'bionic/private/ErrnoRestorer.h',
+ 'configuration.cc',
+ 'configuration.h',
'configuration_public.h',
'configuration_constants.cc',
'decode_target_create.cc',
@@ -136,6 +138,7 @@
'microphone_impl.cc',
'player_create.cc',
'player_destroy.cc',
+ 'player_get_preferred_output_mode.cc',
'player_set_bounds.cc',
'player_set_playback_rate.cc',
'sanitizer_options.cc',
@@ -404,19 +407,15 @@
'<(DEPTH)/starboard/shared/starboard/player/job_thread.cc',
'<(DEPTH)/starboard/shared/starboard/player/job_thread.h',
'<(DEPTH)/starboard/shared/starboard/player/player_get_current_frame.cc',
- '<(DEPTH)/starboard/shared/starboard/player/player_get_info.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_get_info2.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_get_maximum_number_of_samples_per_write.cc',
- '<(DEPTH)/starboard/shared/starboard/player/player_get_preferred_output_mode_prefer_punchout.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_internal.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_internal.h',
- '<(DEPTH)/starboard/shared/starboard/player/player_seek.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_seek2.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_set_volume.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_worker.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_worker.h',
'<(DEPTH)/starboard/shared/starboard/player/player_write_end_of_stream.cc',
- '<(DEPTH)/starboard/shared/starboard/player/player_write_sample.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_write_sample2.cc',
'<(DEPTH)/starboard/shared/starboard/queue_application.cc',
'<(DEPTH)/starboard/shared/starboard/queue_application.h',
diff --git a/src/starboard/android/shared/system_get_extensions.cc b/src/starboard/android/shared/system_get_extensions.cc
index 262d04c..869446b 100644
--- a/src/starboard/android/shared/system_get_extensions.cc
+++ b/src/starboard/android/shared/system_get_extensions.cc
@@ -14,7 +14,9 @@
#include "starboard/system.h"
+#include "cobalt/extension/configuration.h"
#include "cobalt/extension/platform_service.h"
+#include "starboard/android/shared/configuration.h"
#include "starboard/android/shared/platform_service.h"
#include "starboard/common/log.h"
#include "starboard/common/string.h"
@@ -23,5 +25,8 @@
if (SbStringCompareAll(name, kCobaltExtensionPlatformServiceName) == 0) {
return starboard::android::shared::GetPlatformServiceApi();
}
+ if (SbStringCompareAll(name, kCobaltExtensionConfigurationName) == 0) {
+ return starboard::android::shared::GetConfigurationApi();
+ }
return NULL;
}
diff --git a/src/starboard/android/shared/video_decoder.cc b/src/starboard/android/shared/video_decoder.cc
index b3d542b..1a32e22 100644
--- a/src/starboard/android/shared/video_decoder.cc
+++ b/src/starboard/android/shared/video_decoder.cc
@@ -32,6 +32,7 @@
#include "starboard/drm.h"
#include "starboard/memory.h"
#include "starboard/shared/starboard/player/filter/video_frame_internal.h"
+#include "starboard/string.h"
#include "starboard/thread.h"
namespace starboard {
@@ -113,6 +114,8 @@
} // namespace
+int VideoDecoder::number_of_hardware_decoders_ = 0;
+
class VideoDecoder::Sink : public VideoDecoder::VideoRendererSink {
public:
bool Render() {
@@ -157,14 +160,24 @@
SbDrmSystem drm_system,
SbPlayerOutputMode output_mode,
SbDecodeTargetGraphicsContextProvider*
- decode_target_graphics_context_provider)
+ decode_target_graphics_context_provider,
+ const char* max_video_capabilities)
: video_codec_(video_codec),
drm_system_(static_cast<DrmSystem*>(drm_system)),
output_mode_(output_mode),
decode_target_graphics_context_provider_(
decode_target_graphics_context_provider),
has_new_texture_available_(false),
- surface_condition_variable_(surface_destroy_mutex_) {
+ surface_condition_variable_(surface_destroy_mutex_),
+ require_software_codec_(max_video_capabilities &&
+ SbStringGetLength(max_video_capabilities) > 0) {
+ if (require_software_codec_) {
+ SB_DCHECK(output_mode_ == kSbPlayerOutputModeDecodeToTexture);
+ }
+ if (!require_software_codec_) {
+ number_of_hardware_decoders_++;
+ }
+
if (!InitializeCodec()) {
SB_LOG(ERROR) << "Failed to initialize video decoder.";
TeardownCodec();
@@ -174,6 +187,10 @@
VideoDecoder::~VideoDecoder() {
TeardownCodec();
ClearVideoWindow();
+
+ if (!require_software_codec_) {
+ number_of_hardware_decoders_--;
+ }
}
scoped_refptr<VideoDecoder::VideoRendererSink> VideoDecoder::GetSink() {
@@ -344,7 +361,7 @@
SB_DCHECK(!drm_system_ || j_media_crypto);
media_decoder_.reset(new MediaDecoder(
this, video_codec_, width, height, j_output_surface, drm_system_,
- color_metadata_ ? &*color_metadata_ : nullptr));
+ color_metadata_ ? &*color_metadata_ : nullptr, require_software_codec_));
if (media_decoder_->is_valid()) {
if (error_cb_) {
media_decoder_->Initialize(error_cb_);
diff --git a/src/starboard/android/shared/video_decoder.h b/src/starboard/android/shared/video_decoder.h
index 18f3730..46b260b 100644
--- a/src/starboard/android/shared/video_decoder.h
+++ b/src/starboard/android/shared/video_decoder.h
@@ -15,7 +15,9 @@
#ifndef STARBOARD_ANDROID_SHARED_VIDEO_DECODER_H_
#define STARBOARD_ANDROID_SHARED_VIDEO_DECODER_H_
+#include <atomic>
#include <deque>
+#include <string>
#include "starboard/android/shared/drm_system.h"
#include "starboard/android/shared/media_codec_bridge.h"
@@ -49,11 +51,16 @@
class Sink;
+ static int number_of_hardware_decoders() {
+ return number_of_hardware_decoders_;
+ }
+
VideoDecoder(SbMediaVideoCodec video_codec,
SbDrmSystem drm_system,
SbPlayerOutputMode output_mode,
SbDecodeTargetGraphicsContextProvider*
- decode_target_graphics_context_provider);
+ decode_target_graphics_context_provider,
+ const char* max_video_capabilities);
~VideoDecoder() override;
scoped_refptr<VideoRendererSink> GetSink();
@@ -93,17 +100,22 @@
void OnSurfaceDestroyed() override;
+ static int number_of_hardware_decoders_;
+
// These variables will be initialized inside ctor or Initialize() and will
// not be changed during the life time of this class.
const SbMediaVideoCodec video_codec_;
DecoderStatusCB decoder_status_cb_;
ErrorCB error_cb_;
DrmSystem* drm_system_;
-
- SbPlayerOutputMode output_mode_;
-
+ const SbPlayerOutputMode output_mode_;
SbDecodeTargetGraphicsContextProvider*
decode_target_graphics_context_provider_;
+ // Android doesn't offically support multi concurrent codecs. But the device
+ // usually has at least one hardware decoder and Google's software decoders.
+ // Google's software decoders can work concurrently. So, we use HW decoder for
+ // the main player and SW decoder for sub players.
+ const bool require_software_codec_;
// If decode-to-texture is enabled, then we store the decode target texture
// inside of this |decode_target_| member.
diff --git a/src/starboard/android/shared/video_window.cc b/src/starboard/android/shared/video_window.cc
index 2fd56da..2216d08 100644
--- a/src/starboard/android/shared/video_window.cc
+++ b/src/starboard/android/shared/video_window.cc
@@ -68,6 +68,15 @@
}
}
+// static
+bool VideoSurfaceHolder::IsVideoSurfaceAvailable() {
+ // We only consider video surface is available when there is a video
+ // surface and it is not held by any decoder, i.e.
+ // g_video_surface_holder is NULL.
+ ScopedLock lock(*GetViewSurfaceMutex());
+ return !g_video_surface_holder && g_j_video_surface;
+}
+
jobject VideoSurfaceHolder::AcquireVideoSurface() {
ScopedLock lock(*GetViewSurfaceMutex());
SB_DCHECK(g_video_surface_holder == NULL);
diff --git a/src/starboard/android/shared/video_window.h b/src/starboard/android/shared/video_window.h
index 908b567..17db407 100644
--- a/src/starboard/android/shared/video_window.h
+++ b/src/starboard/android/shared/video_window.h
@@ -24,6 +24,9 @@
class VideoSurfaceHolder {
public:
+ // Return true only if the video surface is available.
+ static bool IsVideoSurfaceAvailable();
+
// OnSurfaceDestroyed() will be invoked when surface is destroyed. When this
// function is called, the decoder no longer owns the surface. Calling
// AcquireVideoSurface(), ReleaseVideoSurface(), GetVideoWindowSize() or
diff --git a/src/starboard/android/x86/gyp_configuration.gypi b/src/starboard/android/x86/gyp_configuration.gypi
index 3d239cf..a339ae6 100644
--- a/src/starboard/android/x86/gyp_configuration.gypi
+++ b/src/starboard/android/x86/gyp_configuration.gypi
@@ -14,7 +14,6 @@
{
'variables': {
- 'target_arch': 'x86',
# Android x86 does not support the instruction set required by SSE4, while
# Opus still tries to build all SSE code in for run time selection, causing
# build errors. Exclude all SSE-related code.
diff --git a/src/starboard/atomic.h b/src/starboard/atomic.h
index b09a68c..81b897a 100644
--- a/src/starboard/atomic.h
+++ b/src/starboard/atomic.h
@@ -30,9 +30,7 @@
extern "C" {
#endif
-#if SB_API_VERSION >= 10
typedef int8_t SbAtomic8;
-#endif
typedef int32_t SbAtomic32;
// Atomically execute:
@@ -88,14 +86,12 @@
static SbAtomic32 SbAtomicAcquire_Load(volatile const SbAtomic32* ptr);
static SbAtomic32 SbAtomicRelease_Load(volatile const SbAtomic32* ptr);
-#if SB_API_VERSION >= 10
// Overloaded functions for Atomic8.
static SbAtomic8 SbAtomicRelease_CompareAndSwap8(volatile SbAtomic8* ptr,
SbAtomic8 old_value,
SbAtomic8 new_value);
static void SbAtomicNoBarrier_Store8(volatile SbAtomic8* ptr, SbAtomic8 value);
static SbAtomic8 SbAtomicNoBarrier_Load8(volatile const SbAtomic8* ptr);
-#endif
// 64-bit atomic operations (only available on 64-bit processors).
#if SB_HAS(64_BIT_ATOMICS)
@@ -262,7 +258,6 @@
namespace starboard {
namespace atomic {
-#if SB_API_VERSION >= 10
inline SbAtomic8 Release_CompareAndSwap(volatile SbAtomic8* ptr,
SbAtomic8 old_value,
SbAtomic8 new_value) {
@@ -276,7 +271,6 @@
inline SbAtomic8 NoBarrier_Load(volatile const SbAtomic8* ptr) {
return SbAtomicNoBarrier_Load8(ptr);
}
-#endif
inline SbAtomic32 NoBarrier_CompareAndSwap(volatile SbAtomic32* ptr,
SbAtomic32 old_value,
diff --git a/src/starboard/build/base_configuration.gypi b/src/starboard/build/base_configuration.gypi
index 068c3aa..0da4c16 100644
--- a/src/starboard/build/base_configuration.gypi
+++ b/src/starboard/build/base_configuration.gypi
@@ -105,7 +105,8 @@
# The source of EGL and GLES headers and libraries.
# Valid values (case and everything sensitive!):
# 'none' - No EGL + GLES implementation is available on this platform.
- # 'system_gles3' - Use the system implementation of EGL + GLES3. The
+ # 'system_gles3' - Deprecated. Use system_gles2 instead.
+ # Use the system implementation of EGL + GLES3. The
# headers and libraries must be on the system include and
# link paths.
# 'system_gles2' - Use the system implementation of EGL + GLES2. The
@@ -208,7 +209,7 @@
['host_os=="linux"', {
'conditions': [
['target_arch=="arm" or target_arch=="x86" or target_arch=="mips" or \
- target_arch=="mipsel" or target_arch=="ppc"', {
+ target_arch=="mipsel" or target_arch=="ppc"', {
# All the 32 bit CPU architectures v8 supports.
'compiler_flags_cc_host%': [
'-m32',
diff --git a/src/starboard/build/config/base.gni b/src/starboard/build/config/base.gni
index 41e0b08..77bfda2 100644
--- a/src/starboard/build/config/base.gni
+++ b/src/starboard/build/config/base.gni
@@ -36,7 +36,8 @@
# The source of EGL and GLES headers and libraries.
# Valid values (case and everything sensitive!):
# "none" - No EGL + GLES implementation is available on this platform.
-# "system_gles3" - Use the system implementation of EGL + GLES3. The
+# "system_gles3" - Deprecated. Use system_gles2 instead.
+# Use the system implementation of EGL + GLES3. The
# headers and libraries must be on the system include and
# link paths.
# "system_gles2" - Use the system implementation of EGL + GLES2. The
diff --git a/src/starboard/build/platform_configuration.py b/src/starboard/build/platform_configuration.py
index 80f7305..2d53f61 100644
--- a/src/starboard/build/platform_configuration.py
+++ b/src/starboard/build/platform_configuration.py
@@ -256,7 +256,6 @@
# V8 are supported. Note that V8 can only be used on platforms that
# support JIT.
'javascript_engine': 'v8',
-
'sabi_json_path': self.GetPathToSabiJsonFile(),
# TODO: Remove these compatibility variables.
@@ -352,8 +351,11 @@
A list of strings of test target names.
"""
tests = [
+ 'elf_loader_test',
+ 'installation_manager_test',
'nplb',
'nplb_blitter_pixel_tests',
+ 'nplb_evergreen_compat_tests',
'player_filter_tests',
'starboard_platform_tests',
]
diff --git a/src/starboard/common/README.md b/src/starboard/common/README.md
new file mode 100644
index 0000000..61772a4
--- /dev/null
+++ b/src/starboard/common/README.md
@@ -0,0 +1,9 @@
+# Starboard Common Library
+Shared library code of C++ helper classes on top of the C Starboard APIs.
+A good example is the `Socket` class built on top of the `SbSocket` API. The
+class provides RAII-style mechanism to manage resources.
+
+## Intended Use
+The library is intended to be used by both Starboard and Cobalt layers.
+
+
diff --git a/src/starboard/common/common.gyp b/src/starboard/common/common.gyp
index 3195314..3b3c0b8 100644
--- a/src/starboard/common/common.gyp
+++ b/src/starboard/common/common.gyp
@@ -28,6 +28,8 @@
'common.cc',
'condition_variable.cc',
'condition_variable.h',
+ 'configuration_defaults.cc',
+ 'configuration_defaults.h',
'flat_map.h',
'locked_ptr.h',
'log.cc',
diff --git a/src/starboard/common/configuration_defaults.cc b/src/starboard/common/configuration_defaults.cc
new file mode 100644
index 0000000..6dbeb7b
--- /dev/null
+++ b/src/starboard/common/configuration_defaults.cc
@@ -0,0 +1,109 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/common/configuration_defaults.h"
+
+namespace starboard {
+namespace common {
+
+const char* CobaltUserOnExitStrategyDefault() {
+ return "stop";
+}
+
+bool CobaltRenderDirtyRegionOnlyDefault() {
+ return false;
+}
+
+int CobaltEglSwapIntervalDefault() {
+ return 1;
+}
+
+const char* CobaltFallbackSplashScreenUrlDefault() {
+ return "none";
+}
+
+bool CobaltEnableQuicDefault() {
+ return true;
+}
+
+int CobaltSkiaCacheSizeInBytesDefault() {
+ return 4 * 1024 * 1024;
+}
+
+int CobaltOffscreenTargetCacheSizeInBytesDefault() {
+ return -1;
+}
+
+int CobaltEncodedImageCacheSizeInBytesDefault() {
+ return 1024 * 1024;
+}
+
+int CobaltImageCacheSizeInBytesDefault() {
+ return -1;
+}
+
+int CobaltLocalTypefaceCacheSizeInBytesDefault() {
+ return 16 * 1024 * 1024;
+}
+
+int CobaltRemoteTypefaceCacheSizeInBytesDefault() {
+ return 4 * 1024 * 1024;
+}
+
+int CobaltMeshCacheSizeInBytesDefault() {
+ return 1024 * 1024;
+}
+
+int CobaltSoftwareSurfaceCacheSizeInBytesDefault() {
+ return 8 * 1024 * 1024;
+}
+
+float CobaltImageCacheCapacityMultiplierWhenPlayingVideoDefault() {
+ return 1.0f;
+}
+
+int CobaltSkiaGlyphAtlasWidthDefault() {
+ return -1;
+}
+
+int CobaltSkiaGlyphAtlasHeightDefault() {
+ return -1;
+}
+
+int CobaltJsGarbageCollectionThresholdInBytesDefault() {
+ return 8 * 1024 * 1024;
+}
+
+int CobaltReduceCpuMemoryByDefault() {
+ return -1;
+}
+
+int CobaltReduceGpuMemoryByDefault() {
+ return -1;
+}
+
+bool CobaltGcZealDefault() {
+ return false;
+}
+
+const char* CobaltRasterizerTypeDefault() {
+ return "direct-gles";
+}
+
+bool CobaltEnableJitDefault() {
+ return true;
+}
+
+} // namespace common
+} // namespace starboard
diff --git a/src/starboard/common/configuration_defaults.h b/src/starboard/common/configuration_defaults.h
new file mode 100644
index 0000000..c79c210
--- /dev/null
+++ b/src/starboard/common/configuration_defaults.h
@@ -0,0 +1,68 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_COMMON_CONFIGURATION_DEFAULTS_H_
+#define STARBOARD_COMMON_CONFIGURATION_DEFAULTS_H_
+
+namespace starboard {
+namespace common {
+
+const char* CobaltUserOnExitStrategyDefault();
+
+int CobaltEglSwapIntervalDefault();
+
+bool CobaltRenderDirtyRegionOnlyDefault();
+
+const char* CobaltFallbackSplashScreenUrlDefault();
+
+bool CobaltEnableQuicDefault();
+
+int CobaltSkiaCacheSizeInBytesDefault();
+
+int CobaltOffscreenTargetCacheSizeInBytesDefault();
+
+int CobaltEncodedImageCacheSizeInBytesDefault();
+
+int CobaltImageCacheSizeInBytesDefault();
+
+int CobaltLocalTypefaceCacheSizeInBytesDefault();
+
+int CobaltRemoteTypefaceCacheSizeInBytesDefault();
+
+int CobaltMeshCacheSizeInBytesDefault();
+
+int CobaltSoftwareSurfaceCacheSizeInBytesDefault();
+
+float CobaltImageCacheCapacityMultiplierWhenPlayingVideoDefault();
+
+int CobaltSkiaGlyphAtlasWidthDefault();
+
+int CobaltSkiaGlyphAtlasHeightDefault();
+
+int CobaltJsGarbageCollectionThresholdInBytesDefault();
+
+int CobaltReduceCpuMemoryByDefault();
+
+int CobaltReduceGpuMemoryByDefault();
+
+bool CobaltGcZealDefault();
+
+const char* CobaltRasterizerTypeDefault();
+
+bool CobaltEnableJitDefault();
+
+} // namespace common
+} // namespace starboard
+
+#endif // STARBOARD_COMMON_CONFIGURATION_DEFAULTS_H_
diff --git a/src/starboard/condition_variable.h b/src/starboard/condition_variable.h
index da9e622..09325e0 100644
--- a/src/starboard/condition_variable.h
+++ b/src/starboard/condition_variable.h
@@ -32,7 +32,7 @@
#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
// Max size of the SbConditionVariable type.
-#define SB_CONDITION_VARIABLE_MAX_SIZE 64
+#define SB_CONDITION_VARIABLE_MAX_SIZE 80
// An opaque handle to a condition variable type with
// reserved memory buffer of size SB_CONDITION_VARIABLE_MAX_SIZE and
diff --git a/src/starboard/configuration.h b/src/starboard/configuration.h
index aa42d5c..d130c45 100644
--- a/src/starboard/configuration.h
+++ b/src/starboard/configuration.h
@@ -38,7 +38,7 @@
// The minimum API version allowed by this version of the Starboard headers,
// inclusive.
-#define SB_MINIMUM_API_VERSION 6
+#define SB_MINIMUM_API_VERSION 10
// The maximum API version allowed by this version of the Starboard headers,
// inclusive.
@@ -97,6 +97,10 @@
// interface instead.
#define SB_BLITTER_DEPRECATED_VERSION SB_EXPERIMENTAL_API_VERSION
+// Crypto API is no longer supported on any platform. BoringSSL CPU
+// optimizations are used instead.
+#define SB_CRYPTOAPI_DEPRECATED_VERSION SB_EXPERIMENTAL_API_VERSION
+
// Require the captions API.
// The system must implement the captions functions in
// `starboard/accessibility.h` or use the provided stub implementations.
@@ -262,6 +266,28 @@
// Add link register to SbThreadContext.
#define SB_THREAD_CONTEXT_LINK_REGISTER_VERSION SB_EXPERIMENTAL_API_VERSION
+
+// Make GYP configuration variables cobalt extensions instead.
+// This change moves all of the GYP configuration variables to be members of
+// the struct declared in "cobalt/extension/configuration.h". All members are
+// function pointers that can be set for each platform, otherwise defaults
+// will be used. These can be referenced through functions declared in
+// "cobalt/configuration/configuration.h", which will use the extension API if
+// available, but will otherwise fall back onto default values.
+#define SB_FEATURE_GYP_CONFIGURATION_VERSION SB_EXPERIMENTAL_API_VERSION
+
+// Add the PCLMULQDQ instruction feature to the Starboard CPU features interface
+// for x86 architectures.
+#define SB_CPU_FEATURE_PCLMULQDQ SB_EXPERIMENTAL_API_VERSION
+
+// |content_type| is added to SbMediaIsVideoSupported() and
+// SbMediaIsAudioSupported().
+#define SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION \
+ SB_EXPERIMENTAL_API_VERSION
+
+// Deprecate support for gles3 features.
+#define SB_GLES3_DEPRECATED_VERSION SB_EXPERIMENTAL_API_VERSION
+
// --- Release Candidate Feature Defines -------------------------------------
// --- Common Detected Features ----------------------------------------------
@@ -337,7 +363,7 @@
TypeName(const TypeName&) = delete; \
void operator=(const TypeName&) = delete
-// An enumeration of values for the SB_PREFERRED_RGBA_BYTE_ORDER configuration
+// An enumeration of values for the kSbPreferredByteOrder configuration
// variable. Setting this up properly means avoiding slow color swizzles when
// passing pixel data from one library to another. Note that these definitions
// are in byte-order and so are endianness-independent.
@@ -545,8 +571,8 @@
#error "Your platform's SB_API_VERSION < SB_MINIMUM_API_VERSION."
#endif
-#if !SB_IS(ARCH_ARM) && !SB_IS(ARCH_ARM64) && !SB_IS(ARCH_MIPS) && \
- !SB_IS(ARCH_PPC) && !SB_IS(ARCH_X86) && !SB_IS(ARCH_X64)
+#if !SB_IS(ARCH_ARM) && !SB_IS(ARCH_ARM64) && !SB_IS(ARCH_X86) && \
+ !SB_IS(ARCH_X64)
#error "Your platform doesn't define a known architecture."
#endif
@@ -740,13 +766,6 @@
"starboard/<PLATFORM_PATH>/configuration_constants.cc."
#endif
-#if defined(SB_HAS_AUDIOLESS_VIDEO)
-#error \
- "SB_HAS_AUDIOLESS_VIDEO should not be defined in Starboard " \
-"versions 12 and later. Instead, define kSbHasAudiolessVideo in " \
-"starboard/<PLATFORM_PATH>/configuration_constants.cc."
-#endif
-
#if defined(SB_HAS_MEDIA_WEBM_VP9_SUPPORT)
#error \
"SB_HAS_MEDIA_WEBM_VP9_SUPPORT should not be defined in Starboard " \
@@ -862,6 +881,13 @@
"starboard/<PLATFORM_PATH>/configuration_constants.cc."
#endif
+#if defined(SB_PREFERRED_RGBA_BYTE_ORDER)
+#error \
+ "SB_PREFERRED_RGBA_BYTE_ORDER should not be defined in Starboard " \
+"versions 12 and later. Instead, define kSbPreferredRgbaByteOrder in " \
+"starboard/<PLATFORM_PATH>/configuration_constants.cc."
+#endif
+
#if defined(SB_USER_MAX_SIGNED_IN)
#error \
"SB_USER_MAX_SIGNED_IN should not be defined in Starboard " \
@@ -889,17 +915,11 @@
#endif // defined(SB_HAS_AC3_AUDIO)
#endif // SB_API_VERSION >= 11
-#if SB_API_VERSION >= 10
#if !defined(SB_HAS_ASYNC_AUDIO_FRAMES_REPORTING)
#error \
"Your platform must define SB_HAS_ASYNC_AUDIO_FRAMES_REPORTING in API "\
"version 10 or later."
#endif // !defined(SB_HAS_ASYNC_AUDIO_FRAMES_REPORTING)
-#endif // SB_API_VERSION >= 10
-
-#if SB_API_VERSION >= 10
-#define SB_HAS_AUDIOLESS_VIDEO 1
-#endif
#if !defined(SB_HAS_THREAD_PRIORITY_SUPPORT)
#error "Your platform must define SB_HAS_THREAD_PRIORITY_SUPPORT."
@@ -941,6 +961,20 @@
#error "Your platform must define SB_PATH_SEP_STRING."
#endif
+#if !defined(SB_PREFERRED_RGBA_BYTE_ORDER)
+// Legal values for SB_PREFERRED_RGBA_BYTE_ORDER are defined in this file above
+// as SB_PREFERRED_RGBA_BYTE_ORDER_*.
+// If your platform uses GLES, you should set this to
+// SB_PREFERRED_RGBA_BYTE_ORDER_RGBA.
+#error "Your platform must define SB_PREFERRED_RGBA_BYTE_ORDER."
+#endif
+
+#if SB_PREFERRED_RGBA_BYTE_ORDER != SB_PREFERRED_RGBA_BYTE_ORDER_RGBA && \
+ SB_PREFERRED_RGBA_BYTE_ORDER != SB_PREFERRED_RGBA_BYTE_ORDER_BGRA && \
+ SB_PREFERRED_RGBA_BYTE_ORDER != SB_PREFERRED_RGBA_BYTE_ORDER_ARGB
+#error "SB_PREFERRED_RGBA_BYTE_ORDER has been assigned an invalid value."
+#endif
+
#endif // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
#if (SB_API_VERSION < 12 && !defined(SB_HAS_MICROPHONE))
@@ -959,20 +993,6 @@
#error "New versions of Starboard specify player output mode at runtime."
#endif
-#if !defined(SB_PREFERRED_RGBA_BYTE_ORDER)
-// Legal values for SB_PREFERRED_RGBA_BYTE_ORDER are defined in this file above
-// as SB_PREFERRED_RGBA_BYTE_ORDER_*.
-// If your platform uses GLES, you should set this to
-// SB_PREFERRED_RGBA_BYTE_ORDER_RGBA.
-#error "Your platform must define SB_PREFERRED_RGBA_BYTE_ORDER."
-#endif
-
-#if SB_PREFERRED_RGBA_BYTE_ORDER != SB_PREFERRED_RGBA_BYTE_ORDER_RGBA && \
- SB_PREFERRED_RGBA_BYTE_ORDER != SB_PREFERRED_RGBA_BYTE_ORDER_BGRA && \
- SB_PREFERRED_RGBA_BYTE_ORDER != SB_PREFERRED_RGBA_BYTE_ORDER_ARGB
-#error "SB_PREFERRED_RGBA_BYTE_ORDER has been assigned an invalid value."
-#endif
-
#if !defined(SB_HAS_BILINEAR_FILTERING_SUPPORT)
#error "Your platform must define SB_HAS_BILINEAR_FILTERING_SUPPORT."
#endif
@@ -993,15 +1013,97 @@
#endif
#endif
+#if SB_API_VERSION >= SB_FEATURE_GYP_CONFIGURATION_VERSION
+#if defined(COBALT_MAX_CPU_USAGE_IN_BYTES)
+#error "|max_cobalt_cpu_usage| is deprecated "
+#error "SbSystemGetTotalCPUMemory() instead."
+#endif
+#if defined(COBALT_MAX_GPU_USAGE_IN_BYTES)
+#error "|max_cobalt_gpu_usage| is deprecated. "
+#error "Implement SbSystemGetTotalGPUMemory() instead."
+#endif
+#endif // SB_API_VERSION >= SB_FEATURE_GYP_CONFIGURATION_VERSION
+
+#if defined(COBALT_MEDIA_BUFFER_NON_VIDEO_BUDGET)
+#error "COBALT_MEDIA_BUFFER_NON_VIDEO_BUDGET is deprecated."
+#error "Implement |SbMediaGetAudioBufferBudget| instead."
+#endif // defined(COBALT_MEDIA_BUFFER_NON_VIDEO_BUDGET)
+
+#if defined(COBALT_MEDIA_BUFFER_ALIGNMENT)
+#error "COBALT_MEDIA_BUFFER_ALIGNMENT is deprecated."
+#error "Implement |SbMediaGetBufferAlignment| instead."
+#endif // defined(COBALT_MEDIA_BUFFER_ALIGNMENT
+
+#if defined(COBALT_MEDIA_BUFFER_ALLOCATION_UNIT)
+#error "COBALT_MEDIA_BUFFER_ALLOCATION_UNIT is deprecated."
+#error "Implement |SbMediaGetBufferAllocationUnit| instead."
+#endif // defined(COBALT_MEDIA_BUFFER_ALLOCATION_UNIT
+
+#if defined( \
+ COBALT_MEDIA_SOURCE_GARBAGE_COLLECTION_DURATION_THRESHOLD_IN_SECONDS)
+#error "COBALT_MEDIA_SOURCE_GARBAGE_COLLECTION_DURATION_THRESHOLD_IN_SECONDS"
+#error "is deprecated. Implement"
+#error "|SbMediaGetBufferGarbageCollectionDurationThreshold| instead."
+#endif // defined(COBALT_MEDIA_SOURCE_GARBAGE_COLLECTION_DURATION_THRESHOLD_IN_SECONDS)
+
+#if defined(COBALT_MEDIA_BUFFER_PADDING)
+#error "COBALT_MEDIA_BUFFER_PADDING is deprecated."
+#error "Implement |SbMediaGetBufferPadding| instead."
+#endif // defined(COBALT_MEDIA_BUFFER_PADDING)
+
+#if defined(COBALT_MEDIA_BUFFER_STORAGE_TYPE_FILE)
+#error "COBALT_MEDIA_BUFFER_STORAGE_TYPE_FILE is deprecated."
+#error "Implement |SbMediaGetBufferStorageType| instead."
+#endif // defined(COBALT_MEDIA_BUFFER_STORAGE_TYPE_FILE)
+
+#if defined(COBALT_MEDIA_BUFFER_STORAGE_TYPE_MEMORY)
+#error "COBALT_MEDIA_BUFFER_STORAGE_TYPE_MEMORY is deprecated."
+#error "Implement |SbMediaGetBufferStorageType| instead."
+#endif // defined(COBALT_MEDIA_BUFFER_STORAGE_TYPE_MEMORY)
+
+#if defined(COBALT_MEDIA_BUFFER_INITIAL_CAPACITY)
+#error "COBALT_MEDIA_BUFFER_INITIAL_CAPACITY is deprecated."
+#error "implement |SbMediaGetInitialBufferCapacity| instead."
+#endif // defined(COBALT_MEDIA_BUFFER_INITIAL_CAPACITY)
+
+#if defined(COBALT_MEDIA_BUFFER_MAX_CAPACITY_1080P)
+#error "COBALT_MEDIA_BUFFER_MAX_CAPACITY_1080P is deprecated."
+#error "Implement |SbMediaGetMaxBufferCapacity| instead."
+#endif // defined(COBALT_MEDIA_BUFFER_MAX_CAPACITY_1080P)
+
+#if defined(COBALT_MEDIA_BUFFER_MAX_CAPACITY_4K)
+#error "COBALT_MEDIA_BUFFER_MAX_CAPACITY_4K is deprecated."
+#error "Implement |SbMediaGetMaxBufferCapacity| instead."
+#endif // defined(COBALT_MEDIA_BUFFER_MAX_CAPACITY_4K)
+
+#if defined(COBALT_MEDIA_BUFFER_PROGRESSIVE_BUDGET)
+#error "COBALT_MEDIA_BUFFER_PROGRESSIVE_BUDGET is deprecated."
+#error "Implement |SbMediaGetProgressiveBufferBudget| instead."
+#endif // defined(COBALT_MEDIA_BUFFER_PROGRESSIVE_BUDGET)
+
+#if defined(COBALT_MEDIA_BUFFER_VIDEO_BUDGET_1080P)
+#error "COBALT_MEDIA_BUFFER_VIDEO_BUDGET_1080P is deprecated."
+#error "Implement |SbMediaGetVideoBufferBudget| instead."
+#endif // defined(COBALT_MEDIA_BUFFER_VIDEO_BUDGET_1080P)
+
+#if defined(COBALT_MEDIA_BUFFER_VIDEO_BUDGET_4K)
+#error "COBALT_MEDIA_BUFFER_VIDEO_BUDGET_4K is deprecated."
+#error "Implement |SbMediaGetVideoBufferBudget| instead."
+#endif // defined(COBALT_MEDIA_BUFFER_VIDEO_BUDGET_4K)
+
+#if defined(COBALT_MEDIA_BUFFER_POOL_ALLOCATE_ON_DEMAND)
+#error "COBALT_MEDIA_BUFFER_POOL_ALLOCATE_ON_DEMAND is deprecated."
+#error "Implement |SbMediaIsBufferPoolAllocateOnDemand| instead."
+#endif // defined(COBALT_MEDIA_BUFFER_POOL_ALLOCATE_ON_DEMAND)
+
#if defined(SB_MEDIA_SOURCE_BUFFER_STREAM_AUDIO_MEMORY_LIMIT)
#error "SB_MEDIA_SOURCE_BUFFER_STREAM_AUDIO_MEMORY_LIMIT is deprecated."
-#error "Use gyp variable |cobalt_media_buffer_non_video_budget| instead."
+#error "Implement function |SbMediaGetAudioBufferBudget| instead."
#endif // defined(SB_MEDIA_SOURCE_BUFFER_STREAM_AUDIO_MEMORY_LIMIT)
#if defined(SB_MEDIA_SOURCE_BUFFER_STREAM_VIDEO_MEMORY_LIMIT)
#error "SB_MEDIA_SOURCE_BUFFER_STREAM_VIDEO_MEMORY_LIMIT is deprecated."
-#error "Use gyp variable |cobalt_media_buffer_video_budget_1080p| instead."
-#error "Use gyp variable |cobalt_media_buffer_video_budget_4k| instead."
+#error "Implement function |SbMediaGetVideoBufferBudget| instead."
#endif // defined(SB_MEDIA_SOURCE_BUFFER_STREAM_VIDEO_MEMORY_LIMIT)
#if defined(SB_MEDIA_MAIN_BUFFER_BUDGET)
@@ -1012,6 +1114,10 @@
#error "SB_MEDIA_GPU_BUFFER_BUDGET is deprecated."
#endif // defined(SB_MEDIA_GPU_BUFFER_BUDGET)
+#if defined(SB_HAS_AUDIOLESS_VIDEO)
+#error "SB_HAS_AUDIOLESS_VIDEO is deprecated."
+#endif // defined(SB_HAS_AUDIOLESS_VIDEO)
+
#if SB_API_VERSION >= 11
#if defined(SB_HAS_MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
#if !SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
@@ -1024,15 +1130,9 @@
#endif // defined(SB_HAS_MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
#endif // SB_API_VERSION >= 11
-#if SB_API_VERSION >= 10
#if defined(SB_HAS_DRM_SESSION_CLOSED)
-#if !SB_HAS(DRM_SESSION_CLOSED)
-#error "SB_HAS_DRM_SESSION_CLOSED is required in this API version."
-#endif // !SB_HAS(DRM_SESSION_CLOSED)
-#else // defined(SB_HAS_DRM_SESSION_CLOSED)
-#define SB_HAS_DRM_SESSION_CLOSED 1
+#error "SB_HAS_DRM_SESSION_CLOSED should not be defined for API version >= 10."
#endif // defined(SB_HAS_DRM_SESSION_CLOSED)
-#endif // SB_API_VERSION >= 10
#if SB_API_VERSION < SB_SPEECH_RECOGNIZER_IS_REQUIRED && SB_API_VERSION >= 5
#if !defined(SB_HAS_SPEECH_RECOGNIZER)
@@ -1053,23 +1153,13 @@
#error "SB_HAS_ON_SCREEN_KEYBOARD not supported in this API version."
#endif
-#if SB_HAS(CAPTIONS) && (SB_API_VERSION < 10)
-#error "SB_HAS_CAPTIONS not supported in this API version."
-#endif
+#if defined(SB_HAS_PLAYER_FILTER_TESTS)
+#error "SB_HAS_PLAYER_FILTER_TESTS should not be defined in API versions >= 10."
+#endif // defined(SB_HAS_PLAYER_FILTER_TESTS)
-#if SB_API_VERSION >= 10
-#define SB_HAS_PLAYER_FILTER_TESTS 1
-#endif
-
-#if SB_API_VERSION >= 10
-#define SB_HAS_PLAYER_ERROR_MESSAGE 1
-#endif
-
-#if SB_API_VERSION < 10
-#if !SB_HAS_QUIRK(SUPPORT_INT16_AUDIO_SAMPLES)
-#define SB_HAS_QUIRK_SUPPORT_INT16_AUDIO_SAMPLES 1
-#endif // !SB_HAS_QUIRK(SUPPORT_INT16_AUDIO_SAMPLES)
-#endif // SB_API_VERSION < 10
+#if defined(SB_HAS_PLAYER_ERROR_MESSAGE)
+#error "SB_HAS_PLAYER_ERROR_MESSAGE should not be defined in API versions >= 10."
+#endif // defined(SB_HAS_PLAYER_ERROR_MESSAGE)
#if SB_API_VERSION >= \
SB_PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT_VERSION
diff --git a/src/starboard/configuration_constants.h b/src/starboard/configuration_constants.h
index c88e127..8e6c27d 100644
--- a/src/starboard/configuration_constants.h
+++ b/src/starboard/configuration_constants.h
@@ -64,9 +64,6 @@
// Specifies whether this platform updates audio frames asynchronously.
extern const bool kSbHasAsyncAudioFramesReporting;
-// Allow playing audioless video.
-extern const bool kSbHasAudiolessVideo;
-
// Specifies whether this platform has webm/vp9 support. This should be set to
// non-zero on platforms with webm/vp9 support.
extern const bool kSbHasMediaWebmVp9Support;
@@ -142,6 +139,11 @@
// like mutexes, so we want to keep this manageable.
extern const uint32_t kSbMaxThreads;
+// Specifies the preferred byte order of color channels in a pixel. Refer to
+// starboard/configuration.h for the possible values. EGL/GLES platforms should
+// generally prefer a byte order of RGBA, regardless of endianness.
+extern const int kSbPreferredRgbaByteOrder;
+
// The current platform's search path component separator character. When
// specifying an ordered list of absolute paths of directories to search for a
// given reason, this is the character that appears between entries. For
diff --git a/src/starboard/contrib/creator/ci20x11/system_get_property.cc b/src/starboard/contrib/creator/ci20x11/system_get_property.cc
index 61fc987..43dabb3 100644
--- a/src/starboard/contrib/creator/ci20x11/system_get_property.cc
+++ b/src/starboard/contrib/creator/ci20x11/system_get_property.cc
@@ -36,52 +36,6 @@
return true;
}
-#if SB_API_VERSION < 10
-
-bool GetPlatformUuid(char* out_value, int value_length) {
- struct ifreq interface;
- struct ifconf config;
- char buf[1024];
-
- int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
- if (fd == -1) {
- return false;
- }
- config.ifc_len = sizeof(buf);
- config.ifc_buf = buf;
- int result = ioctl(fd, SIOCGIFCONF, &config);
- if (result == -1) {
- return false;
- }
-
- struct ifreq* cur_interface = config.ifc_req;
- const struct ifreq* const end =
- cur_interface + (config.ifc_len / sizeof(struct ifreq));
-
- for (; cur_interface != end; ++cur_interface) {
- SbStringCopy(interface.ifr_name, cur_interface->ifr_name,
- sizeof(cur_interface->ifr_name));
- if (ioctl(fd, SIOCGIFFLAGS, &interface) == -1) {
- continue;
- }
- if (interface.ifr_flags & IFF_LOOPBACK) {
- continue;
- }
- if (ioctl(fd, SIOCGIFHWADDR, &interface) == -1) {
- continue;
- }
- SbStringFormatF(
- out_value, value_length, "%x:%x:%x:%x:%x:%x",
- interface.ifr_addr.sa_data[0], interface.ifr_addr.sa_data[1],
- interface.ifr_addr.sa_data[2], interface.ifr_addr.sa_data[3],
- interface.ifr_addr.sa_data[4], interface.ifr_addr.sa_data[5]);
- return true;
- }
- return false;
-}
-
-#endif // SB_API_VERSION < 10
-
} // namespace
bool SbSystemGetProperty(SbSystemPropertyId property_id,
@@ -111,11 +65,6 @@
case kSbSystemPropertyPlatformName:
return CopyStringAndTestIfSuccess(out_value, value_length, kPlatformName);
-#if SB_API_VERSION < 10
- case kSbSystemPropertyPlatformUuid:
- return GetPlatformUuid(out_value, value_length);
-#endif // SB_API_VERSION < 10
-
default:
SB_DLOG(WARNING) << __FUNCTION__
<< ": Unrecognized property: " << property_id;
diff --git a/src/starboard/contrib/creator/shared/starboard_platform.gypi b/src/starboard/contrib/creator/shared/starboard_platform.gypi
index a7f092d..b63ce99 100644
--- a/src/starboard/contrib/creator/shared/starboard_platform.gypi
+++ b/src/starboard/contrib/creator/shared/starboard_platform.gypi
@@ -264,13 +264,11 @@
'<(DEPTH)/starboard/shared/starboard/player/player_create.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_destroy.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_get_current_frame.cc',
- '<(DEPTH)/starboard/shared/starboard/player/player_get_info.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_get_info2.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_get_maximum_number_of_samples_per_write.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_output_mode_supported.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_internal.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_internal.h',
- '<(DEPTH)/starboard/shared/starboard/player/player_seek.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_seek2.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_set_bounds.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_set_playback_rate.cc',
@@ -278,7 +276,6 @@
'<(DEPTH)/starboard/shared/starboard/player/player_worker.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_worker.h',
'<(DEPTH)/starboard/shared/starboard/player/player_write_end_of_stream.cc',
- '<(DEPTH)/starboard/shared/starboard/player/player_write_sample.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_write_sample2.cc',
'<(DEPTH)/starboard/shared/starboard/queue_application.cc',
'<(DEPTH)/starboard/shared/starboard/string_concat.cc',
diff --git a/src/starboard/contrib/linux/x64wl/system_get_property.cc b/src/starboard/contrib/linux/x64wl/system_get_property.cc
index 9c4a529..552dc5a 100644
--- a/src/starboard/contrib/linux/x64wl/system_get_property.cc
+++ b/src/starboard/contrib/linux/x64wl/system_get_property.cc
@@ -36,52 +36,6 @@
return true;
}
-#if SB_API_VERSION < 10
-
-bool GetPlatformUuid(char* out_value, int value_length) {
- struct ifreq interface;
- struct ifconf config;
- char buf[1024];
-
- int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
- if (fd == -1) {
- return false;
- }
- config.ifc_len = sizeof(buf);
- config.ifc_buf = buf;
- int result = ioctl(fd, SIOCGIFCONF, &config);
- if (result == -1) {
- return false;
- }
-
- struct ifreq* cur_interface = config.ifc_req;
- const struct ifreq* const end =
- cur_interface + (config.ifc_len / sizeof(struct ifreq));
-
- for (; cur_interface != end; ++cur_interface) {
- SbStringCopy(interface.ifr_name, cur_interface->ifr_name,
- sizeof(cur_interface->ifr_name));
- if (ioctl(fd, SIOCGIFFLAGS, &interface) == -1) {
- continue;
- }
- if (interface.ifr_flags & IFF_LOOPBACK) {
- continue;
- }
- if (ioctl(fd, SIOCGIFHWADDR, &interface) == -1) {
- continue;
- }
- SbStringFormatF(
- out_value, value_length, "%x:%x:%x:%x:%x:%x",
- interface.ifr_addr.sa_data[0], interface.ifr_addr.sa_data[1],
- interface.ifr_addr.sa_data[2], interface.ifr_addr.sa_data[3],
- interface.ifr_addr.sa_data[4], interface.ifr_addr.sa_data[5]);
- return true;
- }
- return false;
-}
-
-#endif // SB_API_VERSION < 10
-
} // namespace
bool SbSystemGetProperty(SbSystemPropertyId property_id,
@@ -111,11 +65,6 @@
case kSbSystemPropertyPlatformName:
return CopyStringAndTestIfSuccess(out_value, value_length, kPlatformName);
-#if SB_API_VERSION < 10
- case kSbSystemPropertyPlatformUuid:
- return GetPlatformUuid(out_value, value_length);
-#endif // SB_API_VERSION < 10
-
default:
SB_DLOG(WARNING) << __FUNCTION__
<< ": Unrecognized property: " << property_id;
diff --git a/src/starboard/contrib/tizen/shared/starboard_platform.gypi b/src/starboard/contrib/tizen/shared/starboard_platform.gypi
index 650d7f7..2697fe2 100644
--- a/src/starboard/contrib/tizen/shared/starboard_platform.gypi
+++ b/src/starboard/contrib/tizen/shared/starboard_platform.gypi
@@ -306,13 +306,11 @@
'<(DEPTH)/starboard/shared/starboard/player/player_create.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_destroy.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_get_current_frame.cc',
- '<(DEPTH)/starboard/shared/starboard/player/player_get_info.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_get_info2.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_get_maximum_number_of_samples_per_write.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_internal.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_internal.h',
'<(DEPTH)/starboard/shared/starboard/player/player_output_mode_supported.cc',
- '<(DEPTH)/starboard/shared/starboard/player/player_seek.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_seek2.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_set_bounds.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_set_playback_rate.cc',
@@ -320,7 +318,6 @@
'<(DEPTH)/starboard/shared/starboard/player/player_worker.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_worker.h',
'<(DEPTH)/starboard/shared/starboard/player/player_write_end_of_stream.cc',
- '<(DEPTH)/starboard/shared/starboard/player/player_write_sample.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_write_sample2.cc',
'<(DEPTH)/starboard/shared/starboard/queue_application.cc',
'<(DEPTH)/starboard/shared/starboard/string_concat.cc',
diff --git a/src/starboard/contrib/tizen/shared/system_has_capability.cc b/src/starboard/contrib/tizen/shared/system_has_capability.cc
index 9958b10..176bf84 100644
--- a/src/starboard/contrib/tizen/shared/system_has_capability.cc
+++ b/src/starboard/contrib/tizen/shared/system_has_capability.cc
@@ -22,10 +22,8 @@
return false;
case kSbSystemCapabilityCanQueryGPUMemoryStats:
return false;
-#if SB_API_VERSION >= 10
case kSbSystemCapabilitySetsInputTimestamp:
return true;
-#endif
}
SB_DLOG(WARNING) << "Unrecognized capability: " << capability_id;
diff --git a/src/starboard/cpu_features.h b/src/starboard/cpu_features.h
index 166bd74..c204ac4 100644
--- a/src/starboard/cpu_features.h
+++ b/src/starboard/cpu_features.h
@@ -192,6 +192,10 @@
// SSE3 extensions.
bool has_sse3;
+#if defined(SB_CPU_FEATURE_PCLMULQDQ)
+ // PCLMULQDQ instruction.
+ bool has_pclmulqdq;
+#endif // defined(SB_CPU_FEATURE_PCLMULQDQ)
// Supplemental SSE3 extensions.
bool has_ssse3;
// SSE-4.1 extensions.
diff --git a/src/starboard/cryptography.h b/src/starboard/cryptography.h
index 2ae2fea..3edc4ba 100644
--- a/src/starboard/cryptography.h
+++ b/src/starboard/cryptography.h
@@ -54,6 +54,10 @@
#include "starboard/export.h"
#include "starboard/types.h"
+#if SB_API_VERSION >= SB_CRYPTOAPI_DEPRECATED_VERSION
+#error "Starboard Crypto API is deprecated"
+#else
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -149,6 +153,8 @@
// |initialization_vector_size|: The size, in bytes, of the IV.
// |key|: The key to use for this transformation.
// |key_size|: The size, in bytes, of the key.
+//
+// presubmit: allow sb_export mismatch
SB_EXPORT SbCryptographyTransformer
SbCryptographyCreateTransformer(const char* algorithm,
int block_size_bits,
@@ -160,6 +166,8 @@
int key_size);
// Destroys the given |transformer| instance.
+//
+// presubmit: allow sb_export mismatch
SB_EXPORT void SbCryptographyDestroyTransformer(
SbCryptographyTransformer transformer);
@@ -177,6 +185,8 @@
// |out_data|: A buffer where the transformed data should be placed. Must have
// at least capacity for |in_data_size| bytes. May point to the same memory as
// |in_data|.
+//
+// presubmit: allow sb_export mismatch
SB_EXPORT int SbCryptographyTransform(
SbCryptographyTransformer transformer,
const void* in_data,
@@ -187,6 +197,8 @@
// internally-set IV. The block cipher mode algorithm will update the IV
// appropriately after every block, so this is not necessary unless the stream
// is discontiguous in some way. This happens with AES-GCM in TLS.
+//
+// presubmit: allow sb_export mismatch
SB_EXPORT void SbCryptographySetInitializationVector(
SbCryptographyTransformer transformer,
const void* initialization_vector,
@@ -196,6 +208,8 @@
// modes that support it (GCM). Returns whether the data was successfully
// set. This can fail if the chaining mode doesn't support AAD, if the
// parameters are invalid, or if the internal state is invalid for setting AAD.
+//
+// presubmit: allow sb_export mismatch
SB_EXPORT bool SbCryptographySetAuthenticatedData(
SbCryptographyTransformer transformer,
const void* data,
@@ -205,6 +219,8 @@
// |out_tag_size| bytes of it in |out_tag|. Returns whether it was able to get
// the tag, which mainly has to do with whether it is compatible with the
// current block cipher mode.
+//
+// presubmit: allow sb_export mismatch
SB_EXPORT bool SbCryptographyGetTag(
SbCryptographyTransformer transformer,
void* out_tag,
@@ -214,4 +230,6 @@
} // extern "C"
#endif
+#endif // SB_CRYPTOAPI_DEPRECATED_VERSION
+
#endif // STARBOARD_CRYPTOGRAPHY_H_
diff --git a/src/starboard/decode_target.h b/src/starboard/decode_target.h
index 3daddc5..cb7576e 100644
--- a/src/starboard/decode_target.h
+++ b/src/starboard/decode_target.h
@@ -135,11 +135,9 @@
// A decoder target format consisting of Y, U, and V planes, in that order.
kSbDecodeTargetFormat3PlaneYUVI420,
-#if SB_API_VERSION >= 10
// A decoder target format consisting of 10bit Y, U, and V planes, in that
// order.
kSbDecodeTargetFormat3Plane10BitYUVI420,
-#endif
// A decoder target format consisting of a single plane with pixels layed out
// in the format UYVY. Since there are two Y values per sample, but only one
@@ -353,9 +351,7 @@
return 1;
case kSbDecodeTargetFormat2PlaneYUVNV12:
return 2;
-#if SB_API_VERSION >= 10
case kSbDecodeTargetFormat3Plane10BitYUVI420:
-#endif
case kSbDecodeTargetFormat3PlaneYUVI420:
return 3;
default:
diff --git a/src/starboard/drm.h b/src/starboard/drm.h
index 43c4332..98e9b15 100644
--- a/src/starboard/drm.h
+++ b/src/starboard/drm.h
@@ -135,7 +135,6 @@
// SbDrmGenerateSessionUpdateRequest() was called on. |context| will be the same
// context that was passed into the call to SbDrmCreateSystem().
//
-#if SB_API_VERSION >= 10
// |status| is the status of the session request.
//
// |type| is the status of the session request.
@@ -144,13 +143,14 @@
// |kSbDrmStatusSuccess| to provide more details about the error. It may be
// NULL if |status| is |kSbDrmStatusSuccess| or if no error message can be
// provided.
-#endif // SB_API_VERSION >= 10
// |ticket| will be the same ticket that was passed to
// SbDrmGenerateSessionUpdateRequest() or |kSbDrmTicketInvalid| if the update
// request was generated by the DRM system.
//
-// |session_id| can be NULL if there was an error generating the request.
-#if SB_API_VERSION >= 10
+// |session_id| cannot be NULL when |ticket| is |kSbDrmTicketInvalid|, even when
+// there was an error generating the request. This allows Cobalt to find and
+// reject the correct Promise corresponding to the associated
+// SbDrmGenerateSessionUpdateRequest().
typedef void (*SbDrmSessionUpdateRequestFunc)(SbDrmSystem drm_system,
void* context,
int ticket,
@@ -162,16 +162,6 @@
const void* content,
int content_size,
const char* url);
-#else // SB_API_VERSION >= 10
-typedef void (*SbDrmSessionUpdateRequestFunc)(SbDrmSystem drm_system,
- void* context,
- int ticket,
- const void* session_id,
- int session_id_size,
- const void* content,
- int content_size,
- const char* url);
-#endif // SB_API_VERSION >= 10
// A callback for notifications that a session has been added, and subsequent
// encrypted samples are actively ready to be decoded. |drm_system| will be the
@@ -180,16 +170,13 @@
//
// |ticket| will be the same ticket that was passed to SbDrmUpdateSession().
//
-#if SB_API_VERSION >= 10
// |status| is the status of the session request.
//
// |error_message| may contain an optional error message when |status| isn't
// |kSbDrmStatusSuccess| to provide more details about the error. It may be
// NULL if |status| is |kSbDrmStatusSuccess| or if no error message can be
// provided.
-#endif // SB_API_VERSION >= 10
// |succeeded| is whether the session was successfully updated or not.
-#if SB_API_VERSION >= 10
typedef void (*SbDrmSessionUpdatedFunc)(SbDrmSystem drm_system,
void* context,
int ticket,
@@ -197,14 +184,6 @@
const char* error_message,
const void* session_id,
int session_id_size);
-#else // SB_API_VERSION >= 10
-typedef void (*SbDrmSessionUpdatedFunc)(SbDrmSystem drm_system,
- void* context,
- int ticket,
- const void* session_id,
- int session_id_size,
- bool succeeded);
-#endif // SB_API_VERSION >= 10
// A callback for notifications that the status of one or more keys in a session
// has been changed. All keys of the session and their new status will be
@@ -219,15 +198,12 @@
const SbDrmKeyStatus* key_statuses);
// A callback for signalling that a session has been closed by the SbDrmSystem
-#if SB_HAS(DRM_SESSION_CLOSED)
typedef void (*SbDrmSessionClosedFunc)(
SbDrmSystem drm_system,
void* context,
const void* session_id,
int session_id_size);
-#endif // SB_HAS(DRM_SESSION_CLOSED))
-#if SB_API_VERSION >= 10
// A callback to notify the caller of SbDrmUpdateServerCertificate() whether the
// update has been successfully updated or not.
typedef void (*SbDrmServerCertificateUpdatedFunc)(SbDrmSystem drm_system,
@@ -235,7 +211,6 @@
int ticket,
SbDrmStatus status,
const char* error_message);
-#endif // SB_API_VERSION >= 10
// --- Constants -------------------------------------------------------------
@@ -284,14 +259,10 @@
// function returns.
// |session_closed_callback|: A function that can be called to indicate that a
// session has closed.
-#if SB_API_VERSION >= 10
// If |NULL| is passed for any of the callbacks (|update_request_callback|,
// |session_updated_callback|, |key_statuses_changed_callback|,
// |server_certificate_updated_callback|, or |session_closed_callback|), then
// |kSbDrmSystemInvalid| must be returned.
-#endif // SB_API_VERSION >= 10
-
-#if SB_API_VERSION >= 10
SB_EXPORT SbDrmSystem SbDrmCreateSystem(
const char* key_system,
@@ -302,27 +273,6 @@
SbDrmServerCertificateUpdatedFunc server_certificate_updated_callback,
SbDrmSessionClosedFunc session_closed_callback);
-#elif SB_HAS(DRM_SESSION_CLOSED)
-
-SB_EXPORT SbDrmSystem SbDrmCreateSystem(
- const char* key_system,
- void* context,
- SbDrmSessionUpdateRequestFunc update_request_callback,
- SbDrmSessionUpdatedFunc session_updated_callback,
- SbDrmSessionKeyStatusesChangedFunc key_statuses_changed_callback,
- SbDrmSessionClosedFunc session_closed_callback);
-
-#else // SB_HAS(DRM_SESSION_CLOSED)
-
-SB_EXPORT SbDrmSystem SbDrmCreateSystem(
- const char* key_system,
- void* context,
- SbDrmSessionUpdateRequestFunc update_request_callback,
- SbDrmSessionUpdatedFunc session_updated_callback,
- SbDrmSessionKeyStatusesChangedFunc key_statuses_changed_callback);
-
-#endif // SB_HAS(DRM_SESSION_CLOSED)
-
// Asynchronously generates a session update request payload for
// |initialization_data|, of |initialization_data_size|, in case sensitive
// |type|, extracted from the media stream, in |drm_system|'s key system.
@@ -389,8 +339,6 @@
const void* session_id,
int session_id_size);
-#if SB_API_VERSION >= 10
-
// Returns true if server certificate of |drm_system| can be updated via
// SbDrmUpdateServerCertificate(). The return value should remain the same
// during the life time of |drm_system|.
@@ -418,8 +366,6 @@
const void* certificate,
int certificate_size);
-#endif // SB_API_VERSION >= 10
-
// Destroys |drm_system|, which implicitly removes all keys installed in it and
// invalidates all outstanding session update requests. A DRM system cannot be
// destroyed unless any associated SbPlayer or SbDecoder has first been
diff --git a/src/starboard/egl_and_gles/egl_and_gles_angle.gyp b/src/starboard/egl_and_gles/egl_and_gles_angle.gyp
index 7ad57ae..8fed38d 100644
--- a/src/starboard/egl_and_gles/egl_and_gles_angle.gyp
+++ b/src/starboard/egl_and_gles/egl_and_gles_angle.gyp
@@ -36,7 +36,6 @@
['target_os=="win" and enable_d3d11_feature_level_11==1', {
'direct_dependent_settings': {
'defines': [
- 'GLES3_SUPPORTED',
'GL_GLEXT_PROTOTYPES',
],
},
diff --git a/src/starboard/egl_and_gles/egl_and_gles_glimp.gyp b/src/starboard/egl_and_gles/egl_and_gles_glimp.gyp
index 7c98fee..55dd8cd 100644
--- a/src/starboard/egl_and_gles/egl_and_gles_glimp.gyp
+++ b/src/starboard/egl_and_gles/egl_and_gles_glimp.gyp
@@ -26,7 +26,6 @@
],
'direct_dependent_settings': {
'defines': [
- 'GLES3_SUPPORTED',
'GL_GLEXT_PROTOTYPES',
],
},
diff --git a/src/starboard/egl_and_gles/egl_and_gles_system_gles3.gyp b/src/starboard/egl_and_gles/egl_and_gles_system_gles3.gyp
index 491b829..01ddbca 100644
--- a/src/starboard/egl_and_gles/egl_and_gles_system_gles3.gyp
+++ b/src/starboard/egl_and_gles/egl_and_gles_system_gles3.gyp
@@ -15,16 +15,10 @@
{
'targets': [
{
+ # Though we support as a valid gl_type option, it will use neither GLES3
+ # features nor GLES3 egl context currently.
'target_name': 'egl_and_gles_implementation',
'type': 'none',
-
- # Use the system-provided implementation of GLES3.
-
- 'direct_dependent_settings': {
- 'defines': [
- 'GLES3_SUPPORTED',
- ],
- },
},
],
}
diff --git a/src/starboard/elf_loader/dynamic_section.cc b/src/starboard/elf_loader/dynamic_section.cc
new file mode 100644
index 0000000..d582124
--- /dev/null
+++ b/src/starboard/elf_loader/dynamic_section.cc
@@ -0,0 +1,193 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/elf_loader/dynamic_section.h"
+
+#include "starboard/common/log.h"
+#include "starboard/elf_loader/log.h"
+
+namespace starboard {
+namespace elf_loader {
+
+DynamicSection::DynamicSection(Addr base_memory_address,
+ Dyn* dynamic,
+ size_t dynamic_count,
+ Word dynamic_flags)
+ : base_memory_address_(base_memory_address),
+ soname_(NULL),
+ dynamic_(dynamic),
+ dynamic_count_(dynamic_count),
+ dynamic_flags_(dynamic_flags),
+ has_DT_SYMBOLIC_(false),
+ symbol_table_(NULL),
+ string_table_(NULL),
+ preinit_array_(NULL),
+ preinit_array_count_(0),
+ init_array_(NULL),
+ init_array_count_(0),
+ fini_array_(NULL),
+ fini_array_count_(0),
+ init_func_(NULL),
+ fini_func_(NULL) {}
+
+bool DynamicSection::InitDynamicSection() {
+ SB_DLOG(INFO) << "Dynamic section count=" << dynamic_count_;
+ for (int i = 0; i < dynamic_count_; i++) {
+ Addr dyn_value = dynamic_[i].d_un.d_val;
+ uintptr_t dyn_addr = base_memory_address_ + dynamic_[i].d_un.d_ptr;
+ SB_DLOG(INFO) << "Dynamic tag=" << dynamic_[i].d_tag;
+ switch (dynamic_[i].d_tag) {
+ case DT_DEBUG:
+ // TODO: implement.
+ break;
+ case DT_INIT:
+ SB_DLOG(INFO) << " DT_INIT addr=0x" << std::hex << dyn_addr;
+ init_func_ = reinterpret_cast<linker_function_t>(dyn_addr);
+ break;
+ case DT_FINI:
+ SB_DLOG(INFO) << " DT_FINI addr=0x" << std::hex << dyn_addr;
+ fini_func_ = reinterpret_cast<linker_function_t>(dyn_addr);
+ break;
+ case DT_INIT_ARRAY:
+ SB_DLOG(INFO) << " DT_INIT_ARRAY addr=0x" << std::hex << dyn_addr;
+ init_array_ = reinterpret_cast<linker_function_t*>(dyn_addr);
+ break;
+ case DT_INIT_ARRAYSZ:
+ init_array_count_ = dyn_value / sizeof(Addr);
+ SB_DLOG(INFO) << " DT_INIT_ARRAYSZ value=0x" << std::hex << dyn_value
+ << " count=" << std::dec << init_array_count_;
+ break;
+ case DT_FINI_ARRAY:
+ SB_DLOG(INFO) << " DT_FINI_ARRAY addr=0x" << std::hex << dyn_addr;
+ fini_array_ = reinterpret_cast<linker_function_t*>(dyn_addr);
+ break;
+ case DT_FINI_ARRAYSZ:
+ fini_array_count_ = dyn_value / sizeof(Addr);
+ SB_DLOG(INFO) << " DT_FINI_ARRAYSZ value=0x" << std::hex << dyn_value
+ << " count=" << fini_array_count_;
+ break;
+ case DT_PREINIT_ARRAY:
+ SB_DLOG(INFO) << " DT_PREINIT_ARRAY addr=0x" << std::hex << dyn_addr;
+ preinit_array_ = reinterpret_cast<linker_function_t*>(dyn_addr);
+ break;
+ case DT_PREINIT_ARRAYSZ:
+ preinit_array_count_ = dyn_value / sizeof(Addr);
+ SB_DLOG(INFO) << " DT_PREINIT_ARRAYSZ addr=" << dyn_addr
+ << " count=" << preinit_array_count_;
+ break;
+ case DT_SYMBOLIC:
+ SB_DLOG(INFO) << " DT_SYMBOLIC";
+ has_DT_SYMBOLIC_ = true;
+ break;
+ case DT_FLAGS:
+ if (dyn_value & DF_SYMBOLIC)
+ has_DT_SYMBOLIC_ = true;
+ break;
+ case DT_SONAME:
+ soname_ = string_table_ + dyn_value;
+ break;
+ case DT_HASH:
+ SB_DLOG(INFO) << " DT_HASH addr=0x" << std::hex << dyn_addr;
+ elf_hash_.Init(dyn_addr);
+ break;
+ case DT_GNU_HASH:
+ SB_DLOG(INFO) << " DT_GNU_HASH addr=0x" << std::hex << dyn_addr;
+ gnu_hash_.Init(dyn_addr);
+ break;
+ case DT_STRTAB:
+ SB_DLOG(INFO) << " DT_STRTAB addr=0x" << std::hex << dyn_addr;
+ string_table_ = reinterpret_cast<const char*>(dyn_addr);
+ break;
+ case DT_SYMTAB:
+ SB_DLOG(INFO) << " DT_SYMTAB addr=0x" << std::hex << dyn_addr;
+ symbol_table_ = reinterpret_cast<Sym*>(dyn_addr);
+ break;
+ default:
+ break;
+ }
+ }
+ return true;
+}
+
+const Dyn* DynamicSection::GetDynamicTable() {
+ return dynamic_;
+}
+
+size_t DynamicSection::GetDynamicTableSize() {
+ return dynamic_count_;
+}
+
+void DynamicSection::CallConstructors() {
+ CallFunction(init_func_, "DT_INIT");
+ for (size_t n = 0; n < init_array_count_; ++n) {
+ CallFunction(init_array_[n], "DT_INIT_ARRAY");
+ }
+}
+
+void DynamicSection::CallDestructors() {
+ for (size_t n = fini_array_count_; n > 0; --n) {
+ CallFunction(fini_array_[n - 1], "DT_FINI_ARRAY");
+ }
+ CallFunction(fini_func_, "DT_FINI");
+}
+
+void DynamicSection::CallFunction(linker_function_t func,
+ const char* func_type) {
+ uintptr_t func_address = reinterpret_cast<uintptr_t>(func);
+
+ // On some platforms the entries in the array can be 0 or -1,
+ // and should be ignored e.g. Android:
+ // https://android.googlesource.com/platform/bionic/+/android-4.2_r1/linker/README.TXT
+ if (func_address != 0 && func_address != uintptr_t(-1)) {
+ func();
+ }
+}
+
+const Sym* DynamicSection::LookupById(size_t symbol_id) const {
+ // TODO: Calculated the symbol_table size and validation check.
+ return &symbol_table_[symbol_id];
+}
+
+bool DynamicSection::IsWeakById(size_t symbol_id) const {
+ // TODO: Calculated the symbol_table size and validation check.
+ return ELF_ST_BIND(symbol_table_[symbol_id].st_info) == STB_WEAK;
+}
+
+const char* DynamicSection::LookupNameById(size_t symbol_id) const {
+ const Sym* sym = LookupById(symbol_id);
+ // TODO: Confirm that LookupById actually can return NULL.
+ if (!sym)
+ return NULL;
+ return string_table_ + sym->st_name;
+}
+
+const Sym* DynamicSection::LookupByName(const char* symbol_name) const {
+ const Sym* sym =
+ gnu_hash_.IsValid()
+ ? gnu_hash_.LookupByName(symbol_name, symbol_table_, string_table_)
+ : elf_hash_.LookupByName(symbol_name, symbol_table_, string_table_);
+
+ // Ignore undefined symbols or those that are not global or weak definitions.
+ if (!sym || sym->st_shndx == SHN_UNDEF)
+ return NULL;
+
+ uint8_t info = ELF_ST_BIND(sym->st_info);
+ if (info != STB_GLOBAL && info != STB_WEAK)
+ return NULL;
+
+ return sym;
+}
+
+} // namespace elf_loader
+} // namespace starboard
diff --git a/src/starboard/elf_loader/dynamic_section.h b/src/starboard/elf_loader/dynamic_section.h
new file mode 100644
index 0000000..8d22bf1
--- /dev/null
+++ b/src/starboard/elf_loader/dynamic_section.h
@@ -0,0 +1,99 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_ELF_LOADER_DYNAMIC_SECTION_H_
+#define STARBOARD_ELF_LOADER_DYNAMIC_SECTION_H_
+
+#include "starboard/elf_loader/elf.h"
+#include "starboard/elf_loader/elf_hash_table.h"
+#include "starboard/elf_loader/exported_symbols.h"
+#include "starboard/elf_loader/gnu_hash_table.h"
+#include "starboard/elf_loader/program_table.h"
+
+namespace starboard {
+namespace elf_loader {
+
+typedef void (*linker_function_t)();
+
+// class representing the ELF dynamic
+// section with dynamic symbols and a
+// string tables.
+
+class DynamicSection {
+ public:
+ DynamicSection(Addr base_memory_address,
+ Dyn* dynamic,
+ size_t dynamic_count,
+ Word dynamic_flags);
+
+ // Initialize the dynamic section.
+ bool InitDynamicSection();
+
+ // Get pointer to the dynamic table.
+ const Dyn* GetDynamicTable();
+
+ // Get the size of the dynamic table
+ size_t GetDynamicTableSize();
+
+ // Call all the global constructors.
+ void CallConstructors();
+
+ // Call all the global destructors.
+ void CallDestructors();
+
+ // Lookup a symbol using its name.
+ const Sym* LookupByName(const char* symbol_name) const;
+
+ // Lookup a symbol using its id.
+ const Sym* LookupById(size_t symbol_id) const;
+
+ // Checks if a symbols is weak.
+ bool IsWeakById(size_t symbol_id) const;
+
+ // Lookup the name of a symbol by using its id.
+ const char* LookupNameById(size_t symbol_id) const;
+
+ private:
+ // Call a function.
+ void CallFunction(linker_function_t func, const char* func_type);
+
+ Addr base_memory_address_;
+ const char* soname_;
+
+ Dyn* dynamic_;
+ size_t dynamic_count_;
+ Word dynamic_flags_;
+ bool has_DT_SYMBOLIC_;
+
+ Sym* symbol_table_;
+ const char* string_table_;
+ ElfHashTable elf_hash_;
+ GnuHashTable gnu_hash_;
+
+ linker_function_t* preinit_array_;
+ size_t preinit_array_count_;
+ linker_function_t* init_array_;
+ size_t init_array_count_;
+ linker_function_t* fini_array_;
+ size_t fini_array_count_;
+ linker_function_t init_func_;
+ linker_function_t fini_func_;
+
+ SB_DISALLOW_COPY_AND_ASSIGN(DynamicSection);
+};
+
+} // namespace elf_loader
+} // namespace starboard
+
+#endif // STARBOARD_ELF_LOADER_DYNAMIC_SECTION_H_
diff --git a/src/starboard/elf_loader/dynamic_section_test.cc b/src/starboard/elf_loader/dynamic_section_test.cc
new file mode 100644
index 0000000..6812046
--- /dev/null
+++ b/src/starboard/elf_loader/dynamic_section_test.cc
@@ -0,0 +1,207 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/elf_loader/dynamic_section.h"
+
+#include "starboard/common/scoped_ptr.h"
+#include "starboard/string.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if SB_API_VERSION >= 12 && \
+ (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)) && \
+ SB_CAN(MAP_EXECUTABLE_MEMORY)
+
+namespace starboard {
+namespace elf_loader {
+
+namespace {
+
+class DynamicSectionTest : public ::testing::Test {
+ protected:
+ DynamicSectionTest() {}
+ ~DynamicSectionTest() {}
+};
+
+typedef struct DynamicSectionMemory {
+ Dyn dynamic_table_[3];
+ linker_function_t init_array_[2];
+ linker_function_t fini_array_[2];
+ Sym symbol_table_[2];
+ char string_table_[128];
+} DynamicSectionMemory;
+
+bool gInitCalled = false;
+bool gCtor1Called = false;
+bool gCtor2Called = false;
+bool gDtor1Called = false;
+bool gDtor2Called = false;
+
+void InitFunction() {
+ gInitCalled = true;
+}
+
+void TestConstructor1() {
+ gCtor1Called = true;
+}
+
+void TestConstructor2() {
+ gCtor2Called = true;
+}
+
+void TestDestructor1() {
+ gDtor1Called = true;
+}
+
+void TestDestructor2() {
+ gDtor2Called = true;
+}
+
+TEST_F(DynamicSectionTest, Initialize) {
+ Addr addr = 0x1234;
+ Dyn dynamic_table[3];
+ Word flags = 0;
+
+ DynamicSection d(addr, dynamic_table, 3, flags);
+ ASSERT_TRUE(d.InitDynamicSection());
+
+ ASSERT_EQ(dynamic_table, d.GetDynamicTable());
+ ASSERT_EQ(3, d.GetDynamicTableSize());
+}
+
+TEST_F(DynamicSectionTest, CallInit) {
+ Word flags = 0;
+ DynamicSectionMemory dynamic_section_memory;
+ Addr base_addr = reinterpret_cast<Addr>(&dynamic_section_memory);
+ dynamic_section_memory.dynamic_table_[0].d_tag = DT_INIT;
+ dynamic_section_memory.dynamic_table_[0].d_un.d_ptr =
+ reinterpret_cast<Addr>(InitFunction) - base_addr;
+
+ DynamicSection d(base_addr, dynamic_section_memory.dynamic_table_, 1, flags);
+ ASSERT_TRUE(d.InitDynamicSection());
+
+ ASSERT_EQ(dynamic_section_memory.dynamic_table_, d.GetDynamicTable());
+ ASSERT_EQ(1, d.GetDynamicTableSize());
+ d.CallConstructors();
+ ASSERT_TRUE(gInitCalled);
+}
+
+TEST_F(DynamicSectionTest, CallConstructors) {
+ Word flags = 0;
+ DynamicSectionMemory dynamic_section_memory;
+ Addr base_addr = reinterpret_cast<Addr>(&dynamic_section_memory);
+
+ dynamic_section_memory.init_array_[0] =
+ reinterpret_cast<linker_function_t>(&TestConstructor1);
+ dynamic_section_memory.init_array_[1] =
+ reinterpret_cast<linker_function_t>(&TestConstructor2);
+
+ dynamic_section_memory.dynamic_table_[0].d_tag = DT_INIT_ARRAY;
+ dynamic_section_memory.dynamic_table_[0].d_un.d_ptr =
+ reinterpret_cast<Addr>(dynamic_section_memory.init_array_) - base_addr;
+
+ dynamic_section_memory.dynamic_table_[1].d_tag = DT_INIT_ARRAYSZ;
+ dynamic_section_memory.dynamic_table_[1].d_un.d_val =
+ sizeof(dynamic_section_memory.init_array_);
+
+ DynamicSection d(base_addr, dynamic_section_memory.dynamic_table_, 2, flags);
+ ASSERT_TRUE(d.InitDynamicSection());
+
+ ASSERT_EQ(dynamic_section_memory.dynamic_table_, d.GetDynamicTable());
+ ASSERT_EQ(2, d.GetDynamicTableSize());
+ d.CallConstructors();
+ ASSERT_TRUE(gCtor1Called);
+ ASSERT_TRUE(gCtor2Called);
+}
+
+TEST_F(DynamicSectionTest, CallDestructors) {
+ Word flags = 0;
+ DynamicSectionMemory dynamic_section_memory;
+ Addr base_addr = reinterpret_cast<Addr>(&dynamic_section_memory);
+
+ dynamic_section_memory.fini_array_[0] =
+ reinterpret_cast<linker_function_t>(&TestDestructor1);
+ dynamic_section_memory.fini_array_[1] =
+ reinterpret_cast<linker_function_t>(&TestDestructor2);
+
+ dynamic_section_memory.dynamic_table_[0].d_tag = DT_FINI_ARRAY;
+ dynamic_section_memory.dynamic_table_[0].d_un.d_ptr =
+ reinterpret_cast<Addr>(dynamic_section_memory.fini_array_) - base_addr;
+
+ dynamic_section_memory.dynamic_table_[1].d_tag = DT_FINI_ARRAYSZ;
+ dynamic_section_memory.dynamic_table_[1].d_un.d_val =
+ sizeof(dynamic_section_memory.fini_array_);
+
+ DynamicSection d(base_addr, dynamic_section_memory.dynamic_table_, 2, flags);
+ ASSERT_TRUE(d.InitDynamicSection());
+
+ ASSERT_EQ(dynamic_section_memory.dynamic_table_, d.GetDynamicTable());
+ ASSERT_EQ(2, d.GetDynamicTableSize());
+ d.CallDestructors();
+ ASSERT_TRUE(gDtor1Called);
+ ASSERT_TRUE(gDtor2Called);
+}
+
+TEST_F(DynamicSectionTest, LookupById) {
+ Word flags = 0;
+ DynamicSectionMemory dynamic_section_memory;
+ Addr base_addr = reinterpret_cast<Addr>(&dynamic_section_memory);
+
+ dynamic_section_memory.dynamic_table_[0].d_tag = DT_SYMTAB;
+ dynamic_section_memory.dynamic_table_[0].d_un.d_ptr =
+ reinterpret_cast<Addr>(dynamic_section_memory.symbol_table_) - base_addr;
+
+ DynamicSection d(base_addr, dynamic_section_memory.dynamic_table_, 1, flags);
+
+ ASSERT_TRUE(d.InitDynamicSection());
+
+ ASSERT_EQ(dynamic_section_memory.dynamic_table_, d.GetDynamicTable());
+ ASSERT_EQ(1, d.GetDynamicTableSize());
+ ASSERT_EQ(dynamic_section_memory.symbol_table_, d.LookupById(0));
+ ASSERT_EQ(dynamic_section_memory.symbol_table_ + 1, d.LookupById(1));
+}
+
+TEST_F(DynamicSectionTest, LookupNameById) {
+ Word flags = 0;
+ DynamicSectionMemory dynamic_section_memory;
+ Addr base_addr = reinterpret_cast<Addr>(&dynamic_section_memory);
+
+ dynamic_section_memory.dynamic_table_[0].d_tag = DT_SYMTAB;
+ dynamic_section_memory.dynamic_table_[0].d_un.d_ptr =
+ reinterpret_cast<Addr>(dynamic_section_memory.symbol_table_) - base_addr;
+
+ dynamic_section_memory.dynamic_table_[1].d_tag = DT_STRTAB;
+ dynamic_section_memory.dynamic_table_[1].d_un.d_ptr =
+ reinterpret_cast<Addr>(dynamic_section_memory.string_table_) - base_addr;
+
+ SbMemoryCopy(dynamic_section_memory.string_table_, "test1\x00test2\x00", 12);
+
+ dynamic_section_memory.symbol_table_[0].st_name = 0; // the offset of test1
+ dynamic_section_memory.symbol_table_[1].st_name = 6; // the offset of test2
+
+ DynamicSection d(base_addr, dynamic_section_memory.dynamic_table_, 2, flags);
+
+ ASSERT_TRUE(d.InitDynamicSection());
+
+ ASSERT_EQ(dynamic_section_memory.dynamic_table_, d.GetDynamicTable());
+ ASSERT_EQ(2, d.GetDynamicTableSize());
+
+ ASSERT_EQ(0, SbStringCompareAll("test1", d.LookupNameById(0)));
+ ASSERT_EQ(0, SbStringCompareAll("test2", d.LookupNameById(1)));
+}
+
+} // namespace
+} // namespace elf_loader
+} // namespace starboard
+#endif // SB_API_VERSION >= 12 && (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION
+ // || SB_HAS(MMAP)) && SB_CAN(MAP_EXECUTABLE_MEMORY)
diff --git a/src/starboard/elf_loader/elf.h b/src/starboard/elf_loader/elf.h
new file mode 100644
index 0000000..64d4365
--- /dev/null
+++ b/src/starboard/elf_loader/elf.h
@@ -0,0 +1,661 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_ELF_LOADER_ELF_H_
+#define STARBOARD_ELF_LOADER_ELF_H_
+
+// Subset of the ELF specification for loading Dynamic Shared Libraries.
+// System V Application Binary Interface - DRAFT - 10 June 2013
+// http://www.sco.com/developers/gabi/latest/contents.html
+
+#ifndef __cplusplus
+#error "Only C++ files can include this header."
+#endif
+
+#include "starboard/types.h"
+
+namespace starboard {
+namespace elf_loader {
+
+// 32 bit data types
+
+// Unsigned program address - 4 bytes.
+typedef uint32_t Elf32_Addr;
+
+// Unsigned medium integer - 2 bytes.
+typedef uint16_t Elf32_Half;
+
+// Unsigned file offset - 4 bytes.
+typedef uint32_t Elf32_Off;
+
+// Signed large integer - 4 bytes.
+typedef int32_t Elf32_Sword;
+
+// Unsigned large integer - 4 bytes.
+typedef uint32_t Elf32_Word;
+
+// 64 bit data types
+
+// Unsigned program address - 8 bytes.
+typedef uint64_t Elf64_Addr;
+
+// Unsigned file offset - 8 bytes.
+typedef uint64_t Elf64_Off;
+
+// Unsigned medium intege 2 - bytes.
+typedef uint16_t Elf64_Half;
+
+// Unsigned integer - 4 bytes.
+typedef uint32_t Elf64_Word;
+
+// Signed integer - 4 bytes.
+typedef int32_t Elf64_Sword;
+
+// Unsigned long integer - 8 bytes.
+typedef uint64_t Elf64_Xword;
+
+// Signed long integer - 8 bytes.
+typedef int64_t Elf64_Sxword;
+
+#define EI_NIDENT (16)
+
+// Pack all the structs at 1 byte alignment.
+#pragma pack(push)
+#pragma pack(1)
+
+// 32 bit ELF file header.
+typedef struct {
+ // The initial bytes mark the file as an object file and provide
+ // machine-independent data.
+ unsigned char e_ident[EI_NIDENT];
+
+ // The object file type. We support only ET_DYN.
+ Elf32_Half e_type;
+
+ // Architecture of the file.
+ Elf32_Half e_machine;
+
+ // Object file version. The value should be 1.
+ Elf32_Word e_version;
+
+ // Virtual address to which the system first transfers
+ // control, thus starting the process.
+ Elf32_Addr e_entry;
+
+ // Program header table's file offset in bytes.
+ Elf32_Off e_phoff;
+
+ // Section header table's file offset in bytes.
+ Elf32_Off e_shoff;
+
+ // Processor-specific flags associated with the file.
+ Elf32_Word e_flags;
+
+ // ELF header's size in bytes.
+ Elf32_Half e_ehsize;
+
+ // Size in bytes of one entry in the file's program header table
+ Elf32_Half e_phentsize;
+
+ // The number of entries in the program header table.
+ Elf32_Half e_phnum;
+
+ // Section header's size in bytes.
+ Elf32_Half e_shentsize;
+
+ // The number of entries in the section header table.
+ Elf32_Half e_shnum;
+
+ // The section header table index of the entry associated
+ // with the section name string table.
+ Elf32_Half e_shstrndx;
+} Elf32_Ehdr;
+
+// 64 bit ELF file header.
+typedef struct {
+ // The initial bytes mark the file as an object file and provide
+ // machine-independent data.
+ unsigned char e_ident[EI_NIDENT];
+
+ // The object file type. We support only ET_DYN.
+ Elf64_Half e_type;
+
+ // Architecture of the file.
+ Elf64_Half e_machine;
+
+ // Object file version. The value should be 1.
+ Elf64_Word e_version;
+
+ // Virtual address to which the system first transfers
+ // control, thus starting the process.
+ Elf64_Addr e_entry;
+
+ // Program header table's file offset in bytes.
+ Elf64_Off e_phoff;
+
+ // Section header table's file offset in bytes.
+ Elf64_Off e_shoff;
+
+ // Processor-specific flags associated with the file.
+ Elf64_Word e_flags;
+
+ // This member holds the ELF header's size in bytes.
+ Elf64_Half e_ehsize;
+
+ // Size in bytes of one entry in the file's program header table
+ Elf64_Half e_phentsize;
+
+ // The number of entries in the section header table.
+ Elf64_Half e_phnum;
+
+ // Section header's size in bytes.
+ Elf64_Half e_shentsize;
+
+ // The number of entries in the section header table.
+ Elf64_Half e_shnum;
+
+ // The section header table index of the entry associated
+ // with the section name string table.
+ Elf64_Half e_shstrndx;
+} Elf64_Ehdr;
+
+// 32 bit Program header.
+typedef struct {
+ // The kind of segment this array element describes.
+ Elf32_Word p_type;
+
+ // The offset from the beginning of the file at which the
+ // first byte of the segment resides.
+ Elf32_Off p_offset;
+
+ // The virtual address at which the first byte of the
+ // segment resides in memory.
+ Elf32_Addr p_vaddr;
+
+ // Segment's physical address. Unused for shared libraries.
+ Elf32_Addr p_paddr;
+
+ // The number of bytes in the file image of the segment. May be zero.
+ Elf32_Word p_filesz;
+
+ // The number of bytes in the memory image of the segment. May be zero.
+ Elf32_Word p_memsz;
+
+ // Segment flags
+ Elf32_Word p_flags;
+
+ // Segment alignment constraint.
+ Elf32_Word p_align;
+} Elf32_Phdr;
+
+// 64 bit Program header.
+typedef struct {
+ // The kind of segment this array element describes.
+ Elf64_Word p_type;
+
+ // Segment flags
+ Elf64_Word p_flags;
+
+ // The offset from the beginning of the file at which the
+ // first byte of the segment resides.
+ Elf64_Off p_offset;
+
+ // The virtual address at which the first byte of the
+ // segment resides in memory.
+ Elf64_Addr p_vaddr;
+
+ // Segment's physical address. Unused for shared libraries.
+ Elf64_Addr p_paddr;
+
+ // The number of bytes in the file image of the segment. May be zero.
+ Elf64_Xword p_filesz;
+
+ // The number of bytes in the memory image of the segment. May be zero.
+ Elf64_Xword p_memsz;
+
+ // Segment alignment constraint
+ Elf64_Xword p_align;
+} Elf64_Phdr;
+
+// 32 bit Dynamic Section Entry
+typedef struct {
+ // Controls the interpretation of d_un.
+ Elf32_Sword d_tag;
+ union {
+ // These objects represent integer values with various interpretations.
+ Elf32_Word d_val;
+ // These objects represent program virtual addresses.
+ Elf32_Addr d_ptr;
+ } d_un;
+} Elf32_Dyn;
+
+// 64 bit Dynamic Section Entry
+typedef struct {
+ // Controls the interpretation of d_un.
+ Elf64_Sxword d_tag;
+ union {
+ // These objects represent integer values with various interpretations.
+ Elf64_Xword d_val;
+ // These objects represent program virtual addresses.
+ Elf64_Addr d_ptr;
+ } d_un;
+} Elf64_Dyn;
+
+// 32 bit Symbol Table Entry
+typedef struct {
+ // An index into the object file's symbol string table,
+ // which holds the character representations of the symbol names. If the value
+ // is non-zero, it represents a string table index that gives the symbol name.
+ // Otherwise, the symbol table entry has no name.
+ Elf32_Word st_name;
+
+ // The value of the associated symbol. Depending on the
+ // context, this may be an absolute value, an address, and so on;
+ Elf32_Addr st_value;
+
+ // Many symbols have associated sizes. For example, a data object's size is
+ // the number of bytes contained in the object.
+ Elf32_Word st_size;
+
+ // The symbol's type and binding attributes.
+ unsigned char st_info;
+
+ // Symbol's visibility.
+ unsigned char st_other;
+
+ // Every symbol table entry is defined in relation to some section. This
+ // member holds the relevant section header table index.
+ Elf32_Half st_shndx;
+} Elf32_Sym;
+
+// 64 bit Symbol Table Entry
+typedef struct {
+ // An index into the object file's symbol string table,
+ // which holds the character representations of the symbol names. If the value
+ // is non-zero, it represents a string table index that gives the symbol name.
+ // Otherwise, the symbol table entry has no name.
+ Elf64_Word st_name;
+
+ // The symbol's type and binding attributes.
+ unsigned char st_info;
+
+ // Symbol's visibility.
+ unsigned char st_other;
+
+ // Every symbol table entry is defined in relation to some section. This
+ // member holds the relevant section header table index.
+ Elf64_Half st_shndx;
+
+ // The value of the associated symbol. Depending on the
+ // context, this may be an absolute value, an address, and so on;
+ Elf64_Addr st_value;
+
+ // Many symbols have associated sizes. For example, a data object's size is
+ // the number of bytes contained in the object.
+ Elf64_Xword st_size;
+} Elf64_Sym;
+
+// 32 bit Relocation Entry
+typedef struct {
+ // The location at which to apply the relocation action. For a relocatable
+ // file, the value is the byte offset from the beginning of the section to
+ // the storage unit affected by the relocation. For an executable file or a
+ // shared object, the value is the virtual address of the storage unit
+ // affected by the relocation.
+ Elf32_Addr r_offset;
+ // The symbol table index with respect to which the
+ // relocation must be made, and the type of relocation to apply.
+ Elf32_Word r_info;
+} Elf32_Rel;
+
+// 64 bit Relocation Entry
+typedef struct {
+ // The location at which to apply the relocation action. For
+ // a relocatable file, the value is the byte offset from the beginning of the
+ // section to the storage unit affected by the relocation. For an executable
+ // file or a shared object, the value is the virtual address of the storage
+ // unit affected by the relocation.
+ Elf64_Addr r_offset;
+
+ // The symbol table index with respect to which the
+ // relocation must be made, and the type of relocation to apply.
+ Elf64_Xword r_info;
+} Elf64_Rel;
+
+// 32 bit Relocation Entry with Addend.
+typedef struct {
+ // The location at which to apply the relocation action. For
+ // a relocatable file, the value is the byte offset from the beginning of the
+ // section to the storage unit affected by the relocation. For an executable
+ // file or a shared object, the value is the virtual address of the storage
+ // unit affected by the relocation.
+ Elf32_Addr r_offset;
+
+ // The symbol table index with respect to which the
+ // relocation must be made, and the type of relocation to apply.
+ Elf32_Word r_info;
+
+ // A constant addend used to compute the value to be stored into the
+ // relocatable field.
+ Elf32_Sword r_addend;
+} Elf32_Rela;
+
+// 64 bit Relocation Entry with Addend.
+typedef struct {
+ // The location at which to apply the relocation action. For a relocatable
+ // file, the value is the byte offset from the beginning of the section to the
+ // storage unit affected by the relocation. For an executable file or a shared
+ // object, the value is the virtual address of the storage unit affected by
+ // the relocation.
+ Elf64_Addr r_offset;
+
+ // The symbol table index with respect to which the
+ // relocation must be made, and the type of relocation to apply.
+ Elf64_Xword r_info;
+
+ // A constant addend used to compute the value to be stored into the
+ // relocatable field.
+ Elf64_Sxword r_addend;
+} Elf64_Rela;
+
+#pragma pack(pop)
+
+#define EI_CLASS 4
+#define ELFCLASS32 1
+#define ELFCLASS64 2
+#define EI_DATA 5
+#define ELFDATA2LSB 1
+#define ET_DYN 3
+#define EV_CURRENT 1
+
+#if SB_SIZE_OF(POINTER) == 4
+typedef Elf32_Ehdr Ehdr;
+typedef Elf32_Phdr Phdr;
+typedef Elf32_Addr Addr;
+typedef Elf32_Dyn Dyn;
+typedef Elf32_Word Word;
+typedef Elf32_Sym Sym;
+typedef Elf32_Rel Rel;
+typedef Elf32_Rela Rela;
+typedef Elf32_Word Relr;
+typedef Elf32_Sword Sword;
+#define ELF_BITS 32
+#define ELF_R_TYPE ELF32_R_TYPE
+#define ELF_R_SYM ELF32_R_SYM
+#define ELF_CLASS_VALUE ELFCLASS32
+#elif SB_SIZE_OF(POINTER) == 8
+typedef Elf64_Ehdr Ehdr;
+typedef Elf64_Phdr Phdr;
+typedef Elf64_Addr Addr;
+typedef Elf64_Dyn Dyn;
+typedef Elf64_Word Word;
+typedef Elf64_Sym Sym;
+typedef Elf64_Rel Rel;
+typedef Elf64_Rela Rela;
+typedef Elf64_Word Relr;
+typedef Elf64_Sword Sword;
+#define ELF_BITS 64
+#define ELF_R_TYPE ELF64_R_TYPE
+#define ELF_R_SYM ELF64_R_SYM
+#define ELF_CLASS_VALUE ELFCLASS64
+#else
+#error "Unsupported pointer size"
+#endif
+
+#define ELF32_R_SYM(val) ((val) >> 8)
+#define ELF32_R_TYPE(val) ((val)&0xff)
+#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type)&0xff))
+
+#define ELF64_R_SYM(i) ((i) >> 32)
+#define ELF64_R_TYPE(i) ((i)&0xffffffff)
+#define ELF64_R_INFO(sym, type) ((((Elf64_Xword)(sym)) << 32) + (type))
+
+#define ELFMAG "\177ELF"
+#define SELFMAG 4
+
+// TODO: Refactor the code to detect it at runtime
+// using DT_PLTREL.
+#if SB_IS(ARCH_ARM64) || SB_IS(ARCH_X64)
+#define USE_RELA
+#endif
+
+#if defined(USE_RELA)
+typedef Rela rel_t;
+#else
+typedef Rel rel_t;
+#endif
+
+#if SB_IS(ARCH_ARM)
+#define ELF_MACHINE 40
+#elif SB_IS(ARCH_X86)
+#define ELF_MACHINE 3
+#elif SB_IS(ARCH_X64)
+#define ELF_MACHINE 62
+#elif SB_IS(ARCH_ARM64)
+#define ELF_MACHINE 183
+#else
+#error "Unsupported target CPU architecture"
+#endif
+
+// Segment types.
+typedef enum SegmentTypes {
+ // Unused segment.
+ PT_NULL = 0,
+
+ // Loadable segment.
+ PT_LOAD = 1,
+
+ // Dynamic linking information.
+ PT_DYNAMIC = 2,
+
+ // Interpreter pathname.
+ PT_INTERP = 3,
+
+ // Auxiliary information.
+ PT_NOTE = 4,
+
+ // Reserved.
+ PT_SHLIB = 5,
+
+ // The program header table itself.
+ PT_PHDR = 6,
+
+ // The thread-local storage template.
+ PT_TLS = 7
+} SegmentTypes;
+
+// Symbol bindings.
+typedef enum SymbolBindings {
+ // Local symbol, not visible outside obj file containing def
+ STB_LOCAL = 0,
+
+ // Global symbol, visible to all object files being combined
+ STB_GLOBAL = 1,
+
+ // Weak symbol, like global but lower-precedence
+ STB_WEAK = 2,
+
+ STB_GNU_UNIQUE = 10,
+
+ // Lowest operating system-specific binding type
+ STB_LOOS = 10,
+
+ // Highest operating system-specific binding type
+ STB_HIOS = 12,
+
+ // Lowest processor-specific binding type
+ STB_LOPROC = 13,
+
+ // Highest processor-specific binding type
+ STB_HIPROC = 15
+} SymbolBindings;
+
+#define ELF_ST_BIND(x) ((x) >> 4)
+#define ELF32_ST_BIND(x) ELF_ST_BIND(x)
+#define ELF64_ST_BIND(x) ELF_ST_BIND(x)
+
+#define PF_X (1 << 0)
+#define PF_W (1 << 1)
+#define PF_R (1 << 2)
+#define PF_MASKOS 0x0ff00000
+#define PF_MASKPROC 0xf0000000
+
+// Dynamic table tags.
+typedef enum DynamicTags {
+ DT_NULL = 0,
+ DT_NEEDED = 1,
+ DT_PLTRELSZ = 2,
+ DT_PLTGOT = 3,
+ DT_HASH = 4,
+ DT_STRTAB = 5,
+ DT_SYMTAB = 6,
+ DT_RELA = 7,
+ DT_RELASZ = 8,
+ DT_RELAENT = 9,
+ DT_STRSZ = 10,
+ DT_SYMENT = 11,
+ DT_INIT = 12,
+ DT_FINI = 13,
+ DT_SONAME = 14,
+ DT_RPATH = 15,
+ DT_SYMBOLIC = 16,
+ DT_REL = 17,
+ DT_RELSZ = 18,
+ DT_RELENT = 19,
+ DT_PLTREL = 20,
+ DT_DEBUG = 21,
+ DT_TEXTREL = 22,
+ DT_JMPREL = 23,
+ DT_BIND_NOW = 24,
+ DT_INIT_ARRAY = 25,
+ DT_FINI_ARRAY = 26,
+ DT_INIT_ARRAYSZ = 27,
+ DT_FINI_ARRAYSZ = 28,
+ DT_RUNPATH = 29,
+ DT_FLAGS = 30,
+ DT_ENCODING = 32,
+ DT_PREINIT_ARRAY = 32,
+ DT_PREINIT_ARRAYSZ = 33,
+ DT_SYMTAB_SHNDX = 34,
+ DT_RELRSZ = 35,
+ DT_RELR = 36,
+ DT_RELRENT = 37,
+ DT_LOOS = 0x6000000D,
+ DT_ANDROID_REL = 0x6000000F,
+ DT_ANDROID_RELSZ = 0x60000010,
+ DT_ANDROID_RELA = 0x60000011,
+ DT_ANDROID_RELASZ = 0x60000012,
+ DT_HIOS = 0x6ffff000,
+ DT_ANDROID_RELR = 0x6fffe000,
+ DT_ANDROID_RELRSZ = 0x6fffe001,
+ DT_ANDROID_RELRENT = 0x6fffe003,
+ DT_GNU_HASH = 0x6ffffef5,
+ DT_LOPROC = 0x70000000,
+ DT_HIPROC = 0x7fffffff,
+} DynamicTags;
+
+typedef enum DynamicFlags {
+ // This flag signifies that the object being loaded may make reference to the
+ DF_ORIGIN = 0x00000001,
+
+ // If this flag is set in a shared object library, the dynamic linker's symbol
+ // resolution algorithm for references within the library is changed. Instead
+ // of starting a symbol search with the executable file, the dynamic linker
+ // starts from the shared object itself. If the shared object fails to supply
+ // the referenced symbol, the dynamic linker then searches the executable file
+ // and other shared objects as usual.
+ DF_SYMBOLIC = 0x00000002,
+
+ // This flag is not set, no relocation entry should cause a modification to a
+ // non-writable segment, as specified by the segment permissions in the
+ // program header table.
+ DF_TEXTREL = 0x00000004,
+
+ // If set in a shared object or executable, this flag instructs the dynamic
+ // linker to process all relocations for the object containing this entry
+ // before transferring control to the program.
+ DF_BIND_NOW = 0x00000008,
+
+ // If set in a shared object or executable, this flag instructs the dynamic
+ // linker to reject attempts to load this file dynamically. It indicates that
+ // the shared object or executable contains code using a static thread-local
+ // storage scheme. Implementations need not support any form of thread-local
+ // storage.
+ DF_STATIC_TLS = 0x00000010,
+} DynamicFalgs;
+
+// Relocation types per CPU architecture
+#if SB_IS(ARCH_ARM)
+typedef enum RelocationTypes {
+ R_ARM_ABS32 = 2,
+ R_ARM_REL32 = 3,
+ R_ARM_GLOB_DAT = 21,
+ R_ARM_JUMP_SLOT = 22,
+ R_ARM_COPY = 20,
+ R_ARM_RELATIVE = 23,
+} RelocationTypes;
+#elif SB_IS(ARCH_ARM64)
+typedef enum RelocationTypes {
+ R_AARCH64_ABS64 = 257,
+ R_AARCH64_COPY = 1024,
+ R_AARCH64_GLOB_DAT = 1025,
+ R_AARCH64_JUMP_SLOT = 1026,
+ R_AARCH64_RELATIVE = 1027,
+} RelocationTypes;
+#elif SB_IS(ARCH_X86)
+typedef enum RelocationTypes {
+ R_386_32 = 1,
+ R_386_PC32 = 2,
+ R_386_GLOB_DAT = 6,
+ R_386_JMP_SLOT = 7,
+ R_386_RELATIVE = 8,
+} RelocationTypes;
+#elif SB_IS(ARCH_X64)
+typedef enum RelocationTypes {
+ R_X86_64_64 = 1,
+ R_X86_64_PC32 = 2,
+ R_X86_64_GLOB_DAT = 6,
+ R_X86_64_JMP_SLOT = 7,
+ R_X86_64_RELATIVE = 8,
+} RelocationTypes;
+#else
+#error "Unsupported architecture for relocations."
+#endif
+
+// Helper macros for memory page computations.
+#ifndef PAGE_SIZE
+#define PAGE_SHIFT 12
+
+#if SB_SIZE_OF(POINTER) == 4
+#define PAGE_SIZE (1UL << PAGE_SHIFT)
+#elif SB_SIZE_OF(POINTER) == 8
+#define PAGE_SIZE (1ULL << PAGE_SHIFT)
+#else
+#error "Unsupported pointer size"
+#endif
+#endif
+
+#ifndef PAGE_MASK
+#define PAGE_MASK (~(PAGE_SIZE - 1))
+#endif
+
+#define PAGE_START(x) ((x)&PAGE_MASK)
+#define PAGE_OFFSET(x) ((x) & ~PAGE_MASK)
+#define PAGE_END(x) PAGE_START((x) + (PAGE_SIZE - 1))
+
+#define SHN_UNDEF 0
+
+} // namespace elf_loader
+} // namespace starboard
+#endif // STARBOARD_ELF_LOADER_ELF_H_
diff --git a/src/starboard/elf_loader/elf_hash_table.cc b/src/starboard/elf_loader/elf_hash_table.cc
new file mode 100644
index 0000000..b6b6c70
--- /dev/null
+++ b/src/starboard/elf_loader/elf_hash_table.cc
@@ -0,0 +1,69 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/elf_loader/elf_hash_table.h"
+#include "starboard/string.h"
+
+namespace starboard {
+namespace elf_loader {
+
+// Compute the ELF hash of a given symbol.
+// Defined in
+// https://refspecs.linuxfoundation.org/elf/gabi4+/ch5.dynamic.html#hash
+static unsigned ElfHash(const char* name) {
+ const uint8_t* ptr = reinterpret_cast<const uint8_t*>(name);
+ unsigned h = 0;
+ while (*ptr) {
+ h = (h << 4) + *ptr++;
+ unsigned g = h & 0xf0000000;
+ h ^= g;
+ h ^= g >> 24;
+ }
+ return h;
+}
+
+ElfHashTable::ElfHashTable()
+ : hash_bucket_(NULL),
+ hash_bucket_size_(0),
+ hash_chain_(NULL),
+ hash_chain_size_(0) {}
+void ElfHashTable::Init(uintptr_t dt_elf_hash) {
+ const Word* data = reinterpret_cast<const Word*>(dt_elf_hash);
+ hash_bucket_size_ = data[0];
+ hash_bucket_ = data + 2;
+ hash_chain_size_ = data[1];
+ hash_chain_ = hash_bucket_ + hash_bucket_size_;
+}
+
+bool ElfHashTable::IsValid() const {
+ return hash_bucket_size_ > 0;
+}
+
+const Sym* ElfHashTable::LookupByName(const char* symbol_name,
+ const Sym* symbol_table,
+ const char* string_table) const {
+ unsigned hash = ElfHash(symbol_name);
+
+ for (unsigned n = hash_bucket_[hash % hash_bucket_size_]; n != 0;
+ n = hash_chain_[n]) {
+ const Sym* symbol = &symbol_table[n];
+ // Check that the symbol has the appropriate name.
+ if (!SbStringCompareAll(string_table + symbol->st_name, symbol_name))
+ return symbol;
+ }
+ return NULL;
+}
+
+} // namespace elf_loader
+} // namespace starboard
diff --git a/src/starboard/elf_loader/elf_hash_table.h b/src/starboard/elf_loader/elf_hash_table.h
new file mode 100644
index 0000000..14bb9ca
--- /dev/null
+++ b/src/starboard/elf_loader/elf_hash_table.h
@@ -0,0 +1,62 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_ELF_LOADER_ELF_HASH_TABLE_H_
+#define STARBOARD_ELF_LOADER_ELF_HASH_TABLE_H_
+
+#include <stddef.h>
+#include "starboard/elf_loader/elf.h"
+
+namespace starboard {
+namespace elf_loader {
+
+// Models the hash table used to map symbol names to symbol entries using
+// the standard ELF format.
+class ElfHashTable {
+ public:
+ ElfHashTable();
+ // Initialize instance. |dt_elf_hash| should be the address that the
+ // DT_HASH entry points to in the input ELF dynamic section. Call IsValid()
+ // to determine whether the table was well-formed.
+ void Init(uintptr_t dt_elf_hash);
+
+ // Returns true iff the content of the table is valid.
+ bool IsValid() const;
+
+ // Index of the first dynamic symbol within the ELF symbol table.
+ size_t dyn_symbols_offset() const { return 1; }
+
+ // Number of dynamic symbols in the ELF symbol table.
+ size_t dyn_symbols_count() const { return hash_chain_size_ - 1; }
+
+ // Lookup |symbol_name| in the table. |symbol_table| should point to the
+ // ELF symbol table, and |string_table| to the start of its string table.
+ // Returns NULL on failure.
+ const Sym* LookupByName(const char* symbol_name,
+ const Sym* symbol_table,
+ const char* string_table) const;
+
+ private:
+ const Word* hash_bucket_;
+ size_t hash_bucket_size_;
+ const Word* hash_chain_;
+ size_t hash_chain_size_;
+
+ SB_DISALLOW_COPY_AND_ASSIGN(ElfHashTable);
+};
+
+} // namespace elf_loader
+} // namespace starboard
+
+#endif // STARBOARD_ELF_LOADER_ELF_HASH_TABLE_H_
diff --git a/src/starboard/elf_loader/elf_header.cc b/src/starboard/elf_loader/elf_header.cc
new file mode 100644
index 0000000..74695ca
--- /dev/null
+++ b/src/starboard/elf_loader/elf_header.cc
@@ -0,0 +1,76 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/elf_loader/elf_header.h"
+
+#include "starboard/common/log.h"
+#include "starboard/elf_loader/log.h"
+#include "starboard/memory.h"
+
+namespace starboard {
+namespace elf_loader {
+
+ElfHeader::ElfHeader() {
+ elf_header_.reset(new Ehdr());
+}
+
+bool ElfHeader::LoadElfHeader(File* file) {
+ SB_DLOG(INFO) << "LoadElfHeader";
+ if (!file->ReadFromOffset(0, reinterpret_cast<char*>(elf_header_.get()),
+ sizeof(Ehdr))) {
+ SB_LOG(ERROR) << "Failed to read file";
+ return false;
+ }
+
+ if (SbMemoryCompare(elf_header_->e_ident, ELFMAG, SELFMAG) != 0) {
+ SB_LOG(ERROR) << "Bad ELF magic: " << elf_header_->e_ident;
+ return false;
+ }
+
+ if (elf_header_->e_ident[EI_CLASS] != ELF_CLASS_VALUE) {
+ SB_LOG(ERROR) << "Not a " << ELF_BITS
+ << "-bit class: " << elf_header_->e_ident[EI_CLASS];
+ return false;
+ }
+ if (elf_header_->e_ident[EI_DATA] != ELFDATA2LSB) {
+ SB_LOG(ERROR) << "Not little-endian class" << elf_header_->e_ident[EI_DATA];
+ return false;
+ }
+
+ if (elf_header_->e_type != ET_DYN) {
+ SB_LOG(ERROR) << "Not a shared library type:" << std::hex
+ << elf_header_->e_type;
+ return false;
+ }
+
+ if (elf_header_->e_version != EV_CURRENT) {
+ SB_LOG(ERROR) << "Unexpected ELF version: " << elf_header_->e_version;
+ return false;
+ }
+
+ if (elf_header_->e_machine != ELF_MACHINE) {
+ SB_LOG(ERROR) << "Unexpected ELF machine type: " << std::hex
+ << elf_header_->e_machine;
+ return false;
+ }
+
+ return true;
+}
+
+const Ehdr* ElfHeader::GetHeader() {
+ return elf_header_.get();
+}
+
+} // namespace elf_loader
+} // namespace starboard
diff --git a/src/starboard/elf_loader/elf_header.h b/src/starboard/elf_loader/elf_header.h
new file mode 100644
index 0000000..a8b666c
--- /dev/null
+++ b/src/starboard/elf_loader/elf_header.h
@@ -0,0 +1,45 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_ELF_LOADER_ELF_HEADER_H_
+#define STARBOARD_ELF_LOADER_ELF_HEADER_H_
+
+#include "starboard/elf_loader/elf.h"
+
+#include "starboard/common/scoped_ptr.h"
+#include "starboard/elf_loader/file.h"
+
+namespace starboard {
+namespace elf_loader {
+
+// Class for loading, parsing and validating the ELF header section.
+class ElfHeader {
+ public:
+ ElfHeader();
+
+ // Load, parse and validate the ELF header.
+ bool LoadElfHeader(File* file);
+
+ // Get the actual header data.
+ const Ehdr* GetHeader();
+
+ private:
+ scoped_ptr<Ehdr> elf_header_;
+ SB_DISALLOW_COPY_AND_ASSIGN(ElfHeader);
+};
+
+} // namespace elf_loader
+} // namespace starboard
+
+#endif // STARBOARD_ELF_LOADER_ELF_HEADER_H_
diff --git a/src/starboard/elf_loader/elf_header_test.cc b/src/starboard/elf_loader/elf_header_test.cc
new file mode 100644
index 0000000..b2b94d2
--- /dev/null
+++ b/src/starboard/elf_loader/elf_header_test.cc
@@ -0,0 +1,130 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/elf_loader/elf_header.h"
+
+#include "starboard/common/scoped_ptr.h"
+#include "starboard/elf_loader/file.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if SB_API_VERSION >= 12 && \
+ (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)) && \
+ SB_CAN(MAP_EXECUTABLE_MEMORY)
+namespace starboard {
+namespace elf_loader {
+
+namespace {
+
+class DummyFile : public File {
+ public:
+ DummyFile(const char* buffer, int size) : buffer_(buffer), size_(size) {}
+
+ bool Open(const char* name) { return true; }
+ bool ReadFromOffset(int64_t offset, char* buffer, int size) {
+ SB_LOG(INFO) << "ReadFromOffset";
+ if (offset != 0) {
+ SB_LOG(ERROR) << "ReadFromOffset: Invalid offset " << offset;
+ return false;
+ }
+ if (size < size_) {
+ SB_LOG(ERROR) << "ReadFromOffset: Invalid size " << size;
+ return false;
+ }
+ SbMemoryCopy(buffer, buffer_, size);
+ return true;
+ }
+ void Close() {}
+
+ private:
+ const char* buffer_;
+ int size_;
+};
+
+class ElfHeaderTest : public ::testing::Test {
+ protected:
+ ElfHeaderTest() {
+ elf_header_.reset(new ElfHeader());
+ SbMemorySet(reinterpret_cast<char*>(&ehdr_data_), 0, sizeof(ehdr_data_));
+ ehdr_data_.e_machine = ELF_MACHINE;
+ ehdr_data_.e_ident[0] = 0x7F;
+ ehdr_data_.e_ident[1] = 'E';
+ ehdr_data_.e_ident[2] = 'L';
+ ehdr_data_.e_ident[3] = 'F';
+ ehdr_data_.e_ident[EI_CLASS] = ELF_CLASS_VALUE;
+ ehdr_data_.e_ident[EI_DATA] = ELFDATA2LSB;
+ ehdr_data_.e_type = ET_DYN;
+ ehdr_data_.e_version = EV_CURRENT;
+ ehdr_data_.e_machine = ELF_MACHINE;
+
+ dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_),
+ sizeof(ehdr_data_)));
+ }
+ ~ElfHeaderTest() {}
+
+ scoped_ptr<ElfHeader> elf_header_;
+ Ehdr ehdr_data_;
+ scoped_ptr<DummyFile> dummy_file_;
+};
+
+TEST_F(ElfHeaderTest, Initialize) {
+ EXPECT_TRUE(elf_header_->LoadElfHeader(dummy_file_.get()));
+}
+
+TEST_F(ElfHeaderTest, NegativeBadImage) {
+ ehdr_data_.e_ident[1] = 'F';
+ dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_),
+ sizeof(ehdr_data_)));
+ EXPECT_FALSE(elf_header_->LoadElfHeader(dummy_file_.get()));
+}
+
+TEST_F(ElfHeaderTest, NegativeBadClass) {
+ ehdr_data_.e_ident[EI_CLASS] = 0;
+ dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_),
+ sizeof(ehdr_data_)));
+ EXPECT_FALSE(elf_header_->LoadElfHeader(dummy_file_.get()));
+}
+
+TEST_F(ElfHeaderTest, NegativeWrongGulliverLilliput) {
+ ehdr_data_.e_type = 2;
+ dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_),
+ sizeof(ehdr_data_)));
+ EXPECT_FALSE(elf_header_->LoadElfHeader(dummy_file_.get()));
+}
+
+TEST_F(ElfHeaderTest, NegativeBadType) {
+ ehdr_data_.e_type = 2;
+ dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_),
+ sizeof(ehdr_data_)));
+ EXPECT_FALSE(elf_header_->LoadElfHeader(dummy_file_.get()));
+}
+
+TEST_F(ElfHeaderTest, NegativeBadVersion) {
+ ehdr_data_.e_version = 2;
+ dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_),
+ sizeof(ehdr_data_)));
+ EXPECT_FALSE(elf_header_->LoadElfHeader(dummy_file_.get()));
+}
+
+TEST_F(ElfHeaderTest, NegativeBadMachine) {
+ ehdr_data_.e_machine = 0;
+ dummy_file_.reset(new DummyFile(reinterpret_cast<const char*>(&ehdr_data_),
+ sizeof(ehdr_data_)));
+ EXPECT_FALSE(elf_header_->LoadElfHeader(dummy_file_.get()));
+}
+} // namespace
+} // namespace elf_loader
+} // namespace starboard
+#endif // SB_API_VERSION >= 12 && (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION
+ // || SB_HAS(MMAP)) && SB_CAN(MAP_EXECUTABLE_MEMORY)
diff --git a/src/starboard/elf_loader/elf_loader.cc b/src/starboard/elf_loader/elf_loader.cc
new file mode 100644
index 0000000..e86fb77
--- /dev/null
+++ b/src/starboard/elf_loader/elf_loader.cc
@@ -0,0 +1,105 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/elf_loader/elf_loader.h"
+
+#include <vector>
+
+#include "starboard/atomic.h"
+#include "starboard/common/log.h"
+#include "starboard/configuration_constants.h"
+#include "starboard/elf_loader/elf_loader_impl.h"
+#include "starboard/elf_loader/evergreen_config.h"
+#include "starboard/elf_loader/file_impl.h"
+
+namespace starboard {
+namespace elf_loader {
+
+ElfLoader* ElfLoader::g_instance = NULL;
+
+ElfLoader::ElfLoader() {
+ ElfLoader* old_instance =
+ reinterpret_cast<ElfLoader*>(SbAtomicAcquire_CompareAndSwapPtr(
+ reinterpret_cast<SbAtomicPtr*>(&g_instance),
+ reinterpret_cast<SbAtomicPtr>(reinterpret_cast<void*>(NULL)),
+ reinterpret_cast<SbAtomicPtr>(this)));
+ SB_DCHECK(!old_instance);
+ SB_UNREFERENCED_PARAMETER(old_instance);
+
+ impl_.reset(new ElfLoaderImpl());
+}
+
+ElfLoader::~ElfLoader() {
+ ElfLoader* old_instance =
+ reinterpret_cast<ElfLoader*>(SbAtomicAcquire_CompareAndSwapPtr(
+ reinterpret_cast<SbAtomicPtr*>(&g_instance),
+ reinterpret_cast<SbAtomicPtr>(this),
+ reinterpret_cast<SbAtomicPtr>(reinterpret_cast<void*>(NULL))));
+ SB_DCHECK(old_instance);
+ SB_DCHECK(old_instance == this);
+}
+
+ElfLoader* ElfLoader::Get() {
+ ElfLoader* elf_loader = reinterpret_cast<ElfLoader*>(
+ SbAtomicAcquire_LoadPtr(reinterpret_cast<SbAtomicPtr*>(&g_instance)));
+ SB_DCHECK(elf_loader);
+ return elf_loader;
+}
+
+bool ElfLoader::Load(const std::string& library_path,
+ const std::string& content_path,
+ bool is_relative_path,
+ const void* (*custom_get_extension)(const char* name)) {
+ if (is_relative_path) {
+ library_path_ = MakeRelativeToContentPath(library_path);
+ content_path_ = MakeRelativeToContentPath(content_path);
+ } else {
+ library_path_ = library_path;
+ content_path_ = content_path;
+ }
+
+ if (library_path_.empty() || content_path_.empty()) {
+ SB_LOG(ERROR) << "|library_path_| and |content_path_| cannot be empty.";
+ return false;
+ }
+ EvergreenConfig::Create(library_path_.c_str(), content_path_.c_str(),
+ custom_get_extension);
+ SB_LOG(INFO) << "evergreen_config: content_path=" << content_path_;
+ return impl_->Load(library_path_.c_str(), custom_get_extension);
+}
+
+void* ElfLoader::LookupSymbol(const char* symbol) {
+ return impl_->LookupSymbol(symbol);
+}
+
+std::string ElfLoader::MakeRelativeToContentPath(const std::string& path) {
+ std::vector<char> content_path(kSbFileMaxPath);
+
+ if (!SbSystemGetPath(kSbSystemPathContentDirectory, content_path.data(),
+ kSbFileMaxPath)) {
+ SB_LOG(ERROR) << "Failed to make '" << path.data()
+ << "' relative to the ELF Loader content directory.";
+ return "";
+ }
+
+ std::string relative_path(content_path.data());
+
+ relative_path.push_back(kSbFileSepChar);
+ relative_path.append(path);
+
+ return relative_path;
+}
+
+} // namespace elf_loader
+} // namespace starboard
diff --git a/src/starboard/elf_loader/elf_loader.gyp b/src/starboard/elf_loader/elf_loader.gyp
new file mode 100644
index 0000000..afb5bd6
--- /dev/null
+++ b/src/starboard/elf_loader/elf_loader.gyp
@@ -0,0 +1,179 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+{
+ 'variables': {
+ 'common_elf_loader_sources': [
+ 'elf_header.h',
+ 'elf_header.cc',
+ 'elf_hash_table.h',
+ 'elf_hash_table.cc',
+ 'elf_loader.h',
+ 'elf_loader.cc',
+ 'elf_loader_switches.h',
+ 'elf_loader_switches.cc',
+ 'exported_symbols.cc',
+ 'file.h',
+ 'file_impl.h',
+ 'file_impl.cc',
+ 'gnu_hash_table.h',
+ 'gnu_hash_table.cc',
+ 'dynamic_section.h',
+ 'dynamic_section.cc',
+ 'program_table.h',
+ 'program_table.cc',
+ 'relocations.h',
+ 'relocations.cc',
+ ],
+ 'elf_loader_impl_sources': [
+ 'elf_loader_impl.h',
+ 'elf_loader_impl.cc',
+ ],
+ 'elf_loader_sys_sources': [
+ 'elf_loader_sys_impl.h',
+ 'elf_loader_sys_impl.cc',
+ ]
+ },
+ 'targets': [
+ {
+ 'target_name': 'elf_loader',
+ 'type': 'static_library',
+ 'include_dirs': [
+ 'src/include',
+ 'src/src/',
+ ],
+ 'dependencies': [
+ '<(DEPTH)/starboard/elf_loader/evergreen_config.gyp:evergreen_config',
+ '<(DEPTH)/starboard/elf_loader/evergreen_info.gyp:evergreen_info',
+ '<(DEPTH)/starboard/starboard.gyp:starboard',
+ ],
+ 'sources': [
+ '<@(common_elf_loader_sources)',
+ '<@(elf_loader_impl_sources)',
+ ],
+ },
+ {
+ # System loader based on dlopen/dlsym.
+ # Should be used only for debugging/troubleshooting.
+ 'target_name': 'elf_loader_sys',
+ 'type': 'static_library',
+ 'include_dirs': [
+ 'src/include',
+ 'src/src/',
+ ],
+ 'dependencies': [
+ '<(DEPTH)/starboard/elf_loader/evergreen_config.gyp:evergreen_config',
+ '<(DEPTH)/starboard/starboard.gyp:starboard',
+ ],
+ 'sources': [
+ '<@(common_elf_loader_sources)',
+ '<@(elf_loader_sys_sources)',
+ ],
+ },
+ {
+ 'target_name': 'elf_loader_sandbox',
+ 'type': '<(final_executable_type)',
+ 'include_dirs': [
+ 'src/include',
+ 'src/src/',
+ ],
+ 'dependencies': [
+ 'elf_loader',
+ '<(DEPTH)/starboard/starboard.gyp:starboard_full',
+ # TODO: Remove this dependency once MediaSession is migrated to use CobaltExtensions.
+ '<@(cobalt_platform_dependencies)',
+ ],
+ 'sources': [
+ 'sandbox.cc',
+ ],
+ },
+ {
+ 'target_name': 'elf_loader_sandbox_deploy',
+ 'type': 'none',
+ 'dependencies': [
+ 'elf_loader_sandbox',
+ ],
+ 'variables': {
+ 'executable_name': 'elf_loader_sandbox',
+ },
+ 'includes': [ '<(DEPTH)/starboard/build/deploy.gypi' ],
+ },
+ {
+ # To properly function the system loader requires the starboard
+ # symbols to be exported from the binary.
+ # To allow symbols to be exported remove the '-fvisibility=hidden' flag
+ # from your compiler_flags.gypi. For Linux this would be:
+ # starboard/linux/shared/compiler_flags.gypi
+ # Example run:
+ # export LD_LIBRARY_PATH=.
+ # ./elf_loader_sys_sandbox --evergreen_library=app/cobalt/lib/libcobalt.so --evergreen_content=app/cobalt/content
+ 'target_name': 'elf_loader_sys_sandbox',
+ 'type': '<(final_executable_type)',
+ 'include_dirs': [
+ 'src/include',
+ 'src/src/',
+ ],
+ 'dependencies': [
+ 'elf_loader_sys',
+ '<(DEPTH)/starboard/starboard.gyp:starboard_full',
+ ],
+ 'sources': [
+ 'sandbox.cc',
+ ],
+ 'ldflags': [
+ '-Wl,--dynamic-list=<(DEPTH)/starboard/starboard.syms',
+ '-ldl' ,
+ ],
+ },
+ {
+ 'target_name': 'elf_loader_test',
+ 'type': '<(gtest_target_type)',
+ 'sources': [
+ '<(DEPTH)/starboard/common/test_main.cc',
+ ],
+ 'dependencies': [
+ '<(DEPTH)/starboard/starboard.gyp:starboard_full',
+ # TODO: Remove this dependency once MediaSession is migrated to use CobaltExtensions.
+ '<@(cobalt_platform_dependencies)',
+ '<(DEPTH)/testing/gmock.gyp:gmock',
+ '<(DEPTH)/testing/gtest.gyp:gtest',
+ ],
+ 'conditions': [
+ ['target_arch in ["x86", "x64", "arm", "arm64"] ', {
+ 'sources': [
+ 'elf_loader_test.cc',
+ 'elf_header_test.cc',
+ 'dynamic_section_test.cc',
+ 'program_table_test.cc',
+ 'relocations_test.cc',
+ ],
+ 'dependencies': [
+ 'elf_loader',
+ ],
+ }],
+ ],
+ },
+ {
+ 'target_name': 'elf_loader_test_deploy',
+ 'type': 'none',
+ 'dependencies': [
+ 'elf_loader_test',
+ ],
+ 'variables': {
+ 'executable_name': 'elf_loader_test',
+ },
+ 'includes': [ '<(DEPTH)/starboard/build/deploy.gypi' ],
+ },
+ ]
+}
diff --git a/src/starboard/elf_loader/elf_loader.h b/src/starboard/elf_loader/elf_loader.h
new file mode 100644
index 0000000..7119651
--- /dev/null
+++ b/src/starboard/elf_loader/elf_loader.h
@@ -0,0 +1,75 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_ELF_LOADER_ELF_LOADER_H_
+#define STARBOARD_ELF_LOADER_ELF_LOADER_H_
+
+#include <string>
+
+#include "starboard/common/scoped_ptr.h"
+#include "starboard/configuration.h"
+
+namespace starboard {
+namespace elf_loader {
+
+class ElfLoaderImpl;
+
+// A loader for ELF dynamic shared library.
+class ElfLoader {
+ public:
+ ElfLoader();
+ ~ElfLoader();
+
+ // Gets the current instance of the ELF Loader. SB_DCHECKS if called before
+ // the ELF Loader has been constructed.
+ static ElfLoader* Get();
+
+ // Loads the shared library. Returns false if |library_path| or |content_path|
+ // is empty, or if the library could not be loaded.
+ // An optional |custom_get_extension| function pointer can be passed in order
+ // to override the |SbSystemGetExtension| function.
+ bool Load(const std::string& library_path,
+ const std::string& content_path,
+ bool is_relative_path,
+ const void* (*custom_get_extension)(const char* name) = NULL);
+
+ // Looks up the symbol address in the
+ // shared library.
+ void* LookupSymbol(const char* symbol);
+
+ const std::string& GetLibraryPath() const { return library_path_; }
+ const std::string& GetContentPath() const { return content_path_; }
+
+ private:
+ // Adjusts |path| to be relative to the content directory of the ELF Loader.
+ // Returns an empty string on error.
+ std::string MakeRelativeToContentPath(const std::string& path);
+
+ // The paths to the loaded shared library and it's content.
+ std::string library_path_;
+ std::string content_path_;
+
+ // The ELF Loader implementation.
+ scoped_ptr<ElfLoaderImpl> impl_;
+
+ // The single ELF Loader instance.
+ static ElfLoader* g_instance;
+
+ SB_DISALLOW_COPY_AND_ASSIGN(ElfLoader);
+};
+
+} // namespace elf_loader
+} // namespace starboard
+
+#endif // STARBOARD_ELF_LOADER_ELF_LOADER_H_
diff --git a/src/starboard/elf_loader/elf_loader_impl.cc b/src/starboard/elf_loader/elf_loader_impl.cc
new file mode 100644
index 0000000..091b154
--- /dev/null
+++ b/src/starboard/elf_loader/elf_loader_impl.cc
@@ -0,0 +1,146 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/elf_loader/elf_loader_impl.h"
+#include "starboard/common/log.h"
+#include "starboard/elf_loader/elf.h"
+#include "starboard/elf_loader/file_impl.h"
+#include "starboard/elf_loader/log.h"
+#include "starboard/memory.h"
+#include "starboard/string.h"
+
+namespace starboard {
+namespace elf_loader {
+
+ElfLoaderImpl::ElfLoaderImpl() {
+#if SB_API_VERSION < 12 || \
+ !(SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)) || \
+ !SB_CAN(MAP_EXECUTABLE_MEMORY)
+ SB_CHECK(false) << "The elf_loader requires SB_API_VERSION >= 12 with "
+ "executable memory map support!";
+#endif
+}
+
+bool ElfLoaderImpl::Load(
+ const char* name,
+ const void* (*custom_get_extension)(const char* name)) {
+ SB_LOG(INFO) << "Loading: " << name;
+ elf_file_.reset(new FileImpl());
+ elf_file_->Open(name);
+
+ elf_header_loader_.reset(new ElfHeader());
+ if (!elf_header_loader_->LoadElfHeader(elf_file_.get())) {
+ SB_LOG(ERROR) << "Failed to loaded ELF header";
+ return false;
+ }
+
+ SB_DLOG(INFO) << "Loaded ELF header";
+
+ program_table_.reset(new ProgramTable());
+ program_table_->LoadProgramHeader(elf_header_loader_->GetHeader(),
+ elf_file_.get());
+
+ SB_DLOG(INFO) << "Loaded Program header";
+
+ if (!program_table_->ReserveLoadMemory()) {
+ SB_LOG(ERROR) << "Failed to reserve memory space";
+ return false;
+ }
+
+ SB_DLOG(INFO) << "Reserved address space";
+
+ if (!program_table_->LoadSegments(elf_file_.get())) {
+ SB_LOG(ERROR) << "Failed to load segments";
+ return false;
+ }
+ SB_DLOG(INFO) << "Loaded segments";
+
+ Dyn* dynamic = NULL;
+ size_t dynamic_count = 0;
+ Word dynamic_flags = 0;
+ program_table_->GetDynamicSection(&dynamic, &dynamic_count, &dynamic_flags);
+ if (!dynamic) {
+ SB_LOG(ERROR) << "No PT_DYNAMIC section!";
+ return false;
+ }
+ dynamic_section_.reset(
+ new DynamicSection(program_table_->GetBaseMemoryAddress(), dynamic,
+ dynamic_count, dynamic_flags));
+ if (!dynamic_section_->InitDynamicSection()) {
+ SB_LOG(ERROR) << "Failed to initialize dynamic section";
+ return false;
+ }
+ SB_DLOG(INFO) << "Initialized dynamic section";
+
+ exported_symbols_.reset(new ExportedSymbols(custom_get_extension));
+ relocations_.reset(new Relocations(program_table_->GetBaseMemoryAddress(),
+ dynamic_section_.get(),
+ exported_symbols_.get()));
+ if (!relocations_->InitRelocations()) {
+ SB_LOG(ERROR) << "Failed to initialize relocations";
+ return false;
+ }
+ if (relocations_->HasTextRelocations()) {
+ SB_DLOG(INFO) << "HasTextRelocations";
+ // Adjust the memory protection to its to allow modifications.
+ if (program_table_->AdjustMemoryProtectionOfReadOnlySegments(
+ kSbMemoryMapProtectWrite) < 0) {
+ SB_LOG(ERROR) << "Unable to make segments writable";
+ return false;
+ }
+ }
+ SB_DLOG(INFO) << "Loaded relocations";
+ if (!relocations_->ApplyAllRelocations()) {
+ SB_LOG(ERROR) << "Failed to apply relocations";
+ return false;
+ }
+
+ if (relocations_->HasTextRelocations()) {
+ // Restores the memory protection to its original state.
+#if SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)
+ if (program_table_->AdjustMemoryProtectionOfReadOnlySegments(
+ kSbMemoryMapProtectReserved) < 0) {
+ SB_LOG(ERROR) << "Unable to restore segment protection";
+ return false;
+ }
+#endif
+ }
+
+ SB_DLOG(INFO) << "Applied relocations";
+
+ program_table_->PublishEvergreenInfo(name);
+ SB_DLOG(INFO) << "Published Evergreen Info";
+
+ SB_DLOG(INFO) << "Call constructors";
+ dynamic_section_->CallConstructors();
+
+ SB_DLOG(INFO) << "Finished loading";
+
+ return true;
+}
+void* ElfLoaderImpl::LookupSymbol(const char* symbol) {
+ const Sym* sym = dynamic_section_->LookupByName(symbol);
+ void* address = NULL;
+ if (sym) {
+ address = reinterpret_cast<void*>(program_table_->GetBaseMemoryAddress() +
+ sym->st_value);
+ }
+ return address;
+}
+
+ElfLoaderImpl::~ElfLoaderImpl() {
+ dynamic_section_->CallDestructors();
+}
+} // namespace elf_loader
+} // namespace starboard
diff --git a/src/starboard/elf_loader/elf_loader_impl.h b/src/starboard/elf_loader/elf_loader_impl.h
new file mode 100644
index 0000000..da9c5f3
--- /dev/null
+++ b/src/starboard/elf_loader/elf_loader_impl.h
@@ -0,0 +1,54 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_ELF_LOADER_ELF_LOADER_IMPL_H_
+#define STARBOARD_ELF_LOADER_ELF_LOADER_IMPL_H_
+
+#include "starboard/common/scoped_ptr.h"
+#include "starboard/elf_loader/dynamic_section.h"
+#include "starboard/elf_loader/elf.h"
+#include "starboard/elf_loader/elf_hash_table.h"
+#include "starboard/elf_loader/elf_header.h"
+#include "starboard/elf_loader/exported_symbols.h"
+#include "starboard/elf_loader/file.h"
+#include "starboard/elf_loader/gnu_hash_table.h"
+#include "starboard/elf_loader/program_table.h"
+#include "starboard/elf_loader/relocations.h"
+
+namespace starboard {
+namespace elf_loader {
+
+// Implementation of the elf loader.
+class ElfLoaderImpl {
+ public:
+ ElfLoaderImpl();
+ bool Load(const char* file_name,
+ const void* (*custom_get_extension)(const char* name));
+ void* LookupSymbol(const char* symbol);
+ ~ElfLoaderImpl();
+
+ private:
+ scoped_ptr<File> elf_file_;
+ scoped_ptr<ElfHeader> elf_header_loader_;
+ scoped_ptr<ProgramTable> program_table_;
+ scoped_ptr<DynamicSection> dynamic_section_;
+ scoped_ptr<ExportedSymbols> exported_symbols_;
+ scoped_ptr<Relocations> relocations_;
+
+ SB_DISALLOW_COPY_AND_ASSIGN(ElfLoaderImpl);
+};
+
+} // namespace elf_loader
+} // namespace starboard
+#endif // STARBOARD_ELF_LOADER_ELF_LOADER_IMPL_H_
diff --git a/src/starboard/linux/x64x11/mozjs/thread_types_public.h b/src/starboard/elf_loader/elf_loader_switches.cc
similarity index 63%
copy from src/starboard/linux/x64x11/mozjs/thread_types_public.h
copy to src/starboard/elf_loader/elf_loader_switches.cc
index 32fbba2..d859d86 100644
--- a/src/starboard/linux/x64x11/mozjs/thread_types_public.h
+++ b/src/starboard/elf_loader/elf_loader_switches.cc
@@ -1,4 +1,4 @@
-// Copyright 2018 The Cobalt Authors. All Rights Reserved.
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,9 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef STARBOARD_LINUX_X64X11_MOZJS_THREAD_TYPES_PUBLIC_H_
-#define STARBOARD_LINUX_X64X11_MOZJS_THREAD_TYPES_PUBLIC_H_
+#include "starboard/elf_loader/elf_loader_switches.h"
-#include "starboard/linux/shared/thread_types_public.h"
+namespace starboard {
+namespace elf_loader {
-#endif // STARBOARD_LINUX_X64X11_MOZJS_THREAD_TYPES_PUBLIC_H_
+const char kEvergreenLibrary[] = "evergreen_library";
+const char kEvergreenContent[] = "evergreen_content";
+
+} // namespace elf_loader
+} // namespace starboard
diff --git a/src/starboard/elf_loader/elf_loader_switches.h b/src/starboard/elf_loader/elf_loader_switches.h
new file mode 100644
index 0000000..be37d59
--- /dev/null
+++ b/src/starboard/elf_loader/elf_loader_switches.h
@@ -0,0 +1,29 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_ELF_LOADER_ELF_LOADER_SWITCHES_H_
+#define STARBOARD_ELF_LOADER_ELF_LOADER_SWITCHES_H_
+
+#include "starboard/configuration.h"
+
+namespace starboard {
+namespace elf_loader {
+
+extern const char kEvergreenLibrary[];
+extern const char kEvergreenContent[];
+
+} // namespace elf_loader
+} // namespace starboard
+
+#endif // STARBOARD_ELF_LOADER_ELF_LOADER_SWITCHES_H_
diff --git a/src/starboard/elf_loader/elf_loader_sys_impl.cc b/src/starboard/elf_loader/elf_loader_sys_impl.cc
new file mode 100644
index 0000000..00c26c6
--- /dev/null
+++ b/src/starboard/elf_loader/elf_loader_sys_impl.cc
@@ -0,0 +1,61 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/elf_loader/elf_loader_sys_impl.h"
+
+#include <dlfcn.h>
+
+#include "starboard/common/log.h"
+#include "starboard/elf_loader/exported_symbols.h"
+
+namespace starboard {
+namespace elf_loader {
+
+ElfLoaderImpl::ElfLoaderImpl() {}
+
+bool ElfLoaderImpl::Load(
+ const char* name,
+ const void* (*custom_get_extension)(const char* name)) {
+ SB_UNREFERENCED_PARAMETER(custom_get_extension);
+ SB_LOG(INFO) << "Loading: " << name;
+
+ // Creating the instance forces the binary to keep all the symbols.
+ ExportedSymbols symbols;
+
+ handle_ = dlopen(name, RTLD_NOW);
+ if (!handle_) {
+ SB_LOG(ERROR) << "dlopen failure: " << dlerror();
+ return false;
+ }
+ return true;
+}
+
+void* ElfLoaderImpl::LookupSymbol(const char* symbol) {
+ if (handle_) {
+ void* p = dlsym(handle_, symbol);
+ if (!p) {
+ SB_LOG(ERROR) << "dlsym failure: " << dlerror();
+ }
+ return p;
+ }
+ return NULL;
+}
+
+ElfLoaderImpl::~ElfLoaderImpl() {
+ if (handle_) {
+ dlclose(handle_);
+ }
+}
+} // namespace elf_loader
+} // namespace starboard
diff --git a/src/starboard/elf_loader/elf_loader_sys_impl.h b/src/starboard/elf_loader/elf_loader_sys_impl.h
new file mode 100644
index 0000000..bcc7af0
--- /dev/null
+++ b/src/starboard/elf_loader/elf_loader_sys_impl.h
@@ -0,0 +1,40 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_ELF_LOADER_ELF_LOADER_SYS_IMPL_H_
+#define STARBOARD_ELF_LOADER_ELF_LOADER_SYS_IMPL_H_
+
+#include "starboard/common/scoped_ptr.h"
+
+namespace starboard {
+namespace elf_loader {
+
+// Implementation of the elf loader.
+class ElfLoaderImpl {
+ public:
+ ElfLoaderImpl();
+ bool Load(const char* file_name,
+ const void* (*custom_get_extension)(const char* name) = NULL);
+ void* LookupSymbol(const char* symbol);
+ ~ElfLoaderImpl();
+
+ private:
+ void* handle_;
+
+ SB_DISALLOW_COPY_AND_ASSIGN(ElfLoaderImpl);
+};
+
+} // namespace elf_loader
+} // namespace starboard
+#endif // STARBOARD_ELF_LOADER_ELF_LOADER_SYS_IMPL_H_
diff --git a/src/starboard/elf_loader/elf_loader_test.cc b/src/starboard/elf_loader/elf_loader_test.cc
new file mode 100644
index 0000000..11c31f5
--- /dev/null
+++ b/src/starboard/elf_loader/elf_loader_test.cc
@@ -0,0 +1,43 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/elf_loader/elf_loader_impl.h"
+
+#include "starboard/common/scoped_ptr.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if SB_API_VERSION >= 12 && \
+ (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)) && \
+ SB_CAN(MAP_EXECUTABLE_MEMORY)
+namespace starboard {
+namespace elf_loader {
+
+namespace {
+
+// TODO: implement using real shared library fro the file system.
+class ElfLoaderTest : public ::testing::Test {
+ protected:
+ ElfLoaderTest() {}
+ ~ElfLoaderTest() {}
+};
+
+TEST_F(ElfLoaderTest, Initialize) {
+ EXPECT_TRUE(true);
+}
+
+} // namespace
+} // namespace elf_loader
+} // namespace starboard
+#endif // SB_API_VERSION >= 12 && (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION
+ // || SB_HAS(MMAP)) && SB_CAN(MAP_EXECUTABLE_MEMORY)
diff --git a/src/starboard/elf_loader/evergreen_config.cc b/src/starboard/elf_loader/evergreen_config.cc
new file mode 100644
index 0000000..b0823e5
--- /dev/null
+++ b/src/starboard/elf_loader/evergreen_config.cc
@@ -0,0 +1,51 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/elf_loader/evergreen_config.h"
+
+#include "starboard/common/log.h"
+#include "starboard/common/mutex.h"
+#include "starboard/common/scoped_ptr.h"
+#include "starboard/memory.h"
+#include "starboard/string.h"
+
+namespace starboard {
+namespace elf_loader {
+
+static starboard::Mutex g_evergreen_config_mutex;
+static scoped_ptr<EvergreenConfig> g_evergreen_config;
+
+void EvergreenConfig::Create(
+ const char* library_path,
+ const char* content_path,
+ const void* (*custom_get_extension)(const char* name)) {
+ starboard::ScopedLock lock(g_evergreen_config_mutex);
+ g_evergreen_config.reset(
+ new EvergreenConfig(library_path, content_path, custom_get_extension));
+}
+
+const EvergreenConfig* EvergreenConfig::GetInstance() {
+ starboard::ScopedLock lock(g_evergreen_config_mutex);
+ return g_evergreen_config.get();
+}
+
+EvergreenConfig::EvergreenConfig(
+ const char* library_path,
+ const char* content_path,
+ const void* (*custom_get_extension)(const char* name))
+ : library_path_(library_path),
+ content_path_(content_path),
+ custom_get_extension_(custom_get_extension) {}
+} // namespace elf_loader
+} // namespace starboard
diff --git a/src/starboard/raspi/2/mozjs/starboard_platform.gyp b/src/starboard/elf_loader/evergreen_config.gyp
similarity index 62%
rename from src/starboard/raspi/2/mozjs/starboard_platform.gyp
rename to src/starboard/elf_loader/evergreen_config.gyp
index 53d18eb..05846f4 100644
--- a/src/starboard/raspi/2/mozjs/starboard_platform.gyp
+++ b/src/starboard/elf_loader/evergreen_config.gyp
@@ -1,4 +1,4 @@
-# Copyright 2018 The Cobalt Authors. All Rights Reserved.
+# Copyright 2020 The Cobalt Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -11,8 +11,18 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+
+# This files contains all targets that should be created by gyp_cobalt by
+# default.
{
- 'includes': [
- '../../shared/starboard_platform.gypi',
+ 'targets': [
+ {
+ 'target_name': 'evergreen_config',
+ 'type': 'static_library',
+ 'sources': [
+ 'evergreen_config.h',
+ 'evergreen_config.cc',
+ ],
+ },
],
}
diff --git a/src/starboard/elf_loader/evergreen_config.h b/src/starboard/elf_loader/evergreen_config.h
new file mode 100644
index 0000000..a2ca212
--- /dev/null
+++ b/src/starboard/elf_loader/evergreen_config.h
@@ -0,0 +1,57 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_ELF_LOADER_EVERGREEN_CONFIG_H_
+#define STARBOARD_ELF_LOADER_EVERGREEN_CONFIG_H_
+
+#include <string>
+
+#include "starboard/configuration.h"
+
+namespace starboard {
+namespace elf_loader {
+
+// This is configuration published by the Evergreen loader.
+// The Starboard implementation may customize its behavior
+// based on it e.g. override the content location in SbSystemGetPath or
+// add an custom extension to SbSystemGetExtension.
+struct EvergreenConfig {
+ // Factory method to create the configuration.
+ static void Create(const char* library_path,
+ const char* content_path,
+ const void* (*custom_get_extension_)(const char* name));
+
+ // Retrieves the singleton instance of the configuration.
+ static const EvergreenConfig* GetInstance();
+
+ // Absolute path to the shared library binary.
+ const std::string library_path_;
+
+ // Absolute path to the content directory for this binary.
+ const std::string content_path_;
+
+ // Getter to a custom extension to be added to Starboard.
+ const void* (*custom_get_extension_)(const char* name);
+
+ private:
+ EvergreenConfig(const char* library_path,
+ const char* content_path,
+ const void* (*custom_get_extension_)(const char* name));
+ SB_DISALLOW_COPY_AND_ASSIGN(EvergreenConfig);
+};
+
+} // namespace elf_loader
+} // namespace starboard
+
+#endif // STARBOARD_ELF_LOADER_EVERGREEN_CONFIG_H_
diff --git a/src/starboard/elf_loader/evergreen_info.cc b/src/starboard/elf_loader/evergreen_info.cc
new file mode 100644
index 0000000..875d215
--- /dev/null
+++ b/src/starboard/elf_loader/evergreen_info.cc
@@ -0,0 +1,70 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/elf_loader/evergreen_info.h"
+
+#include "starboard/atomic.h"
+#include "starboard/common/log.h"
+#include "starboard/memory.h"
+#include "starboard/string.h"
+
+static EvergreenInfo g_evergreen_info;
+static bool g_valid_info = false;
+static SbAtomic32 g_busy = 0;
+
+bool SetEvergreenInfo(const EvergreenInfo* evergreen_info) {
+ // Set the busy flag or bail.
+ if (SbAtomicNoBarrier_CompareAndSwap(&g_busy, 0, 1) == 1) {
+ // Bailing out is OK as the process crashed
+ // before we launched the application and in that
+ // case the evergreen information is not needed.
+ return false;
+ }
+ if (evergreen_info != NULL && evergreen_info->base_address != 0 &&
+ SbStringGetLength(evergreen_info->file_path_buf) != 0) {
+ g_evergreen_info = *evergreen_info;
+ g_valid_info = true;
+ } else {
+ g_valid_info = false;
+ }
+ // Publish local memory changes to all threads.
+ SbAtomicMemoryBarrier();
+
+ // Clear the busy flag.
+ SbAtomicNoBarrier_CompareAndSwap(&g_busy, 1, 0);
+ return true;
+}
+
+bool GetEvergreenInfo(EvergreenInfo* evergreen_info) {
+ if (evergreen_info == NULL) {
+ return false;
+ }
+
+ // Set the busy flag or bail.
+ if (SbAtomicNoBarrier_CompareAndSwap(&g_busy, 0, 1) == 1) {
+ return false;
+ }
+
+ // Make sure all memory changes are visible to the current thread.
+ SbAtomicMemoryBarrier();
+ if (!g_valid_info) {
+ return false;
+ }
+
+ *evergreen_info = g_evergreen_info;
+
+ // Clear the busy flag.
+ SbAtomicNoBarrier_CompareAndSwap(&g_busy, 1, 0);
+ return true;
+}
diff --git a/src/starboard/linux/x64x11/mozjs/starboard_platform_tests.gyp b/src/starboard/elf_loader/evergreen_info.gyp
similarity index 62%
copy from src/starboard/linux/x64x11/mozjs/starboard_platform_tests.gyp
copy to src/starboard/elf_loader/evergreen_info.gyp
index 0ea8622..d6c66e3 100644
--- a/src/starboard/linux/x64x11/mozjs/starboard_platform_tests.gyp
+++ b/src/starboard/elf_loader/evergreen_info.gyp
@@ -1,4 +1,4 @@
-# Copyright 2018 The Cobalt Authors. All Rights Reserved.
+# Copyright 2020 The Cobalt Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -11,8 +11,18 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+
+# This files contains all targets that should be created by gyp_cobalt by
+# default.
{
- 'includes': [
- '<(DEPTH)/starboard/linux/shared/starboard_platform_tests.gypi',
+ 'targets': [
+ {
+ 'target_name': 'evergreen_info',
+ 'type': 'static_library',
+ 'sources': [
+ 'evergreen_info.h',
+ 'evergreen_info.cc',
+ ],
+ },
],
}
diff --git a/src/starboard/elf_loader/evergreen_info.h b/src/starboard/elf_loader/evergreen_info.h
new file mode 100644
index 0000000..cca62e0
--- /dev/null
+++ b/src/starboard/elf_loader/evergreen_info.h
@@ -0,0 +1,73 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// An implementation of storage that just uses the filesystem. The User
+// implementation must implement a way to get the user's home directory.
+
+#ifndef STARBOARD_ELF_LOADER_EVERGREEN_INFO_H_
+#define STARBOARD_ELF_LOADER_EVERGREEN_INFO_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// This is duplicate constant for use from signal-safe code in
+// the starboard implementation.
+#define EVERGREEN_FILE_PATH_MAX_SIZE 4096
+
+#define IS_EVERGREEN_ADDRESS(address, evergreen_info) \
+ (evergreen_info.base_address != 0 && \
+ reinterpret_cast<uint64_t>(address) >= evergreen_info.base_address && \
+ (reinterpret_cast<uint64_t>(address) - evergreen_info.base_address) < \
+ evergreen_info.load_size)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Evergreen shared library memory mapping information used for
+// stack unwinding and symbolizing.
+typedef struct EvergreenInfo {
+ // File path of the shared library file.
+ char file_path_buf[EVERGREEN_FILE_PATH_MAX_SIZE];
+
+ // Base memory address of the mapped library.
+ uint64_t base_address;
+
+ // Size of the mapped memory.
+ size_t load_size;
+
+ // Address of the Program Header Table for the library.
+ uint64_t phdr_table;
+
+ // Number of items in the Program Header Table.
+ size_t phdr_table_num;
+} EvergreenInfo;
+
+// Set the Evergreen information. Should be called only from the
+// elf_loader module. Passing NULL clears the currently stored
+// information.
+// Returns true if if successful.
+bool SetEvergreenInfo(const EvergreenInfo* evergreen_info);
+
+// Retrieve the Evergreen information. The implementation must be
+// signal-safe. The main clients for this call are stack unwinding
+// libraries and symbolization routines.
+// Returns true if the Evergreen info is available.
+bool GetEvergreenInfo(EvergreenInfo* evergreen_info);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // STARBOARD_ELF_LOADER_EVERGREEN_INFO_H_
diff --git a/src/starboard/elf_loader/exported_symbols.cc b/src/starboard/elf_loader/exported_symbols.cc
new file mode 100644
index 0000000..492731e
--- /dev/null
+++ b/src/starboard/elf_loader/exported_symbols.cc
@@ -0,0 +1,466 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/elf_loader/exported_symbols.h"
+
+#include "starboard/accessibility.h"
+#include "starboard/audio_sink.h"
+#include "starboard/blitter.h"
+#include "starboard/byte_swap.h"
+#include "starboard/character.h"
+#include "starboard/condition_variable.h"
+#include "starboard/configuration.h"
+#include "starboard/configuration_constants.h"
+#include "starboard/cpu_features.h"
+#include "starboard/decode_target.h"
+#include "starboard/directory.h"
+#include "starboard/double.h"
+#include "starboard/egl.h"
+#include "starboard/event.h"
+#include "starboard/file.h"
+#include "starboard/gles.h"
+#include "starboard/image.h"
+#include "starboard/log.h"
+#include "starboard/memory.h"
+#include "starboard/memory_reporter.h"
+#include "starboard/microphone.h"
+#include "starboard/mutex.h"
+#include "starboard/once.h"
+#include "starboard/player.h"
+#include "starboard/socket.h"
+#include "starboard/socket_waiter.h"
+#include "starboard/speech_recognizer.h"
+#include "starboard/speech_synthesis.h"
+#include "starboard/storage.h"
+#include "starboard/string.h"
+#include "starboard/system.h"
+#include "starboard/thread.h"
+#include "starboard/time_zone.h"
+#include "starboard/ui_navigation.h"
+#include "starboard/window.h"
+
+#define REGISTER_SYMBOL(s) \
+ do { \
+ map_[#s] = reinterpret_cast<const void*>(&s); \
+ } while (0)
+
+namespace starboard {
+namespace elf_loader {
+
+ExportedSymbols::ExportedSymbols(
+ const void* (*custom_get_extension)(const char* name)) {
+ REGISTER_SYMBOL(SbAccessibilityGetDisplaySettings);
+ REGISTER_SYMBOL(SbAccessibilityGetTextToSpeechSettings);
+ REGISTER_SYMBOL(SbAudioSinkCreate);
+ REGISTER_SYMBOL(SbAudioSinkDestroy);
+ REGISTER_SYMBOL(SbAudioSinkGetMaxChannels);
+ REGISTER_SYMBOL(SbAudioSinkGetNearestSupportedSampleFrequency);
+ REGISTER_SYMBOL(SbAudioSinkIsAudioFrameStorageTypeSupported);
+ REGISTER_SYMBOL(SbAudioSinkIsAudioSampleTypeSupported);
+ REGISTER_SYMBOL(SbAudioSinkIsValid);
+ REGISTER_SYMBOL(SbByteSwapS16);
+ REGISTER_SYMBOL(SbByteSwapS32);
+ REGISTER_SYMBOL(SbByteSwapS64);
+ REGISTER_SYMBOL(SbByteSwapU16);
+ REGISTER_SYMBOL(SbByteSwapU32);
+ REGISTER_SYMBOL(SbByteSwapU64);
+ REGISTER_SYMBOL(SbCharacterIsAlphanumeric);
+ REGISTER_SYMBOL(SbCharacterIsDigit);
+ REGISTER_SYMBOL(SbCharacterIsHexDigit);
+ REGISTER_SYMBOL(SbCharacterIsSpace);
+ REGISTER_SYMBOL(SbCharacterIsUpper);
+ REGISTER_SYMBOL(SbCharacterToLower);
+ REGISTER_SYMBOL(SbCharacterToUpper);
+ REGISTER_SYMBOL(SbConditionVariableBroadcast);
+ REGISTER_SYMBOL(SbConditionVariableCreate);
+ REGISTER_SYMBOL(SbConditionVariableDestroy);
+ REGISTER_SYMBOL(SbConditionVariableSignal);
+ REGISTER_SYMBOL(SbConditionVariableWait);
+ REGISTER_SYMBOL(SbConditionVariableWaitTimed);
+ REGISTER_SYMBOL(SbDecodeTargetGetInfo);
+ REGISTER_SYMBOL(SbDecodeTargetRelease);
+ REGISTER_SYMBOL(SbDirectoryCanOpen);
+ REGISTER_SYMBOL(SbDirectoryClose);
+ REGISTER_SYMBOL(SbDirectoryCreate);
+ REGISTER_SYMBOL(SbDirectoryGetNext);
+ REGISTER_SYMBOL(SbDirectoryOpen);
+ REGISTER_SYMBOL(SbDoubleAbsolute);
+ REGISTER_SYMBOL(SbDoubleExponent);
+ REGISTER_SYMBOL(SbDoubleFloor);
+ REGISTER_SYMBOL(SbDoubleIsFinite);
+ REGISTER_SYMBOL(SbDoubleIsNan);
+ REGISTER_SYMBOL(SbDrmCloseSession);
+ REGISTER_SYMBOL(SbDrmCreateSystem);
+ REGISTER_SYMBOL(SbDrmDestroySystem);
+ REGISTER_SYMBOL(SbDrmGenerateSessionUpdateRequest);
+ REGISTER_SYMBOL(SbDrmUpdateSession);
+ REGISTER_SYMBOL(SbEventCancel);
+ REGISTER_SYMBOL(SbEventSchedule);
+ REGISTER_SYMBOL(SbFileCanOpen);
+ REGISTER_SYMBOL(SbFileClose);
+ REGISTER_SYMBOL(SbFileDelete);
+ REGISTER_SYMBOL(SbFileExists);
+ REGISTER_SYMBOL(SbFileFlush);
+ REGISTER_SYMBOL(SbFileGetInfo);
+ REGISTER_SYMBOL(SbFileGetPathInfo);
+ REGISTER_SYMBOL(SbFileModeStringToFlags);
+ REGISTER_SYMBOL(SbFileOpen);
+ REGISTER_SYMBOL(SbFileRead);
+ REGISTER_SYMBOL(SbFileSeek);
+ REGISTER_SYMBOL(SbFileTruncate);
+ REGISTER_SYMBOL(SbFileWrite);
+ REGISTER_SYMBOL(SbMediaGetAudioConfiguration);
+ REGISTER_SYMBOL(SbMediaGetAudioOutputCount);
+ REGISTER_SYMBOL(SbMediaIsOutputProtected);
+ REGISTER_SYMBOL(SbMediaIsSupported);
+ REGISTER_SYMBOL(SbMediaSetOutputProtection);
+ REGISTER_SYMBOL(SbMemoryAllocate);
+ REGISTER_SYMBOL(SbMemoryAllocateAligned);
+ REGISTER_SYMBOL(SbMemoryAllocateNoReport);
+ REGISTER_SYMBOL(SbMemoryDeallocate);
+ REGISTER_SYMBOL(SbMemoryDeallocateAligned);
+ REGISTER_SYMBOL(SbMemoryDeallocateNoReport);
+ REGISTER_SYMBOL(SbMemoryReallocate);
+ REGISTER_SYMBOL(SbMemorySetReporter);
+ REGISTER_SYMBOL(SbImageDecode);
+ REGISTER_SYMBOL(SbImageIsDecodeSupported);
+ REGISTER_SYMBOL(SbLog);
+ REGISTER_SYMBOL(SbLogFlush);
+ REGISTER_SYMBOL(SbLogFormat);
+ REGISTER_SYMBOL(SbLogIsTty);
+ REGISTER_SYMBOL(SbLogRaw);
+ REGISTER_SYMBOL(SbLogRawDumpStack);
+ REGISTER_SYMBOL(SbLogRawFormat);
+ REGISTER_SYMBOL(SbMediaCanPlayMimeAndKeySystem);
+ REGISTER_SYMBOL(SbMemoryAllocateAlignedUnchecked);
+ REGISTER_SYMBOL(SbMemoryAllocateUnchecked);
+ REGISTER_SYMBOL(SbMemoryCompare);
+ REGISTER_SYMBOL(SbMemoryCopy);
+ REGISTER_SYMBOL(SbMemoryFindByte);
+ REGISTER_SYMBOL(SbMemoryFree);
+ REGISTER_SYMBOL(SbMemoryFreeAligned);
+ REGISTER_SYMBOL(SbMemoryGetStackBounds);
+ REGISTER_SYMBOL(SbMemoryMove);
+ REGISTER_SYMBOL(SbMemoryReallocateUnchecked);
+ REGISTER_SYMBOL(SbMemorySet);
+ REGISTER_SYMBOL(SbMutexAcquire);
+ REGISTER_SYMBOL(SbMutexAcquireTry);
+ REGISTER_SYMBOL(SbMutexCreate);
+ REGISTER_SYMBOL(SbMutexDestroy);
+ REGISTER_SYMBOL(SbMutexRelease);
+ REGISTER_SYMBOL(SbOnce);
+ REGISTER_SYMBOL(SbPlayerCreate);
+ REGISTER_SYMBOL(SbPlayerDestroy);
+ REGISTER_SYMBOL(SbPlayerGetCurrentFrame);
+ REGISTER_SYMBOL(SbPlayerSetBounds);
+ REGISTER_SYMBOL(SbPlayerSetPlaybackRate);
+ REGISTER_SYMBOL(SbPlayerSetVolume);
+ REGISTER_SYMBOL(SbPlayerWriteEndOfStream);
+ REGISTER_SYMBOL(SbSocketAccept);
+ REGISTER_SYMBOL(SbSocketBind);
+ REGISTER_SYMBOL(SbSocketClearLastError);
+ REGISTER_SYMBOL(SbSocketConnect);
+ REGISTER_SYMBOL(SbSocketCreate);
+ REGISTER_SYMBOL(SbSocketDestroy);
+ REGISTER_SYMBOL(SbSocketFreeResolution);
+ REGISTER_SYMBOL(SbSocketGetInterfaceAddress);
+ REGISTER_SYMBOL(SbSocketGetLastError);
+ REGISTER_SYMBOL(SbSocketGetLocalAddress);
+ REGISTER_SYMBOL(SbSocketIsConnected);
+ REGISTER_SYMBOL(SbSocketIsConnectedAndIdle);
+ REGISTER_SYMBOL(SbSocketJoinMulticastGroup);
+ REGISTER_SYMBOL(SbSocketListen);
+ REGISTER_SYMBOL(SbSocketReceiveFrom);
+ REGISTER_SYMBOL(SbSocketResolve);
+ REGISTER_SYMBOL(SbSocketSendTo);
+ REGISTER_SYMBOL(SbSocketSetBroadcast);
+ REGISTER_SYMBOL(SbSocketSetReceiveBufferSize);
+ REGISTER_SYMBOL(SbSocketSetReuseAddress);
+ REGISTER_SYMBOL(SbSocketSetSendBufferSize);
+ REGISTER_SYMBOL(SbSocketSetTcpKeepAlive);
+ REGISTER_SYMBOL(SbSocketSetTcpNoDelay);
+ REGISTER_SYMBOL(SbSocketSetTcpWindowScaling);
+ REGISTER_SYMBOL(SbSocketWaiterAdd);
+ REGISTER_SYMBOL(SbSocketWaiterCreate);
+ REGISTER_SYMBOL(SbSocketWaiterDestroy);
+ REGISTER_SYMBOL(SbSocketWaiterRemove);
+ REGISTER_SYMBOL(SbSocketWaiterWait);
+ REGISTER_SYMBOL(SbSocketWaiterWaitTimed);
+ REGISTER_SYMBOL(SbSocketWaiterWakeUp);
+ REGISTER_SYMBOL(SbStorageCloseRecord);
+ REGISTER_SYMBOL(SbStorageDeleteRecord);
+ REGISTER_SYMBOL(SbStorageGetRecordSize);
+ REGISTER_SYMBOL(SbStorageOpenRecord);
+ REGISTER_SYMBOL(SbStorageReadRecord);
+ REGISTER_SYMBOL(SbStorageWriteRecord);
+ REGISTER_SYMBOL(SbStringCompare);
+ REGISTER_SYMBOL(SbStringCompareAll);
+ REGISTER_SYMBOL(SbStringCompareNoCase);
+ REGISTER_SYMBOL(SbStringCompareNoCaseN);
+ REGISTER_SYMBOL(SbStringCompareWide);
+ REGISTER_SYMBOL(SbStringConcat);
+ REGISTER_SYMBOL(SbStringConcatWide);
+ REGISTER_SYMBOL(SbStringCopy);
+ REGISTER_SYMBOL(SbStringCopyWide);
+ REGISTER_SYMBOL(SbStringDuplicate);
+ REGISTER_SYMBOL(SbStringFindCharacter);
+ REGISTER_SYMBOL(SbStringFindLastCharacter);
+ REGISTER_SYMBOL(SbStringFindString);
+ REGISTER_SYMBOL(SbStringFormat);
+ REGISTER_SYMBOL(SbStringFormatWide);
+ REGISTER_SYMBOL(SbStringGetLength);
+ REGISTER_SYMBOL(SbStringGetLengthWide);
+ REGISTER_SYMBOL(SbStringParseDouble);
+ REGISTER_SYMBOL(SbStringParseSignedInteger);
+ REGISTER_SYMBOL(SbStringParseUInt64);
+ REGISTER_SYMBOL(SbStringParseUnsignedInteger);
+ REGISTER_SYMBOL(SbStringScan);
+ REGISTER_SYMBOL(SbSystemBinarySearch);
+ REGISTER_SYMBOL(SbSystemBreakIntoDebugger);
+ REGISTER_SYMBOL(SbSystemClearLastError);
+ REGISTER_SYMBOL(SbSystemGetConnectionType);
+ REGISTER_SYMBOL(SbSystemGetDeviceType);
+ REGISTER_SYMBOL(SbSystemGetErrorString);
+ REGISTER_SYMBOL(SbSystemGetLastError);
+ REGISTER_SYMBOL(SbSystemGetLocaleId);
+ REGISTER_SYMBOL(SbSystemGetNumberOfProcessors);
+ REGISTER_SYMBOL(SbSystemGetProperty);
+ REGISTER_SYMBOL(SbSystemGetRandomData);
+ REGISTER_SYMBOL(SbSystemGetRandomUInt64);
+ REGISTER_SYMBOL(SbSystemGetStack);
+ REGISTER_SYMBOL(SbSystemGetTotalCPUMemory);
+ REGISTER_SYMBOL(SbSystemGetTotalGPUMemory);
+ REGISTER_SYMBOL(SbSystemGetUsedCPUMemory);
+ REGISTER_SYMBOL(SbSystemGetUsedGPUMemory);
+ REGISTER_SYMBOL(SbSystemHasCapability);
+ REGISTER_SYMBOL(SbSystemHideSplashScreen);
+ REGISTER_SYMBOL(SbSystemIsDebuggerAttached);
+ REGISTER_SYMBOL(SbSystemRaisePlatformError);
+ REGISTER_SYMBOL(SbSystemRequestPause);
+ REGISTER_SYMBOL(SbSystemRequestStop);
+ REGISTER_SYMBOL(SbSystemRequestSuspend);
+ REGISTER_SYMBOL(SbSystemRequestUnpause);
+ REGISTER_SYMBOL(SbSystemSort);
+ REGISTER_SYMBOL(SbSystemSymbolize);
+ REGISTER_SYMBOL(SbThreadCreate);
+ REGISTER_SYMBOL(SbThreadCreateLocalKey);
+ REGISTER_SYMBOL(SbThreadDestroyLocalKey);
+ REGISTER_SYMBOL(SbThreadDetach);
+ REGISTER_SYMBOL(SbThreadGetCurrent);
+ REGISTER_SYMBOL(SbThreadGetId);
+ REGISTER_SYMBOL(SbThreadGetLocalValue);
+ REGISTER_SYMBOL(SbThreadGetName);
+ REGISTER_SYMBOL(SbThreadIsEqual);
+ REGISTER_SYMBOL(SbThreadJoin);
+ REGISTER_SYMBOL(SbThreadSetLocalValue);
+ REGISTER_SYMBOL(SbThreadSetName);
+ REGISTER_SYMBOL(SbThreadSleep);
+ REGISTER_SYMBOL(SbThreadYield);
+ REGISTER_SYMBOL(SbTimeGetMonotonicNow);
+ REGISTER_SYMBOL(SbTimeGetNow);
+ REGISTER_SYMBOL(SbTimeZoneGetCurrent);
+ REGISTER_SYMBOL(SbTimeZoneGetName);
+ REGISTER_SYMBOL(SbUserGetCurrent);
+ REGISTER_SYMBOL(SbUserGetProperty);
+ REGISTER_SYMBOL(SbUserGetPropertySize);
+ REGISTER_SYMBOL(SbUserGetSignedIn);
+ REGISTER_SYMBOL(SbWindowCreate);
+ REGISTER_SYMBOL(SbWindowDestroy);
+ REGISTER_SYMBOL(SbWindowGetPlatformHandle);
+ REGISTER_SYMBOL(SbWindowGetSize);
+ REGISTER_SYMBOL(SbWindowSetDefaultOptions);
+ REGISTER_SYMBOL(SbSystemGetPath);
+
+#if SB_API_VERSION >= 11
+ REGISTER_SYMBOL(SbGetEglInterface);
+ REGISTER_SYMBOL(SbGetGlesInterface);
+#endif // SB_API_VERSION >= 11
+
+#if SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION
+ REGISTER_SYMBOL(SbFileAtomicReplace);
+#endif // SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION
+
+#if SB_CAN(MAP_EXECUTABLE_MEMORY)
+ REGISTER_SYMBOL(SbMemoryFlush);
+#endif // SB_CAN(MAP_EXECUTABLE_MEMORY)
+
+#if SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
+ REGISTER_SYMBOL(SbPlayerGetPreferredOutputMode);
+#else
+ REGISTER_SYMBOL(SbPlayerOutputModeSupported);
+#endif
+
+#if SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)
+ REGISTER_SYMBOL(SbMemoryMap);
+ REGISTER_SYMBOL(SbMemoryUnmap);
+ REGISTER_SYMBOL(SbMemoryProtect);
+#endif // SB_HAS(MMAP)
+
+#if SB_API_VERSION >= SB_UI_NAVIGATION_VERSION
+ REGISTER_SYMBOL(SbUiNavGetInterface);
+#endif // SB_API_VERSION >= SB_UI_NAVIGATION_VERSION
+
+#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION || \
+ SB_HAS(ON_SCREEN_KEYBOARD)
+ REGISTER_SYMBOL(SbWindowBlurOnScreenKeyboard);
+ REGISTER_SYMBOL(SbWindowFocusOnScreenKeyboard);
+ REGISTER_SYMBOL(SbWindowGetOnScreenKeyboardBoundingRect);
+ REGISTER_SYMBOL(SbWindowHideOnScreenKeyboard);
+ REGISTER_SYMBOL(SbWindowIsOnScreenKeyboardShown);
+ REGISTER_SYMBOL(SbWindowSetOnScreenKeyboardKeepFocus);
+ REGISTER_SYMBOL(SbWindowShowOnScreenKeyboard);
+#if SB_API_VERSION >= 11
+ REGISTER_SYMBOL(SbWindowOnScreenKeyboardSuggestionsSupported);
+ REGISTER_SYMBOL(SbWindowUpdateOnScreenKeyboardSuggestions);
+#endif // SB_API_VERSION >= 11
+#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION ||
+ // SB_HAS(ON_SCREEN_KEYBOARD)
+
+#if SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION
+ REGISTER_SYMBOL(SbWindowOnScreenKeyboardIsSupported);
+#endif // SB_API_VERSION >= SB_ON_SCREEN_KEYBOARD_REQUIRED_VERSION
+
+#if SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS)
+ REGISTER_SYMBOL(SbAccessibilityGetCaptionSettings);
+ REGISTER_SYMBOL(SbAccessibilitySetCaptionsEnabled);
+#endif // SB_API_VERSION >= SB_CAPTIONS_REQUIRED_VERSION || SB_HAS(CAPTIONS)
+
+#if SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION || SB_HAS(MICROPHONE)
+ REGISTER_SYMBOL(SbMicrophoneClose);
+ REGISTER_SYMBOL(SbMicrophoneCreate);
+ REGISTER_SYMBOL(SbMicrophoneDestroy);
+ REGISTER_SYMBOL(SbMicrophoneGetAvailable);
+ REGISTER_SYMBOL(SbMicrophoneIsSampleRateSupported);
+ REGISTER_SYMBOL(SbMicrophoneOpen);
+ REGISTER_SYMBOL(SbMicrophoneRead);
+#endif // SB_API_VERSION >= SB_MICROPHONE_REQUIRED_VERSION ||
+ // SB_HAS(MICROPHONE)
+
+#if SB_API_VERSION >= SB_IPV6_REQUIRED_VERSION
+ REGISTER_SYMBOL(SbSocketIsIpv6Supported);
+#endif
+
+#if SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION || \
+ SB_HAS(SPEECH_SYNTHESIS)
+ REGISTER_SYMBOL(SbSpeechSynthesisCancel);
+ REGISTER_SYMBOL(SbSpeechSynthesisSpeak);
+#endif // SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION ||
+ // SB_HAS(SPEECH_SYNTHESIS)
+
+#if SB_API_VERSION >= SB_TIME_THREAD_NOW_REQUIRED_VERSION || \
+ SB_HAS(TIME_THREAD_NOW)
+ REGISTER_SYMBOL(SbTimeGetMonotonicThreadNow);
+#endif // SB_API_VERSION >= SB_TIME_THREAD_NOW_REQUIRED_VERSION ||
+ // SB_HAS(TIME_THREAD_NOW)
+
+#if SB_API_VERSION >= 5
+#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION
+ REGISTER_SYMBOL(SbSpeechRecognizerIsSupported);
+#endif
+#if SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION || \
+ SB_HAS(SPEECH_RECOGNIZER)
+ REGISTER_SYMBOL(SbSpeechRecognizerCreate);
+ REGISTER_SYMBOL(SbSpeechRecognizerDestroy);
+ REGISTER_SYMBOL(SbSpeechRecognizerStart);
+ REGISTER_SYMBOL(SbSpeechRecognizerStop);
+ REGISTER_SYMBOL(SbSpeechRecognizerCancel);
+#endif // SB_API_VERSION >= SB_SPEECH_RECOGNIZER_REQUIRED_VERSION ||
+ // SB_HAS(SPEECH_RECOGNIZER)
+#endif // SB_API_VERSION >= 5
+
+#if SB_API_VERSION >= SB_SPEECH_SYNTHESIS_REQUIRED_VERSION
+ REGISTER_SYMBOL(SbSpeechSynthesisIsSupported);
+#endif
+
+#if SB_API_VERSION >= SB_TIME_THREAD_NOW_REQUIRED_VERSION
+ REGISTER_SYMBOL(SbTimeIsTimeThreadNowSupported);
+#endif
+
+ REGISTER_SYMBOL(SbDrmIsServerCertificateUpdatable);
+ REGISTER_SYMBOL(SbDrmUpdateServerCertificate);
+ REGISTER_SYMBOL(SbMediaGetAudioBufferBudget);
+ REGISTER_SYMBOL(SbMediaGetBufferAlignment);
+ REGISTER_SYMBOL(SbMediaGetBufferAllocationUnit);
+ REGISTER_SYMBOL(SbMediaGetBufferGarbageCollectionDurationThreshold);
+ REGISTER_SYMBOL(SbMediaGetBufferPadding);
+ REGISTER_SYMBOL(SbMediaGetBufferStorageType);
+ REGISTER_SYMBOL(SbMediaGetInitialBufferCapacity);
+ REGISTER_SYMBOL(SbMediaGetMaxBufferCapacity);
+ REGISTER_SYMBOL(SbMediaGetProgressiveBufferBudget);
+ REGISTER_SYMBOL(SbMediaGetVideoBufferBudget);
+ REGISTER_SYMBOL(SbMediaIsBufferPoolAllocateOnDemand);
+ REGISTER_SYMBOL(SbMediaIsBufferUsingMemoryPool);
+ REGISTER_SYMBOL(SbPlayerGetInfo2);
+ REGISTER_SYMBOL(SbPlayerGetMaximumNumberOfSamplesPerWrite);
+ REGISTER_SYMBOL(SbPlayerSeek2);
+ REGISTER_SYMBOL(SbPlayerWriteSample2);
+ REGISTER_SYMBOL(SbSystemSupportsResume);
+
+#if SB_API_VERSION >= 11
+ REGISTER_SYMBOL(SbAudioSinkGetMinBufferSizeInFrames);
+ REGISTER_SYMBOL(SbCPUFeaturesGet);
+ REGISTER_SYMBOL(SbMediaSetAudioWriteDuration);
+ REGISTER_SYMBOL(SbSystemGetExtension);
+ REGISTER_SYMBOL(SbSystemSignWithCertificationSecretKey);
+ REGISTER_SYMBOL(SbThreadContextGetPointer);
+ REGISTER_SYMBOL(SbThreadSamplerCreate);
+ REGISTER_SYMBOL(SbThreadSamplerDestroy);
+ REGISTER_SYMBOL(SbThreadSamplerFreeze);
+ REGISTER_SYMBOL(SbThreadSamplerIsSupported);
+ REGISTER_SYMBOL(SbThreadSamplerThaw);
+ REGISTER_SYMBOL(SbWindowGetDiagonalSizeInInches);
+#endif // SB_API_VERSION >= 11
+
+#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+ REGISTER_SYMBOL(kSbDefaultMmapThreshold);
+ REGISTER_SYMBOL(kSbFileMaxName);
+ REGISTER_SYMBOL(kSbFileMaxOpen);
+ REGISTER_SYMBOL(kSbFileAltSepChar);
+ REGISTER_SYMBOL(kSbFileAltSepString);
+ REGISTER_SYMBOL(kSbFileMaxPath);
+ REGISTER_SYMBOL(kSbFileSepChar);
+ REGISTER_SYMBOL(kSbFileSepString);
+ REGISTER_SYMBOL(kSbHasAc3Audio);
+ REGISTER_SYMBOL(kSbHasAsyncAudioFramesReporting);
+ REGISTER_SYMBOL(kSbHasMediaWebmVp9Support);
+ REGISTER_SYMBOL(kSbHasThreadPrioritySupport);
+ REGISTER_SYMBOL(kSbMallocAlignment);
+ REGISTER_SYMBOL(kSbMaxThreadLocalKeys);
+ REGISTER_SYMBOL(kSbMaxThreadNameLength);
+ REGISTER_SYMBOL(kSbMediaMaxAudioBitrateInBitsPerSecond);
+ REGISTER_SYMBOL(kSbMediaMaxVideoBitrateInBitsPerSecond);
+ REGISTER_SYMBOL(kSbMediaMaximumVideoFrames);
+ REGISTER_SYMBOL(kSbMediaMaximumVideoPrerollFrames);
+ REGISTER_SYMBOL(kSbMediaVideoFrameAlignment);
+ REGISTER_SYMBOL(kSbMemoryLogPath);
+ REGISTER_SYMBOL(kSbMemoryPageSize);
+ REGISTER_SYMBOL(kSbNetworkReceiveBufferSize);
+ REGISTER_SYMBOL(kSbMaxThreads);
+ REGISTER_SYMBOL(kSbPathSepChar);
+ REGISTER_SYMBOL(kSbPathSepString);
+ REGISTER_SYMBOL(kSbPreferredRgbaByteOrder);
+ REGISTER_SYMBOL(kSbUserMaxSignedIn);
+#endif // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+}
+
+const void* ExportedSymbols::Lookup(const char* name) {
+ const void* address = map_[name];
+ // Any symbol that is not registered as part of the Starboard API in the
+ // constructor of this class is a leak, and is an error.
+ SB_CHECK(address) << "Failed to retrieve the address of '" << name << "'.";
+ return address;
+}
+
+} // namespace elf_loader
+} // namespace starboard
diff --git a/src/starboard/elf_loader/exported_symbols.h b/src/starboard/elf_loader/exported_symbols.h
new file mode 100644
index 0000000..1ffc732
--- /dev/null
+++ b/src/starboard/elf_loader/exported_symbols.h
@@ -0,0 +1,49 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_ELF_LOADER_EXPORTED_SYMBOLS_H_
+#define STARBOARD_ELF_LOADER_EXPORTED_SYMBOLS_H_
+
+#include <map>
+#include <string>
+
+#include "starboard/elf_loader/elf_hash_table.h"
+#include "starboard/elf_loader/gnu_hash_table.h"
+#include "starboard/file.h"
+
+namespace starboard {
+namespace elf_loader {
+
+// class representing all exported symbols
+// by the starboard layer.
+
+// The elf_loader will not use any other symbols
+// outside of the set represented in this class.
+class ExportedSymbols {
+ public:
+ // An optional |custom_get_extension| function pointer can be passed in order
+ // to override the |SbSystemGetExtension| function.
+ explicit ExportedSymbols(
+ const void* (*custom_get_extension)(const char* name) = NULL);
+ const void* Lookup(const char* name);
+
+ private:
+ std::map<std::string, const void*> map_;
+
+ SB_DISALLOW_COPY_AND_ASSIGN(ExportedSymbols);
+};
+
+} // namespace elf_loader
+} // namespace starboard
+#endif // STARBOARD_ELF_LOADER_EXPORTED_SYMBOLS_H_
diff --git a/src/starboard/elf_loader/file.h b/src/starboard/elf_loader/file.h
new file mode 100644
index 0000000..90296e7
--- /dev/null
+++ b/src/starboard/elf_loader/file.h
@@ -0,0 +1,44 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_ELF_LOADER_FILE_H_
+#define STARBOARD_ELF_LOADER_FILE_H_
+
+#include "starboard/elf_loader/elf.h"
+
+namespace starboard {
+namespace elf_loader {
+
+// File abstraction to be used by the ELF loader.
+// The main reason to introduce this class is to allow for
+// easy testing.
+class File {
+ public:
+ // Opens the file specified for reading.
+ virtual bool Open(const char* name) = 0;
+
+ // Reads a buffer from the file using the specified offset from the beginning
+ // of the file.
+ virtual bool ReadFromOffset(int64_t offset, char* buffer, int size) = 0;
+
+ // Closes the underlying file.
+ virtual void Close() = 0;
+
+ virtual ~File() {}
+};
+
+} // namespace elf_loader
+} // namespace starboard
+
+#endif // STARBOARD_ELF_LOADER_FILE_H_
diff --git a/src/starboard/elf_loader/file_impl.cc b/src/starboard/elf_loader/file_impl.cc
new file mode 100644
index 0000000..94ee465
--- /dev/null
+++ b/src/starboard/elf_loader/file_impl.cc
@@ -0,0 +1,76 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/elf_loader/file_impl.h"
+
+#include "starboard/common/log.h"
+#include "starboard/elf_loader/log.h"
+
+namespace {
+void LogLastError(const char* msg) {
+ const int kErrorMessageBufferSize = 256;
+ char msgbuf[kErrorMessageBufferSize];
+ SbSystemError error_code = SbSystemGetLastError();
+ if (SbSystemGetErrorString(error_code, msgbuf, kErrorMessageBufferSize) > 0) {
+ SB_LOG(ERROR) << msg << ": " << msgbuf;
+ }
+}
+} // namespace
+
+namespace starboard {
+namespace elf_loader {
+
+FileImpl::FileImpl() : file_(NULL) {}
+
+FileImpl::~FileImpl() {
+ Close();
+}
+
+bool FileImpl::Open(const char* name) {
+ SB_DLOG(INFO) << "Loading: " << name;
+ file_ = SbFileOpen(name, kSbFileOpenOnly | kSbFileRead, NULL, NULL);
+ if (!file_) {
+ return false;
+ }
+ return true;
+}
+
+bool FileImpl::ReadFromOffset(int64_t offset, char* buffer, int size) {
+ if (!file_) {
+ return false;
+ }
+ int64_t ret = SbFileSeek(file_, kSbFileFromBegin, offset);
+ SB_DLOG(INFO) << "SbFileSeek: ret=" << ret;
+ if (ret == -1) {
+ LogLastError("SbFileSeek: failed");
+ return false;
+ }
+
+ int count = SbFileReadAll(file_, buffer, size);
+ SB_DLOG(INFO) << "SbFileReadAll: count=" << count;
+ if (count == -1) {
+ LogLastError("SbFileReadAll failed");
+ return false;
+ }
+ return true;
+}
+
+void FileImpl::Close() {
+ if (file_) {
+ SbFileClose(file_);
+ }
+}
+
+} // namespace elf_loader
+} // namespace starboard
diff --git a/src/starboard/elf_loader/file_impl.h b/src/starboard/elf_loader/file_impl.h
new file mode 100644
index 0000000..9407c95
--- /dev/null
+++ b/src/starboard/elf_loader/file_impl.h
@@ -0,0 +1,44 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_ELF_LOADER_FILE_IMPL_H_
+#define STARBOARD_ELF_LOADER_FILE_IMPL_H_
+
+#include "starboard/elf_loader/elf.h"
+
+#include "starboard/elf_loader/file.h"
+#include "starboard/file.h"
+
+namespace starboard {
+namespace elf_loader {
+
+// Starboard implementation for reading a file.
+class FileImpl : public File {
+ public:
+ FileImpl();
+ ~FileImpl() override;
+ bool Open(const char* name);
+ bool ReadFromOffset(int64_t offset, char* buffer, int size);
+ void Close();
+
+ private:
+ SbFile file_;
+
+ SB_DISALLOW_COPY_AND_ASSIGN(FileImpl);
+};
+
+} // namespace elf_loader
+} // namespace starboard
+
+#endif // STARBOARD_ELF_LOADER_FILE_IMPL_H_
diff --git a/src/starboard/elf_loader/gnu_hash_table.cc b/src/starboard/elf_loader/gnu_hash_table.cc
new file mode 100644
index 0000000..9e413db
--- /dev/null
+++ b/src/starboard/elf_loader/gnu_hash_table.cc
@@ -0,0 +1,143 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/elf_loader/gnu_hash_table.h"
+#include "starboard/common/log.h"
+#include "starboard/elf_loader/log.h"
+#include "starboard/string.h"
+
+namespace starboard {
+namespace elf_loader {
+
+// Compute the GNU hash of a given symbol.
+// For more details on the hash function:
+// https://blogs.oracle.com/solaris/gnu-hash-elf-sections-v2
+static uint32_t GnuHash(const char* name) {
+ uint32_t h = 5381;
+ const uint8_t* ptr = reinterpret_cast<const uint8_t*>(name);
+ while (*ptr) {
+ h = h * 33 + *ptr++;
+ }
+ return h;
+}
+
+GnuHashTable::GnuHashTable()
+ : num_buckets_(0),
+ sym_offset_(0),
+ sym_count_(0),
+ bloom_word_mask_(0),
+ bloom_shift_(0),
+ bloom_filter_(NULL),
+ buckets_(NULL),
+ chain_(NULL) {}
+void GnuHashTable::Init(uintptr_t dt_gnu_hash) {
+ SB_DLOG(INFO) << "GnuHashTable::Init 0x" << std::hex << dt_gnu_hash;
+ sym_count_ = 0;
+
+ const uint32_t* data = reinterpret_cast<const uint32_t*>(dt_gnu_hash);
+ num_buckets_ = data[0];
+ sym_offset_ = data[1];
+
+ SB_DLOG(INFO) << "GnuHashTable::Init num_buckets_=" << num_buckets_
+ << " sym_offset_" << sym_offset_;
+ if (!num_buckets_)
+ return;
+
+ const uint32_t bloom_size = data[2];
+ SB_DLOG(INFO) << "GnuHashTable::Init bloom_size=" << bloom_size;
+ if ((bloom_size & (bloom_size - 1U)) != 0) // must be a power of 2
+ return;
+
+ bloom_word_mask_ = bloom_size - 1U;
+ bloom_shift_ = data[3];
+
+ SB_DLOG(INFO) << "GnuHashTable::Init bloom_word_mask_=" << bloom_word_mask_;
+ SB_DLOG(INFO) << "GnuHashTable::Init bloom_shift_=" << bloom_shift_;
+ bloom_filter_ = reinterpret_cast<const Addr*>(data + 4);
+ SB_DLOG(INFO) << "GnuHashTable::Init bloom_filter_=0x" << std::hex
+ << bloom_filter_;
+ buckets_ = reinterpret_cast<const uint32_t*>(bloom_filter_ + bloom_size);
+
+ SB_DLOG(INFO) << "GnuHashTable::Init buckets_=0x" << std::hex << buckets_;
+ chain_ = buckets_ + num_buckets_;
+
+ // Compute number of dynamic symbols by parsing the table.
+ if (num_buckets_ > 0) {
+ // First find the maximum index in the buckets table.
+ uint32_t max_index = buckets_[0];
+ for (size_t n = 1; n < num_buckets_; ++n) {
+ uint32_t sym_index = buckets_[n];
+ if (sym_index > max_index)
+ max_index = sym_index;
+ }
+ // Now start to look at the chain_ table from (max_index - sym_offset_)
+ // until there is a value with LSB set to 1, indicating the end of the
+ // last chain.
+ while ((chain_[max_index - sym_offset_] & 1) == 0)
+ max_index++;
+
+ sym_count_ = (max_index - sym_offset_) + 1;
+ }
+}
+
+bool GnuHashTable::IsValid() const {
+ return sym_count_ > 0;
+}
+
+const Sym* GnuHashTable::LookupByName(const char* symbol_name,
+ const Sym* symbol_table,
+ const char* string_table) const {
+ SB_DLOG(INFO) << "GnuHashTable::LookupByName: " << symbol_name;
+ uint32_t hash = GnuHash(symbol_name);
+
+ SB_DLOG(INFO) << "GnuHashTable::LookupByName: hash=" << hash;
+ SB_DLOG(INFO) << "GnuHashTable::LookupByName: ELF_BITS=" << ELF_BITS;
+
+ // First, bloom filter test.
+ Addr word = bloom_filter_[(hash / ELF_BITS) & bloom_word_mask_];
+
+ SB_DLOG(INFO) << "GnuHashTable::LookupByName: word=" << word;
+ Addr mask = (Addr(1) << (hash % ELF_BITS)) |
+ (Addr(1) << ((hash >> bloom_shift_) % ELF_BITS));
+
+ SB_DLOG(INFO) << "GnuHashTable::LookupByName: mask=" << mask;
+ if ((word & mask) != mask)
+ return NULL;
+
+ uint32_t sym_index = buckets_[hash % num_buckets_];
+ if (sym_index < sym_offset_)
+ return NULL;
+
+ // TODO: add validations of the syn_index
+ while (true) {
+ const Sym* sym = symbol_table + sym_index;
+ const uint32_t sym_hash = chain_[sym_index - sym_offset_];
+ const char* sym_name = string_table + sym->st_name;
+
+ if ((sym_hash | 1) == (hash | 1) &&
+ !SbStringCompareAll(sym_name, symbol_name)) {
+ return sym;
+ }
+
+ if (sym_hash & 1)
+ break;
+
+ sym_index++;
+ }
+
+ return NULL;
+}
+
+} // namespace elf_loader
+} // namespace starboard
diff --git a/src/starboard/elf_loader/gnu_hash_table.h b/src/starboard/elf_loader/gnu_hash_table.h
new file mode 100644
index 0000000..5bdf199
--- /dev/null
+++ b/src/starboard/elf_loader/gnu_hash_table.h
@@ -0,0 +1,66 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_ELF_LOADER_GNU_HASH_TABLE_H_
+#define STARBOARD_ELF_LOADER_GNU_HASH_TABLE_H_
+
+#include <stddef.h>
+#include "starboard/elf_loader/elf.h"
+
+namespace starboard {
+namespace elf_loader {
+
+// Models the hash table used to map symbol names to symbol entries using
+// the GNU format. This one is smaller and faster than the standard ELF one.
+class GnuHashTable {
+ public:
+ GnuHashTable();
+ // Initialize instance. |dt_gnu_hash| should be the address that the
+ // DT_GNU_HASH entry points to in the input ELF dynamic section. Call
+ // IsValid() to determine whether the table was well-formed.
+ void Init(uintptr_t dt_gnu_hash);
+
+ // Returns true iff the content of the table is valid.
+ bool IsValid() const;
+
+ // Return the index of the first dynamic symbol within the ELF symbol table.
+ size_t dyn_symbols_offset() const { return sym_offset_; }
+
+ // Number of dynamic symbols in the ELF symbol table.
+ size_t dyn_symbols_count() const { return sym_count_; }
+
+ // Lookup |symbol_name| in the table. |symbol_table| should point to the
+ // ELF symbol table, and |string_table| to the start of its string table.
+ // Returns NULL on failure.
+ const Sym* LookupByName(const char* symbol_name,
+ const Sym* symbol_table,
+ const char* string_table) const;
+
+ private:
+ uint32_t num_buckets_;
+ uint32_t sym_offset_;
+ uint32_t sym_count_;
+ uint32_t bloom_word_mask_;
+ uint32_t bloom_shift_;
+ const Addr* bloom_filter_;
+ const uint32_t* buckets_;
+ const uint32_t* chain_;
+
+ SB_DISALLOW_COPY_AND_ASSIGN(GnuHashTable);
+};
+
+} // namespace elf_loader
+} // namespace starboard
+
+#endif // STARBOARD_ELF_LOADER_GNU_HASH_TABLE_H_
diff --git a/src/starboard/linux/x64x11/mozjs/thread_types_public.h b/src/starboard/elf_loader/log.h
similarity index 64%
rename from src/starboard/linux/x64x11/mozjs/thread_types_public.h
rename to src/starboard/elf_loader/log.h
index 32fbba2..9736465 100644
--- a/src/starboard/linux/x64x11/mozjs/thread_types_public.h
+++ b/src/starboard/elf_loader/log.h
@@ -1,4 +1,4 @@
-// Copyright 2018 The Cobalt Authors. All Rights Reserved.
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,9 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef STARBOARD_LINUX_X64X11_MOZJS_THREAD_TYPES_PUBLIC_H_
-#define STARBOARD_LINUX_X64X11_MOZJS_THREAD_TYPES_PUBLIC_H_
+#ifndef STARBOARD_ELF_LOADER_LOG_H_
+#define STARBOARD_ELF_LOADER_LOG_H_
-#include "starboard/linux/shared/thread_types_public.h"
+// Disable the verbose logging which is designed only for
+// debugging.
+#undef SB_DLOG
+#define SB_DLOG(severity) SB_EAT_STREAM_PARAMETERS
-#endif // STARBOARD_LINUX_X64X11_MOZJS_THREAD_TYPES_PUBLIC_H_
+#endif // STARBOARD_ELF_LOADER_LOG_H_
diff --git a/src/starboard/elf_loader/program_table.cc b/src/starboard/elf_loader/program_table.cc
new file mode 100644
index 0000000..aa1e49f
--- /dev/null
+++ b/src/starboard/elf_loader/program_table.cc
@@ -0,0 +1,380 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/elf_loader/program_table.h"
+
+#include "starboard/common/log.h"
+#include "starboard/elf_loader/evergreen_info.h"
+#include "starboard/elf_loader/log.h"
+#include "starboard/memory.h"
+#include "starboard/string.h"
+
+#define MAYBE_MAP_FLAG(x, from, to) (((x) & (from)) ? (to) : 0)
+
+#if SB_CAN(MAP_EXECUTABLE_MEMORY)
+#define PFLAGS_TO_PROT(x) \
+ (MAYBE_MAP_FLAG((x), PF_X, kSbMemoryMapProtectExec) | \
+ MAYBE_MAP_FLAG((x), PF_R, kSbMemoryMapProtectRead) | \
+ MAYBE_MAP_FLAG((x), PF_W, kSbMemoryMapProtectWrite))
+#endif
+
+#define MAP_FAILED ((void*)-1)
+
+namespace starboard {
+namespace elf_loader {
+
+ProgramTable::ProgramTable()
+ : phdr_num_(0),
+ phdr_mmap_(NULL),
+ phdr_table_(NULL),
+ phdr_size_(0),
+ load_start_(NULL),
+ load_size_(0),
+ base_memory_address_(0) {}
+
+bool ProgramTable::LoadProgramHeader(const Ehdr* elf_header, File* elf_file) {
+ if (!elf_header) {
+ SB_LOG(ERROR) << "Ehdr is required";
+ return false;
+ }
+ if (!elf_file) {
+ SB_LOG(ERROR) << "File is required";
+ return false;
+ }
+ phdr_num_ = elf_header->e_phnum;
+
+ SB_DLOG(INFO) << "Program Header count=" << phdr_num_;
+ // Like the kernel, only accept program header tables smaller than 64 KB.
+ if (phdr_num_ < 1 || phdr_num_ > 65536 / elf_header->e_phentsize) {
+ SB_LOG(ERROR) << "Invalid program header count: " << phdr_num_;
+ return false;
+ }
+
+ SB_DLOG(INFO) << "elf_header->e_phoff=" << elf_header->e_phoff;
+ SB_DLOG(INFO) << "elf_header->e_phnum=" << elf_header->e_phnum;
+
+ Addr page_min = PAGE_START(elf_header->e_phoff);
+ Addr page_max = PAGE_END(elf_header->e_phoff + (phdr_num_ * elf_header->e_phentsize));
+ Addr page_offset = PAGE_OFFSET(elf_header->e_phoff);
+
+ SB_DLOG(INFO) << "page_min=" << page_min;
+ SB_DLOG(INFO) << "page_max=" << page_max;
+
+ phdr_size_ = page_max - page_min;
+
+ SB_DLOG(INFO) << "page_max - page_min=" << page_max - page_min;
+
+#if SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)
+ phdr_mmap_ =
+ SbMemoryMap(phdr_size_, kSbMemoryMapProtectWrite, "program_header");
+ if (!phdr_mmap_) {
+ SB_LOG(ERROR) << "Failed to allocate memory";
+ return false;
+ }
+
+ SB_DLOG(INFO) << "Allocated address=" << phdr_mmap_;
+#else
+ SB_CHECK(false);
+#endif
+ if (!elf_file->ReadFromOffset(page_min, reinterpret_cast<char*>(phdr_mmap_),
+ phdr_size_)) {
+ SB_LOG(ERROR) << "Failed to read program header from file offset: "
+ << page_min;
+ return false;
+ }
+#if SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)
+ bool mp_result =
+ SbMemoryProtect(phdr_mmap_, phdr_size_, kSbMemoryMapProtectRead);
+ SB_DLOG(INFO) << "mp_result=" << mp_result;
+ if (!mp_result) {
+ SB_LOG(ERROR) << "Failed to protect program header";
+ return false;
+ }
+#else
+ SB_CHECK(false);
+#endif
+
+ phdr_table_ = reinterpret_cast<Phdr*>(reinterpret_cast<char*>(phdr_mmap_) +
+ page_offset);
+
+ return true;
+}
+
+bool ProgramTable::LoadSegments(File* elf_file) {
+ for (size_t i = 0; i < phdr_num_; ++i) {
+ const Phdr* phdr = &phdr_table_[i];
+
+ if (phdr->p_type != PT_LOAD) {
+ continue;
+ }
+
+ // Segment byte addresses in memory.
+ Addr seg_start = phdr->p_vaddr + base_memory_address_;
+ Addr seg_end = seg_start + phdr->p_memsz;
+
+ // Segment page addresses in memory.
+ Addr seg_page_start = PAGE_START(seg_start);
+ Addr seg_page_end = PAGE_END(seg_end);
+
+ // File offsets.
+ Addr seg_file_end = seg_start + phdr->p_filesz;
+ Addr file_start = phdr->p_offset;
+ Addr file_end = file_start + phdr->p_filesz;
+
+ SB_DLOG(INFO) << " phdr->p_offset=" << phdr->p_offset
+ << " phdr->p_filesz=" << phdr->p_filesz;
+
+ Addr file_page_start = PAGE_START(file_start);
+ Addr file_length = file_end - file_page_start;
+
+ SB_DLOG(INFO) << "Mapping segment: "
+ << " file_page_start=" << file_page_start
+ << " file_length=" << file_length << " seg_page_start=0x"
+ << std::hex << seg_page_start;
+
+#if (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)) && \
+ SB_CAN(MAP_EXECUTABLE_MEMORY)
+ if (file_length != 0) {
+ const int prot_flags = PFLAGS_TO_PROT(phdr->p_flags);
+ SB_DLOG(INFO) << "segment prot_flags=" << std::hex << prot_flags;
+
+ void* seg_addr = reinterpret_cast<void*>(seg_page_start);
+ bool mp_ret =
+ SbMemoryProtect(seg_addr, file_length, kSbMemoryMapProtectWrite);
+ SB_DLOG(INFO) << "segment vaddress=" << seg_addr;
+
+ if (!mp_ret) {
+ SB_LOG(ERROR) << "Failed to unprotect segment";
+ return false;
+ }
+ if (!elf_file->ReadFromOffset(file_page_start,
+ reinterpret_cast<char*>(seg_addr),
+ file_length)) {
+ SB_DLOG(INFO) << "Failed to read segment from file offset: "
+ << file_page_start;
+ return false;
+ }
+ mp_ret = SbMemoryProtect(seg_addr, file_length, prot_flags);
+ SB_DLOG(INFO) << "mp_ret=" << mp_ret;
+ if (!mp_ret) {
+ SB_LOG(ERROR) << "Failed to protect segment";
+ return false;
+ }
+ if (!seg_addr) {
+ SB_LOG(ERROR) << "Could not map segment " << i;
+ return false;
+ }
+ }
+#else
+ SB_CHECK(false);
+#endif
+
+ // if the segment is writable, and does not end on a page boundary,
+ // zero-fill it until the page limit.
+ if ((phdr->p_flags & PF_W) != 0 && PAGE_OFFSET(seg_file_end) > 0) {
+ SbMemorySet(reinterpret_cast<void*>(seg_file_end), 0,
+ PAGE_SIZE - PAGE_OFFSET(seg_file_end));
+ }
+
+ seg_file_end = PAGE_END(seg_file_end);
+
+ // seg_file_end is now the first page address after the file
+ // content. If seg_page_end is larger, we need to zero anything
+ // between them. This is done by using a private anonymous
+ // map for all extra pages.
+ if (seg_page_end > seg_file_end) {
+#if (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)) && \
+ SB_CAN(MAP_EXECUTABLE_MEMORY)
+ bool mprotect_fix = SbMemoryProtect(reinterpret_cast<void*>(seg_file_end),
+ seg_page_end - seg_file_end,
+ kSbMemoryMapProtectWrite);
+ SB_DLOG(INFO) << "mprotect_fix=" << mprotect_fix;
+ if (!mprotect_fix) {
+ SB_LOG(ERROR) << "Failed to unprotect end of segment";
+ return false;
+ }
+#else
+ SB_CHECK(false);
+#endif
+
+ SbMemorySet(reinterpret_cast<void*>(seg_file_end), 0,
+ seg_page_end - seg_file_end);
+#if (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)) && \
+ SB_CAN(MAP_EXECUTABLE_MEMORY)
+ SbMemoryProtect(reinterpret_cast<void*>(seg_file_end),
+ seg_page_end - seg_file_end,
+ PFLAGS_TO_PROT(phdr->p_flags));
+ SB_DLOG(INFO) << "mprotect_fix=" << mprotect_fix;
+ if (!mprotect_fix) {
+ SB_LOG(ERROR) << "Failed to protect end of segment";
+ return false;
+ }
+#else
+ SB_CHECK(false);
+#endif
+ }
+ }
+ return true;
+}
+
+size_t ProgramTable::GetLoadMemorySize() {
+ Addr min_vaddr = ~static_cast<Addr>(0);
+ Addr max_vaddr = 0x00000000U;
+
+ bool found_pt_load = false;
+ for (size_t i = 0; i < phdr_num_; ++i) {
+ const Phdr* phdr = &phdr_table_[i];
+
+ if (phdr->p_type != PT_LOAD) {
+ SB_DLOG(INFO) << "GetLoadMemorySize: ignoring segment with type: "
+ << phdr->p_type;
+ continue;
+ }
+ found_pt_load = true;
+
+ if (phdr->p_vaddr < min_vaddr) {
+ SB_DLOG(INFO) << "p_vaddr=" << std::hex << phdr->p_vaddr;
+ min_vaddr = phdr->p_vaddr;
+ }
+
+ if (phdr->p_vaddr + phdr->p_memsz > max_vaddr) {
+ max_vaddr = phdr->p_vaddr + phdr->p_memsz;
+ SB_DLOG(INFO) << "phdr->p_vaddr=" << phdr->p_vaddr
+ << " phdr->p_memsz=" << phdr->p_memsz;
+ SB_DLOG(INFO) << " max_vaddr=0x" << std::hex << max_vaddr;
+ }
+ }
+ if (!found_pt_load) {
+ min_vaddr = 0x00000000U;
+ }
+
+ min_vaddr = PAGE_START(min_vaddr);
+ max_vaddr = PAGE_END(max_vaddr);
+
+ return max_vaddr - min_vaddr;
+}
+
+void ProgramTable::GetDynamicSection(Dyn** dynamic,
+ size_t* dynamic_count,
+ Word* dynamic_flags) {
+ const Phdr* phdr = phdr_table_;
+ const Phdr* phdr_limit = phdr + phdr_num_;
+
+ for (phdr = phdr_table_; phdr < phdr_limit; phdr++) {
+ if (phdr->p_type != PT_DYNAMIC) {
+ SB_DLOG(INFO) << "Ignore section with type: " << phdr->p_type;
+ continue;
+ }
+
+ SB_DLOG(INFO) << "Reading at vaddr: " << phdr->p_vaddr;
+ *dynamic = reinterpret_cast<Dyn*>(base_memory_address_ + phdr->p_vaddr);
+ if (dynamic_count) {
+ *dynamic_count = (size_t)(phdr->p_memsz / sizeof(Dyn));
+ }
+ if (dynamic_flags) {
+ *dynamic_flags = phdr->p_flags;
+ }
+ return;
+ }
+ *dynamic = NULL;
+ if (dynamic_count) {
+ *dynamic_count = 0;
+ }
+}
+
+int ProgramTable::AdjustMemoryProtectionOfReadOnlySegments(
+ int extra_prot_flags) {
+ const Phdr* phdr = phdr_table_;
+ const Phdr* phdr_limit = phdr + phdr_num_;
+
+ for (; phdr < phdr_limit; phdr++) {
+ if (phdr->p_type != PT_LOAD || (phdr->p_flags & PF_W) != 0)
+ continue;
+
+ Addr seg_page_start = PAGE_START(phdr->p_vaddr) + base_memory_address_;
+ Addr seg_page_end =
+ PAGE_END(phdr->p_vaddr + phdr->p_memsz) + base_memory_address_;
+#if (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)) && \
+ SB_CAN(MAP_EXECUTABLE_MEMORY)
+ int ret = SbMemoryProtect(reinterpret_cast<void*>(seg_page_start),
+ seg_page_end - seg_page_start,
+ PFLAGS_TO_PROT(phdr->p_flags) | extra_prot_flags);
+ if (ret < 0) {
+ return -1;
+ }
+#else
+ SB_CHECK(false);
+#endif
+ }
+ return 0;
+}
+
+bool ProgramTable::ReserveLoadMemory() {
+ load_size_ = GetLoadMemorySize();
+ if (load_size_ == 0) {
+ SB_LOG(ERROR) << "No loadable segments";
+ return false;
+ }
+
+ SB_DLOG(INFO) << "Load size=" << load_size_;
+
+#if (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP))
+ load_start_ =
+ SbMemoryMap(load_size_, kSbMemoryMapProtectReserved, "reserved_mem");
+ if (load_start_ == MAP_FAILED) {
+ SB_LOG(ERROR) << "Could not reserve " << load_size_
+ << " bytes of address space";
+ return false;
+ }
+#else
+ SB_CHECK(false);
+#endif
+ base_memory_address_ = reinterpret_cast<Addr>(load_start_);
+ SB_LOG(INFO) << "Load start=" << std::hex << load_start_
+ << " base_memory_address=0x" << base_memory_address_;
+ return true;
+}
+
+void ProgramTable::PublishEvergreenInfo(const char* file_path) {
+ EvergreenInfo evergreen_info;
+ SbMemorySet(&evergreen_info, sizeof(EvergreenInfo), 0);
+ SbStringCopy(evergreen_info.file_path_buf, file_path,
+ EVERGREEN_FILE_PATH_MAX_SIZE);
+ evergreen_info.base_address = base_memory_address_;
+ evergreen_info.load_size = load_size_;
+ evergreen_info.phdr_table = (uint64_t)phdr_table_;
+ evergreen_info.phdr_table_num = phdr_num_;
+ SetEvergreenInfo(&evergreen_info);
+}
+
+Addr ProgramTable::GetBaseMemoryAddress() {
+ return base_memory_address_;
+}
+
+ProgramTable::~ProgramTable() {
+ SetEvergreenInfo(NULL);
+#if SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)
+ if (load_start_) {
+ SbMemoryUnmap(load_start_, load_size_);
+ }
+ if (phdr_mmap_) {
+ SbMemoryUnmap(phdr_mmap_, phdr_size_);
+ }
+#else
+ SB_CHECK(false);
+#endif
+}
+
+} // namespace elf_loader
+} // namespace starboard
diff --git a/src/starboard/elf_loader/program_table.h b/src/starboard/elf_loader/program_table.h
new file mode 100644
index 0000000..9512b5e
--- /dev/null
+++ b/src/starboard/elf_loader/program_table.h
@@ -0,0 +1,95 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_ELF_LOADER_PROGRAM_TABLE_H_
+#define STARBOARD_ELF_LOADER_PROGRAM_TABLE_H_
+
+#include "starboard/elf_loader/elf.h"
+#include "starboard/elf_loader/file.h"
+
+namespace starboard {
+namespace elf_loader {
+
+// Loads the ELF's binary program table and memory maps
+// the loadable segments.
+//
+// To properly initialize the program table and the segments
+// the following calls are required:
+// 1. LoadProgramHeader()
+// 2. LoadSegments()
+//
+// After those calls the ProgramTable class is fully functional and
+// the segments properly loaded.
+
+class ProgramTable {
+ public:
+ ProgramTable();
+
+ // Loads the program header.
+ bool LoadProgramHeader(const Ehdr* elf_header, File* elf_file);
+
+ // Loads the segments.
+ bool LoadSegments(File* elf_file);
+
+ // Retrieves the dynamic section table.
+ void GetDynamicSection(Dyn** dynamic,
+ size_t* dynamic_count,
+ Word* dynamic_flags);
+
+ // Adjusts the memory protection of read only segments.
+ // This call is used to make text segments writable in order
+ // to apply relocations. After the relocations are done the
+ // protection is restored to its original read only state.
+ int AdjustMemoryProtectionOfReadOnlySegments(int extra_prot_flags);
+
+ // Reserves a contiguous block of memory, page aligned for mapping all
+ // the segments of the binary.
+ bool ReserveLoadMemory();
+
+ // Retrieves the base load address for the binary.
+ Addr GetBaseMemoryAddress();
+
+ // Publish the memory mapping information of the library to
+ // the EvergreenInfo API.
+ void PublishEvergreenInfo(const char* file_path);
+
+ ~ProgramTable();
+
+ private:
+ // Calculates the memory size of the binary.
+ size_t GetLoadMemorySize();
+
+ private:
+ size_t phdr_num_;
+ void* phdr_mmap_;
+ Phdr* phdr_table_;
+ Addr phdr_size_;
+
+ // First page of reserved address space.
+ void* load_start_;
+
+ // Size in bytes of reserved address space.
+ Addr load_size_;
+
+ // The base memory address. All virtual addresses
+ // from the ELF file are offsets from this address.
+ Addr base_memory_address_;
+
+ SB_DISALLOW_COPY_AND_ASSIGN(ProgramTable);
+};
+
+} // namespace elf_loader
+} // namespace starboard
+
+#endif // STARBOARD_ELF_LOADER_PROGRAM_TABLE_H_
diff --git a/src/starboard/elf_loader/program_table_test.cc b/src/starboard/elf_loader/program_table_test.cc
new file mode 100644
index 0000000..b2b6efa
--- /dev/null
+++ b/src/starboard/elf_loader/program_table_test.cc
@@ -0,0 +1,188 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/elf_loader/program_table.h"
+
+#include <vector>
+
+#include "starboard/common/scoped_ptr.h"
+#include "starboard/elf_loader/file.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if SB_API_VERSION >= 12 && \
+ (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)) && \
+ SB_CAN(MAP_EXECUTABLE_MEMORY)
+namespace starboard {
+namespace elf_loader {
+
+namespace {
+
+class DummyFile : public File {
+ public:
+ typedef struct FileChunk {
+ FileChunk(int file_offset, const char* buffer, int size)
+ : file_offset_(file_offset), buffer_(buffer), size_(size) {}
+ int file_offset_;
+ const char* buffer_;
+ int size_;
+ } FileChunk;
+
+ explicit DummyFile(const std::vector<FileChunk>& file_chunks)
+ : file_chunks_(file_chunks), read_index_(0) {}
+
+ bool Open(const char* name) { return true; }
+ bool ReadFromOffset(int64_t offset, char* buffer, int size) {
+ SB_LOG(INFO) << "ReadFromOffset offset=" << offset << " size=" << size
+ << " read_index_=" << read_index_;
+ if (read_index_ >= file_chunks_.size()) {
+ SB_LOG(INFO) << "ReadFromOffset EOF";
+ return false;
+ }
+ const FileChunk& file_chunk = file_chunks_[read_index_++];
+ if (offset != file_chunk.file_offset_) {
+ SB_LOG(ERROR) << "ReadFromOffset: Invalid offset " << offset
+ << " expected " << file_chunk.file_offset_;
+ return false;
+ }
+ if (size > file_chunk.size_) {
+ SB_LOG(ERROR) << "ReadFromOffset: Invalid size " << size << " expected < "
+ << file_chunk.size_;
+ return false;
+ }
+ SbMemoryCopy(buffer, file_chunk.buffer_, size);
+ return true;
+ }
+ void Close() {}
+
+ private:
+ int file_offset_;
+ const char* buffer_;
+ int size_;
+ std::vector<FileChunk> file_chunks_;
+ int read_index_;
+};
+
+class ProgramTableTest : public ::testing::Test {
+ protected:
+ ProgramTableTest() { program_table_.reset(new ProgramTable()); }
+ ~ProgramTableTest() {}
+
+ void HelperMethod() {}
+
+ protected:
+ scoped_ptr<ProgramTable> program_table_;
+};
+
+TEST_F(ProgramTableTest, LoadSegments) {
+ // File structure
+ // [Phdr1]
+ // [Phdr2]
+ // [200, 300) sement for phdr1
+ // [250, 300) dyanmic section in segment for phdr1
+ // [400, 500) sement for phdr2
+ Ehdr ehdr;
+ ehdr.e_phnum = 3;
+ ehdr.e_phoff = 0;
+ ehdr.e_phentsize = sizeof(Phdr);
+
+ Phdr ent1;
+ Phdr ent2;
+ Phdr ent3;
+ SbMemorySet(&ent1, 0, sizeof(Phdr));
+ SbMemorySet(&ent2, 0, sizeof(Phdr));
+ SbMemorySet(&ent3, 0, sizeof(Phdr));
+
+ ent1.p_type = PT_LOAD;
+ ent1.p_vaddr = 0;
+ ent1.p_memsz = 2 * PAGE_SIZE;
+ ent1.p_offset = 200;
+ ent1.p_filesz = 100;
+ ent1.p_flags = kSbMemoryMapProtectRead;
+
+ ent2.p_type = PT_LOAD;
+ ent2.p_vaddr = 2 * PAGE_SIZE;
+ ent2.p_memsz = 3 * PAGE_SIZE;
+ ent2.p_offset = 400;
+ ent2.p_filesz = 100;
+ ent1.p_flags = kSbMemoryMapProtectRead | kSbMemoryMapProtectExec;
+
+ ent3.p_type = PT_DYNAMIC;
+ ent3.p_vaddr = 250;
+ ent3.p_memsz = 3 * sizeof(Dyn);
+ ent3.p_offset = 250;
+ ent3.p_filesz = 5 * sizeof(Dyn);
+ ent3.p_flags = 0x42;
+
+ Phdr program_table_data[3];
+ program_table_data[0] = ent1;
+ program_table_data[1] = ent2;
+ program_table_data[2] = ent3;
+
+ Dyn dynamic_table_data[3];
+ dynamic_table_data[0].d_tag = DT_DEBUG;
+ dynamic_table_data[1].d_tag = DT_DEBUG;
+ dynamic_table_data[2].d_tag = DT_DEBUG;
+
+ char program_table_page[PAGE_SIZE];
+ SbMemorySet(program_table_page, 0, sizeof(program_table_page));
+ SbMemoryCopy(program_table_page, program_table_data,
+ sizeof(program_table_data));
+
+ char segment_file_data1[2 * PAGE_SIZE];
+ char segment_file_data2[3 * PAGE_SIZE];
+
+ SbMemoryCopy(segment_file_data1 + 250, dynamic_table_data,
+ sizeof(dynamic_table_data));
+
+ std::vector<DummyFile::FileChunk> file_chunks;
+ file_chunks.push_back(
+ DummyFile::FileChunk(0, program_table_page, sizeof(program_table_page)));
+ file_chunks.push_back(
+ DummyFile::FileChunk(0, segment_file_data1, sizeof(segment_file_data1)));
+ file_chunks.push_back(
+ DummyFile::FileChunk(0, segment_file_data2, sizeof(segment_file_data2)));
+
+ DummyFile file(file_chunks);
+
+ EXPECT_TRUE(program_table_->LoadProgramHeader(&ehdr, &file));
+
+ EXPECT_EQ(program_table_->GetBaseMemoryAddress(), 0);
+
+ EXPECT_TRUE(program_table_->ReserveLoadMemory());
+
+ EXPECT_NE(program_table_->GetBaseMemoryAddress(), 0);
+
+ EXPECT_TRUE(program_table_->LoadSegments(&file));
+
+ Dyn* dynamic = NULL;
+ size_t dynamic_count = 0;
+ Word dynamic_flags = 0;
+
+ program_table_->GetDynamicSection(&dynamic, &dynamic_count, &dynamic_flags);
+ Dyn* expected_dyn = reinterpret_cast<Dyn*>(
+ program_table_->GetBaseMemoryAddress() + ent3.p_vaddr);
+ EXPECT_TRUE(dynamic != NULL);
+ EXPECT_EQ(dynamic[0].d_tag, DT_DEBUG);
+ EXPECT_EQ(dynamic[1].d_tag, DT_DEBUG);
+ EXPECT_EQ(dynamic[2].d_tag, DT_DEBUG);
+ EXPECT_EQ(dynamic_count, 3);
+ EXPECT_EQ(dynamic_flags, 0x42);
+}
+
+} // namespace
+} // namespace elf_loader
+} // namespace starboard
+#endif // SB_API_VERSION >= 12 && (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION
+ // || SB_HAS(MMAP)) && SB_CAN(MAP_EXECUTABLE_MEMORY)
diff --git a/src/starboard/elf_loader/relocations.cc b/src/starboard/elf_loader/relocations.cc
new file mode 100644
index 0000000..80c9069
--- /dev/null
+++ b/src/starboard/elf_loader/relocations.cc
@@ -0,0 +1,478 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/elf_loader/relocations.h"
+
+#include "starboard/common/log.h"
+#include "starboard/elf_loader/log.h"
+
+namespace starboard {
+namespace elf_loader {
+
+Relocations::Relocations(Addr base_memory_address,
+ DynamicSection* dynamic_section,
+ ExportedSymbols* exported_symbols)
+ : base_memory_address_(base_memory_address),
+ dynamic_section_(dynamic_section),
+ plt_relocations_(0),
+ plt_relocations_size_(0),
+ plt_got_(NULL),
+ relocations_(0),
+ relocations_size_(0),
+ has_text_relocations_(false),
+ has_symbolic_(false),
+ exported_symbols_(exported_symbols) {}
+
+bool Relocations::HasTextRelocations() {
+ return has_text_relocations_;
+}
+
+bool Relocations::InitRelocations() {
+ SB_DLOG(INFO) << "InitRelocations: dynamic_count="
+ << dynamic_section_->GetDynamicTableSize();
+ const Dyn* dynamic = dynamic_section_->GetDynamicTable();
+ for (int i = 0; i < dynamic_section_->GetDynamicTableSize(); i++) {
+ Addr dyn_value = dynamic[i].d_un.d_val;
+ uintptr_t dyn_addr = base_memory_address_ + dynamic[i].d_un.d_ptr;
+ Addr tag = dynamic[i].d_tag;
+ SB_DLOG(INFO) << "InitRelocations: tag=" << tag;
+ switch (tag) {
+#if defined(USE_RELA)
+ case DT_REL:
+ case DT_RELSZ:
+#else
+ case DT_RELA:
+ case DT_RELASZ:
+#endif
+ SB_LOG(ERROR) << "unsupported relocation type";
+ return false;
+ case DT_PLTREL:
+ SB_DLOG(INFO) << " DT_PLTREL value=" << dyn_value;
+#if defined(USE_RELA)
+ if (dyn_value != DT_RELA) {
+ SB_LOG(ERROR) << "unsupported DT_PLTREL expected DT_RELA";
+ return false;
+ }
+#else
+ if (dyn_value != DT_REL) {
+ SB_LOG(ERROR) << "unsupported DT_PLTREL expected DT_REL";
+ return false;
+ }
+#endif
+ break;
+ case DT_JMPREL:
+ SB_DLOG(INFO) << " DT_JMPREL addr=0x" << std::hex
+ << (dyn_addr - base_memory_address_);
+ plt_relocations_ = dyn_addr;
+ break;
+ case DT_PLTRELSZ:
+ plt_relocations_size_ = dyn_value;
+ SB_DLOG(INFO) << " DT_PLTRELSZ size=" << dyn_value;
+ break;
+#if defined(USE_RELA)
+ case DT_RELA:
+#else
+ case DT_REL:
+#endif
+ SB_DLOG(INFO) << " " << ((tag == DT_RELA) ? "DT_RELA" : "DT_REL")
+ << " addr=" << std::hex
+ << (dyn_addr - base_memory_address_);
+ if (relocations_) {
+ SB_LOG(ERROR)
+ << "Unsupported DT_RELA/DT_REL combination in dynamic section";
+ return false;
+ }
+ relocations_ = dyn_addr;
+ break;
+#if defined(USE_RELA)
+ case DT_RELASZ:
+#else
+ case DT_RELSZ:
+#endif
+ SB_DLOG(INFO) << " " << ((tag == DT_RELASZ) ? "DT_RELASZ" : "DT_RELSZ")
+ << " size=" << dyn_value;
+ relocations_size_ = dyn_value;
+ break;
+ case DT_RELR:
+ case DT_RELRSZ:
+ SB_LOG(ERROR) << " DT_RELRSZ NOT IMPELMENTED";
+ break;
+ case DT_RELRENT:
+ case DT_PLTGOT:
+ SB_DLOG(INFO) << "DT_PLTGOT addr=0x" << std::hex
+ << (dyn_addr - base_memory_address_);
+ plt_got_ = reinterpret_cast<Addr*>(dyn_addr);
+ break;
+ case DT_TEXTREL:
+ SB_DLOG(INFO) << " DT_TEXTREL";
+ has_text_relocations_ = true;
+ break;
+ case DT_SYMBOLIC:
+ SB_DLOG(INFO) << " DT_SYMBOLIC";
+ has_symbolic_ = true;
+ break;
+ case DT_FLAGS:
+ if (dyn_value & DF_TEXTREL)
+ has_text_relocations_ = true;
+ if (dyn_value & DF_SYMBOLIC)
+ has_symbolic_ = true;
+
+ SB_DLOG(INFO) << " DT_FLAGS has_text_relocations="
+ << has_text_relocations_
+ << " has_symbolic=" << has_symbolic_;
+
+ break;
+ default:
+ break;
+ }
+ }
+
+ return true;
+}
+
+bool Relocations::ApplyAllRelocations() {
+ SB_DLOG(INFO) << "Applying regular relocations";
+ if (!ApplyRelocations(reinterpret_cast<rel_t*>(relocations_),
+ relocations_size_ / sizeof(rel_t))) {
+ SB_LOG(ERROR) << "regular relocations failed";
+ return false;
+ }
+
+ SB_DLOG(INFO) << "Applying PLT relocations";
+ if (!ApplyRelocations(reinterpret_cast<rel_t*>(plt_relocations_),
+ plt_relocations_size_ / sizeof(rel_t))) {
+ SB_LOG(ERROR) << "PLT relocations failed";
+ return false;
+ }
+ return true;
+}
+
+bool Relocations::ApplyRelocations(const rel_t* rel, size_t rel_count) {
+ SB_DLOG(INFO) << "rel=" << std::hex << rel << std::dec
+ << " rel_count=" << rel_count;
+
+ if (!rel)
+ return true;
+
+ for (size_t rel_n = 0; rel_n < rel_count; rel++, rel_n++) {
+ SB_DLOG(INFO) << " Relocation " << rel_n + 1 << " of " << rel_count;
+
+ if (!ApplyRelocation(rel))
+ return false;
+ }
+
+ return true;
+}
+
+bool Relocations::ApplyRelocation(const rel_t* rel) {
+ const Word rel_type = ELF_R_TYPE(rel->r_info);
+ const Word rel_symbol = ELF_R_SYM(rel->r_info);
+
+ Addr sym_addr = 0;
+ Addr reloc = static_cast<Addr>(rel->r_offset + base_memory_address_);
+ SB_DLOG(INFO) << " offset=0x" << std::hex << rel->r_offset
+ << " type=" << std::dec << rel_type << " reloc=0x" << std::hex
+ << reloc << " symbol=" << rel_symbol;
+
+ if (rel_type == 0)
+ return true;
+
+ if (rel_symbol != 0) {
+ if (!ResolveSymbol(rel_type, rel_symbol, reloc, &sym_addr)) {
+ SB_LOG(ERROR) << "Failed to resolve symbol: " << rel_symbol;
+ return false;
+ }
+ }
+
+ return ApplyResolvedReloc(rel, sym_addr);
+}
+
+#if defined(USE_RELA)
+bool Relocations::ApplyResolvedReloc(const Rela* rela, Addr sym_addr) {
+ const Word rela_type = ELF_R_TYPE(rela->r_info);
+ const Sword addend = rela->r_addend;
+ const Addr reloc = static_cast<Addr>(rela->r_offset + base_memory_address_);
+
+ SB_DLOG(INFO) << " rela reloc=0x" << std::hex << reloc << " offset=0x"
+ << rela->r_offset << " type=" << std::dec << rela_type
+ << " addend=0x" << std::hex << addend;
+ Addr* target = reinterpret_cast<Addr*>(reloc);
+ switch (rela_type) {
+#if SB_IS(ARCH_ARM64)
+ case R_AARCH64_JUMP_SLOT:
+ SB_DLOG(INFO) << " R_AARCH64_JUMP_SLOT target=" << std::hex << target
+ << " addr=" << (sym_addr + addend);
+ *target = sym_addr + addend;
+ break;
+
+ case R_AARCH64_GLOB_DAT:
+ SB_DLOG(INFO) << " R_AARCH64_GLOB_DAT target=" << std::hex << target
+ << " addr=" << (sym_addr + addend);
+ *target = sym_addr + addend;
+ break;
+
+ case R_AARCH64_ABS64:
+ SB_DLOG(INFO) << " R_AARCH64_ABS64 target=" << std::hex << target << " "
+ << *target << " addr=" << sym_addr + addend;
+ *target += sym_addr + addend;
+ break;
+
+ case R_AARCH64_RELATIVE:
+ SB_DLOG(INFO) << " R_AARCH64_RELATIVE target=" << std::hex << target
+ << " " << *target
+ << " bias=" << base_memory_address_ + addend;
+ *target = base_memory_address_ + addend;
+ break;
+#endif
+
+#if SB_IS(ARCH_X64)
+ case R_X86_64_JMP_SLOT:
+ SB_DLOG(INFO) << " R_X86_64_JMP_SLOT target=" << std::hex << target
+ << " addr=" << (sym_addr + addend);
+ *target = sym_addr + addend;
+ break;
+
+ case R_X86_64_GLOB_DAT:
+ SB_DLOG(INFO) << " R_X86_64_GLOB_DAT target=" << std::hex << target
+ << " addr=" << (sym_addr + addend);
+
+ *target = sym_addr + addend;
+ break;
+
+ case R_X86_64_RELATIVE:
+ SB_DLOG(INFO) << " R_X86_64_RELATIVE target=" << std::hex << target
+ << " " << *target
+ << " bias=" << base_memory_address_ + addend;
+ *target = base_memory_address_ + addend;
+ break;
+
+ case R_X86_64_64:
+ *target = sym_addr + addend;
+ break;
+
+ case R_X86_64_PC32:
+ *target = sym_addr + (addend - reloc);
+ break;
+#endif
+
+ default:
+ SB_LOG(ERROR) << "Invalid relocation type: " << rela_type;
+ return false;
+ }
+
+ return true;
+}
+#else
+bool Relocations::ApplyResolvedReloc(const Rel* rel, Addr sym_addr) {
+ const Word rel_type = ELF_R_TYPE(rel->r_info);
+ const Addr reloc = static_cast<Addr>(rel->r_offset + base_memory_address_);
+
+ SB_DLOG(INFO) << " rel reloc=0x" << std::hex << reloc << " offset=0x"
+ << rel->r_offset << " type=" << std::dec << rel_type;
+
+ Addr* target = reinterpret_cast<Addr*>(reloc);
+ switch (rel_type) {
+#if SB_IS(ARCH_ARM)
+ case R_ARM_JUMP_SLOT:
+ SB_DLOG(INFO) << " R_ARM_JUMP_SLOT target=" << std::hex << target
+ << " addr=" << sym_addr;
+ *target = sym_addr;
+ break;
+
+ case R_ARM_GLOB_DAT:
+ SB_DLOG(INFO) << " R_ARM_GLOB_DAT target=" << std::hex << target
+ << " addr=" << sym_addr;
+ *target = sym_addr;
+ break;
+
+ case R_ARM_ABS32:
+ SB_DLOG(INFO) << " R_ARM_ABS32 target=" << std::hex << target << " "
+ << *target << " addr=" << sym_addr;
+ *target += sym_addr;
+ break;
+
+ case R_ARM_REL32:
+ SB_DLOG(INFO) << " R_ARM_REL32 target=" << std::hex << target << " "
+ << *target << " addr=" << sym_addr
+ << " offset=" << rel->r_offset;
+ *target += sym_addr - rel->r_offset;
+ break;
+
+ case R_ARM_RELATIVE:
+ SB_DLOG(INFO) << " RR_ARM_RELATIVE target=" << std::hex << target << " "
+ << *target << " bias=" << base_memory_address_;
+ *target += base_memory_address_;
+ break;
+#endif
+
+#if SB_IS(ARCH_X86)
+ case R_386_JMP_SLOT:
+ SB_DLOG(INFO) << " R_386_JMP_SLOT target=" << std::hex << target
+ << " addr=" << sym_addr;
+
+ *target = sym_addr;
+ break;
+
+ case R_386_GLOB_DAT:
+ SB_DLOG(INFO) << " R_386_GLOB_DAT target=" << std::hex << target
+ << " addr=" << sym_addr;
+ *target = sym_addr;
+
+ break;
+
+ case R_386_RELATIVE:
+ SB_DLOG(INFO) << " R_386_RELATIVE target=" << std::hex << target << " "
+ << *target << " bias=" << base_memory_address_;
+
+ *target += base_memory_address_;
+ break;
+
+ case R_386_32:
+ SB_DLOG(INFO) << " R_386_32 target=" << std::hex << target << " "
+ << *target << " addr=" << sym_addr;
+ *target += sym_addr;
+ break;
+
+ case R_386_PC32:
+ SB_DLOG(INFO) << " R_386_PC32 target=" << std::hex << target << " "
+ << *target << " addr=" << sym_addr << " reloc=" << reloc;
+ *target += (sym_addr - reloc);
+ break;
+#endif
+
+ default:
+ SB_LOG(ERROR) << "Invalid relocation type: " << rel_type;
+ return false;
+ }
+
+ return true;
+}
+#endif
+
+RelocationType Relocations::GetRelocationType(Word r_type) {
+ switch (r_type) {
+#if SB_IS(ARCH_ARM)
+ case R_ARM_JUMP_SLOT:
+ case R_ARM_GLOB_DAT:
+ case R_ARM_ABS32:
+ return RELOCATION_TYPE_ABSOLUTE;
+
+ case R_ARM_REL32:
+ case R_ARM_RELATIVE:
+ return RELOCATION_TYPE_RELATIVE;
+
+ case R_ARM_COPY:
+ return RELOCATION_TYPE_COPY;
+#endif
+
+#if SB_IS(ARCH_ARM64)
+ case R_AARCH64_JUMP_SLOT:
+ case R_AARCH64_GLOB_DAT:
+ case R_AARCH64_ABS64:
+ return RELOCATION_TYPE_ABSOLUTE;
+
+ case R_AARCH64_RELATIVE:
+ return RELOCATION_TYPE_RELATIVE;
+
+ case R_AARCH64_COPY:
+ return RELOCATION_TYPE_COPY;
+#endif
+
+#if SB_IS(ARCH_X86)
+ case R_386_JMP_SLOT:
+ case R_386_GLOB_DAT:
+ case R_386_32:
+ return RELOCATION_TYPE_ABSOLUTE;
+
+ case R_386_RELATIVE:
+ return RELOCATION_TYPE_RELATIVE;
+
+ case R_386_PC32:
+ return RELOCATION_TYPE_PC_RELATIVE;
+#endif
+
+#if SB_IS(ARCH_X64)
+ case R_X86_64_JMP_SLOT:
+ case R_X86_64_GLOB_DAT:
+ case R_X86_64_64:
+ return RELOCATION_TYPE_ABSOLUTE;
+
+ case R_X86_64_RELATIVE:
+ return RELOCATION_TYPE_RELATIVE;
+
+ case R_X86_64_PC32:
+ return RELOCATION_TYPE_PC_RELATIVE;
+#endif
+ default:
+ return RELOCATION_TYPE_UNKNOWN;
+ }
+}
+
+bool Relocations::ResolveSymbol(Word rel_type,
+ Word rel_symbol,
+ Addr reloc,
+ Addr* sym_addr) {
+ const char* sym_name = dynamic_section_->LookupNameById(rel_symbol);
+ SB_DLOG(INFO) << "Resolve: " << sym_name;
+ const void* address = NULL;
+
+ const Sym* sym = dynamic_section_->LookupByName(sym_name);
+ if (sym) {
+ address = reinterpret_cast<void*>(base_memory_address_ + sym->st_value);
+ } else {
+ address = exported_symbols_->Lookup(sym_name);
+ }
+
+ SB_DLOG(INFO) << "Resolve: address=0x" << std::hex << address;
+
+ if (address) {
+ // The symbol was found, so compute its address.
+ *sym_addr = reinterpret_cast<Addr>(address);
+ return true;
+ }
+
+ // The symbol was not found. Normally this is an error except
+ // if this is a weak reference.
+ if (!dynamic_section_->IsWeakById(rel_symbol)) {
+ SB_LOG(ERROR) << "Could not find symbol: " << sym_name;
+ return false;
+ }
+
+ // IHI0044C AAELF 4.5.1.1:
+ // Libraries are not searched to resolve weak references.
+ // It is not an error for a weak reference to remain
+ // unsatisfied.
+ //
+ // During linking, the value of an undefined weak reference is:
+ // - Zero if the relocation type is absolute
+ // - The address of the place if the relocation is pc-relative
+ // - The address of nominal base address if the relocation
+ // type is base-relative.
+ RelocationType r = GetRelocationType(rel_type);
+ if (r == RELOCATION_TYPE_ABSOLUTE || r == RELOCATION_TYPE_RELATIVE) {
+ *sym_addr = 0;
+ return true;
+ }
+
+ if (r == RELOCATION_TYPE_PC_RELATIVE) {
+ *sym_addr = reloc;
+ return true;
+ }
+
+ SB_LOG(ERROR) << "Invalid weak relocation type (" << r
+ << ") for unknown symbol '" << sym_name << "'";
+ return false;
+}
+} // namespace elf_loader
+} // namespace starboard
diff --git a/src/starboard/elf_loader/relocations.h b/src/starboard/elf_loader/relocations.h
new file mode 100644
index 0000000..fad8a4e
--- /dev/null
+++ b/src/starboard/elf_loader/relocations.h
@@ -0,0 +1,93 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_ELF_LOADER_RELOCATIONS_H_
+#define STARBOARD_ELF_LOADER_RELOCATIONS_H_
+
+#include "starboard/elf_loader/elf.h"
+
+#include "starboard/elf_loader/dynamic_section.h"
+#include "starboard/elf_loader/program_table.h"
+
+namespace starboard {
+namespace elf_loader {
+
+enum RelocationType {
+ RELOCATION_TYPE_UNKNOWN = 0,
+ RELOCATION_TYPE_ABSOLUTE = 1,
+ RELOCATION_TYPE_RELATIVE = 2,
+ RELOCATION_TYPE_PC_RELATIVE = 3,
+ RELOCATION_TYPE_COPY = 4,
+};
+
+// class representing the ELF relocations.
+class Relocations {
+ public:
+ Relocations(Addr base_memory_adddress,
+ DynamicSection* dynamic_section,
+ ExportedSymbols* exported_symbols);
+
+ // Initialize the relocation tables.
+ bool InitRelocations();
+
+ // Apply all the relocations.
+ bool ApplyAllRelocations();
+
+ // Apply a set of relocations.
+ bool ApplyRelocations(const rel_t* rel, size_t rel_count);
+
+ // Apply an individual relocation.
+ bool ApplyRelocation(const rel_t* rel);
+
+// Apply a resolved symbol relocation.
+#if defined(USE_RELA)
+ bool ApplyResolvedReloc(const Rela* rela, Addr sym_addr);
+#else
+ bool ApplyResolvedReloc(const Rel* rel, Addr sym_addr);
+#endif
+
+ // Convert an ELF relocation type info a RelocationType value.
+ RelocationType GetRelocationType(Word r_type);
+
+ // Resolve a symbol address.
+ bool ResolveSymbol(Word rel_type,
+ Word rel_symbol,
+ Addr reloc,
+ Addr* sym_addr);
+
+ // Checks if there are any text relocations.
+ bool HasTextRelocations();
+
+ private:
+ Addr base_memory_address_;
+ DynamicSection* dynamic_section_;
+ Addr plt_relocations_;
+ size_t plt_relocations_size_;
+ Addr* plt_got_;
+
+ Addr relocations_;
+ size_t relocations_size_;
+
+ bool has_text_relocations_;
+ bool has_symbolic_;
+
+ ExportedSymbols* exported_symbols_;
+
+ SB_DISALLOW_COPY_AND_ASSIGN(Relocations);
+};
+
+} // namespace elf_loader
+} // namespace starboard
+
+#endif // STARBOARD_ELF_LOADER_RELOCATIONS_H_
diff --git a/src/starboard/elf_loader/relocations_test.cc b/src/starboard/elf_loader/relocations_test.cc
new file mode 100644
index 0000000..1bb2b7b
--- /dev/null
+++ b/src/starboard/elf_loader/relocations_test.cc
@@ -0,0 +1,388 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/elf_loader/relocations.h"
+
+#include "starboard/common/scoped_ptr.h"
+#include "starboard/elf_loader/elf.h"
+#include "starboard/elf_loader/file_impl.h"
+#include "starboard/string.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if SB_API_VERSION >= 12 && \
+ (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)) && \
+ SB_CAN(MAP_EXECUTABLE_MEMORY)
+namespace starboard {
+namespace elf_loader {
+
+namespace {
+
+// Test constants used as sample data.
+const Addr kTestAddress = 34;
+const Sword kTestAddend = 5;
+
+class RelocationsTest : public ::testing::Test {
+ protected:
+ RelocationsTest() {
+ SbMemorySet(buf_, 'A', sizeof(buf_));
+ base_addr_ = reinterpret_cast<Addr>(&buf_);
+ dynamic_table_[0].d_tag = DT_REL;
+
+ dynamic_section_.reset(
+ new DynamicSection(base_addr_, dynamic_table_, 1, 0));
+ dynamic_section_->InitDynamicSection();
+
+ exported_symbols_.reset(new ExportedSymbols());
+ relocations_.reset(new Relocations(base_addr_, dynamic_section_.get(),
+ exported_symbols_.get()));
+ }
+ ~RelocationsTest() {}
+
+ void VerifySymAddress(const rel_t* rel, Addr sym_addr) {
+ Addr target_addr = base_addr_ + rel->r_offset;
+ Addr target_value = sym_addr;
+ EXPECT_EQ(target_value, *reinterpret_cast<Addr*>(target_addr));
+ }
+
+#ifdef USE_RELA
+ void VerifySymAddressPlusAddend(const rel_t* rel, Addr sym_addr) {
+ Addr target_addr = base_addr_ + rel->r_offset;
+ Addr target_value = sym_addr + rel->r_addend;
+ EXPECT_EQ(target_value, *reinterpret_cast<Addr*>(target_addr));
+ }
+
+ void VerifyBaseAddressPlusAddend(const rel_t* rel) {
+ Addr target_addr = base_addr_ + rel->r_offset;
+ Addr target_value = base_addr_ + rel->r_addend;
+ EXPECT_EQ(target_value, *reinterpret_cast<Addr*>(target_addr));
+ }
+
+ void VerifySymAddressPlusAddendDelta(const rel_t* rel, Addr sym_addr) {
+ Addr target_addr = base_addr_ + rel->r_offset;
+ Addr offset_rel = rel->r_offset + base_addr_;
+ Addr target_value = sym_addr + (rel->r_addend - offset_rel);
+ EXPECT_EQ(target_value, *reinterpret_cast<Addr*>(target_addr));
+ }
+#endif
+
+ protected:
+ scoped_ptr<Relocations> relocations_;
+ Addr base_addr_;
+
+ private:
+ char buf_[128];
+ Dyn dynamic_table_[10];
+ scoped_ptr<DynamicSection> dynamic_section_;
+ scoped_ptr<ExportedSymbols> exported_symbols_;
+};
+
+#if SB_IS(ARCH_ARM)
+TEST_F(RelocationsTest, R_ARM_JUMP_SLOT) {
+ rel_t rel;
+ rel.r_offset = 0;
+ rel.r_info = R_ARM_JUMP_SLOT;
+ Addr sym_addr = kTestAddress;
+
+ // Expected relocation calculation:
+ // *target = sym_addr;
+ relocations_->ApplyResolvedReloc(&rel, sym_addr);
+
+ VerifySymAddress(&rel, sym_addr);
+}
+
+TEST_F(RelocationsTest, R_ARM_GLOB_DAT) {
+ rel_t rel;
+ rel.r_offset = 1;
+ rel.r_info = R_ARM_GLOB_DAT;
+ Addr sym_addr = kTestAddress;
+
+ // Expected relocation calculation:
+ // *target = sym_addr;
+ relocations_->ApplyResolvedReloc(&rel, sym_addr);
+
+ VerifySymAddress(&rel, sym_addr);
+}
+
+TEST_F(RelocationsTest, R_ARM_ABS32) {
+ rel_t rel;
+ rel.r_offset = 2;
+ rel.r_info = R_ARM_ABS32;
+ Addr sym_addr = kTestAddress;
+
+ Addr target_addr = base_addr_ + rel.r_offset;
+ Addr target_value = *reinterpret_cast<Addr*>(target_addr);
+ target_value += sym_addr;
+
+ // Expected relocation calculation:
+ // *target += sym_addr;
+ relocations_->ApplyResolvedReloc(&rel, sym_addr);
+
+ EXPECT_EQ(target_value, *reinterpret_cast<Addr*>(target_addr));
+}
+
+TEST_F(RelocationsTest, R_ARM_REL32) {
+ rel_t rel;
+ rel.r_offset = 3;
+ rel.r_info = R_ARM_REL32;
+ Addr sym_addr = kTestAddress;
+
+ Addr target_addr = base_addr_ + rel.r_offset;
+ Addr target_value = *reinterpret_cast<Addr*>(target_addr);
+ target_value += sym_addr - rel.r_offset;
+
+ // Expected relocation calculation:
+ // *target += sym_addr - rel->r_offset;
+ relocations_->ApplyResolvedReloc(&rel, sym_addr);
+
+ EXPECT_EQ(target_value, *reinterpret_cast<Addr*>(target_addr));
+}
+
+TEST_F(RelocationsTest, R_ARM_RELATIVE) {
+ rel_t rel;
+ rel.r_offset = 4;
+ rel.r_info = R_ARM_RELATIVE;
+ Addr sym_addr = kTestAddress;
+
+ Addr target_addr = base_addr_ + rel.r_offset;
+ Addr target_value = *reinterpret_cast<Addr*>(target_addr);
+ target_value += base_addr_;
+
+ // Expected relocation calculation:
+ // *target += base_memory_address_;
+ relocations_->ApplyResolvedReloc(&rel, sym_addr);
+
+ EXPECT_EQ(target_value, *reinterpret_cast<Addr*>(target_addr));
+}
+#endif // SB_IS(ARCH_ARM)
+
+#if SB_IS(ARCH_ARM64) && defined(USE_RELA)
+TEST_F(RelocationsTest, R_AARCH64_JUMP_SLOT) {
+ rel_t rel;
+ rel.r_offset = 0;
+ rel.r_info = R_AARCH64_JUMP_SLOT;
+ rel.r_addend = kTestAddend;
+ Addr sym_addr = kTestAddress;
+
+ // Expected relocation calculation:
+ // *target = sym_addr + addend;
+ relocations_->ApplyResolvedReloc(&rel, sym_addr);
+
+ VerifySymAddressPlusAddend(&rel, sym_addr);
+}
+
+TEST_F(RelocationsTest, R_AARCH64_GLOB_DAT) {
+ rel_t rel;
+ rel.r_offset = 1;
+ rel.r_info = R_AARCH64_GLOB_DAT;
+ rel.r_addend = kTestAddend;
+ Addr sym_addr = kTestAddress;
+
+ // Expected relocation calculation:
+ // *target = sym_addr + addend;
+ relocations_->ApplyResolvedReloc(&rel, sym_addr);
+
+ VerifySymAddressPlusAddend(&rel, sym_addr);
+}
+
+TEST_F(RelocationsTest, R_AARCH64_ABS64) {
+ rel_t rel;
+ rel.r_offset = 2;
+ rel.r_info = R_AARCH64_ABS64;
+ rel.r_addend = kTestAddend;
+ Addr sym_addr = kTestAddress;
+
+ Addr target_addr = base_addr_ + rel.r_offset;
+ Addr target_value = *reinterpret_cast<Addr*>(target_addr);
+ target_value += sym_addr + rel.r_addend;
+
+ // Expected relocation calculation:
+ // *target += sym_addr + addend;
+ relocations_->ApplyResolvedReloc(&rel, sym_addr);
+
+ EXPECT_EQ(target_value, *reinterpret_cast<Addr*>(target_addr));
+}
+
+TEST_F(RelocationsTest, R_AARCH64_RELATIVE) {
+ rel_t rel;
+ rel.r_offset = 3;
+ rel.r_info = R_AARCH64_RELATIVE;
+ rel.r_addend = kTestAddend;
+ Addr sym_addr = kTestAddress;
+
+ // Expected relocation calculation:
+ // *target = base_memory_address_ + addend;
+ relocations_->ApplyResolvedReloc(&rel, sym_addr);
+
+ VerifyBaseAddressPlusAddend(&rel);
+}
+
+#endif // SB_IS(ARCH_ARM64) && defined(USE_RELA)
+
+#if SB_IS(ARCH_X86)
+TEST_F(RelocationsTest, R_386_JMP_SLOT) {
+ rel_t rel;
+ rel.r_offset = 0;
+ rel.r_info = R_386_JMP_SLOT;
+ Addr sym_addr = kTestAddress;
+
+ // Expected relocation calculation:
+ // *target = sym_addr;
+ relocations_->ApplyResolvedReloc(&rel, sym_addr);
+
+ VerifySymAddress(&rel, sym_addr);
+}
+
+TEST_F(RelocationsTest, R_386_GLOB_DAT) {
+ rel_t rel;
+ rel.r_offset = 1;
+ rel.r_info = R_386_GLOB_DAT;
+ Addr sym_addr = kTestAddress;
+
+ // Expected relocation calculation:
+ // *target = sym_addr;
+ relocations_->ApplyResolvedReloc(&rel, sym_addr);
+
+ VerifySymAddress(&rel, sym_addr);
+}
+
+TEST_F(RelocationsTest, R_386_RELATIVE) {
+ rel_t rel;
+ rel.r_offset = 2;
+ rel.r_info = R_386_RELATIVE;
+ Addr sym_addr = kTestAddress;
+
+ Addr target_addr = base_addr_ + rel.r_offset;
+ Addr target_value = *reinterpret_cast<Addr*>(target_addr);
+ target_value += base_addr_;
+
+ // Expected relocation calculation:
+ // *target += base_memory_address_;
+ relocations_->ApplyResolvedReloc(&rel, sym_addr);
+
+ EXPECT_EQ(target_value, *reinterpret_cast<Addr*>(target_addr));
+}
+
+TEST_F(RelocationsTest, R_386_32) {
+ rel_t rel;
+ rel.r_offset = 3;
+ rel.r_info = R_386_32;
+ Addr sym_addr = kTestAddress;
+
+ Addr target_addr = base_addr_ + rel.r_offset;
+ Addr target_value = *reinterpret_cast<Addr*>(target_addr);
+ target_value += sym_addr;
+
+ // Expected relocation calculation:
+ // *target += sym_addr;
+ relocations_->ApplyResolvedReloc(&rel, sym_addr);
+
+ EXPECT_EQ(target_value, *reinterpret_cast<Addr*>(target_addr));
+}
+
+TEST_F(RelocationsTest, R_386_PC32) {
+ rel_t rel;
+ rel.r_offset = 4;
+ rel.r_info = R_386_PC32;
+ Addr sym_addr = kTestAddress;
+
+ Addr target_addr = base_addr_ + rel.r_offset;
+ Addr target_value = *reinterpret_cast<Addr*>(target_addr);
+ Addr reloc = static_cast<Addr>(rel.r_offset + base_addr_);
+ target_value += (sym_addr - reloc);
+
+ // Expected relocation calculation:
+ // *target += (sym_addr - reloc);
+ relocations_->ApplyResolvedReloc(&rel, sym_addr);
+
+ EXPECT_EQ(target_value, *reinterpret_cast<Addr*>(target_addr));
+}
+#endif // SB_IS(ARCH_X86)
+
+#if SB_IS(ARCH_X64) && defined(USE_RELA)
+TEST_F(RelocationsTest, R_X86_64_JMP_SLOT) {
+ rel_t rel;
+ rel.r_offset = 0;
+ rel.r_info = R_X86_64_JMP_SLOT;
+ rel.r_addend = kTestAddend;
+ Addr sym_addr = kTestAddress;
+
+ // Expected relocation calculation:
+ // *target = sym_addr + addend;
+ relocations_->ApplyResolvedReloc(&rel, sym_addr);
+
+ VerifySymAddressPlusAddend(&rel, sym_addr);
+}
+
+TEST_F(RelocationsTest, R_X86_64_GLOB_DAT) {
+ rel_t rel;
+ rel.r_offset = 1;
+ rel.r_info = R_X86_64_GLOB_DAT;
+ rel.r_addend = kTestAddend;
+ Addr sym_addr = kTestAddress;
+
+ // Expected relocation calculation:
+ // *target = sym_addr + addend;
+ relocations_->ApplyResolvedReloc(&rel, sym_addr);
+
+ VerifySymAddressPlusAddend(&rel, sym_addr);
+}
+
+TEST_F(RelocationsTest, R_X86_64_RELATIVE) {
+ rel_t rel;
+ rel.r_offset = 2;
+ rel.r_info = R_X86_64_RELATIVE;
+ rel.r_addend = kTestAddend;
+ Addr sym_addr = kTestAddress;
+
+ // Expected relocation calculation:
+ // *target = base_memory_address_ + addend;
+ relocations_->ApplyResolvedReloc(&rel, sym_addr);
+
+ VerifyBaseAddressPlusAddend(&rel);
+}
+
+TEST_F(RelocationsTest, R_X86_64_64) {
+ rel_t rel;
+ rel.r_offset = 3;
+ rel.r_info = R_X86_64_64;
+ rel.r_addend = kTestAddend;
+ Addr sym_addr = kTestAddress;
+
+ // Expected relocation calculation:
+ // *target = sym_addr + addend;
+ relocations_->ApplyResolvedReloc(&rel, sym_addr);
+
+ VerifySymAddressPlusAddend(&rel, sym_addr);
+}
+
+TEST_F(RelocationsTest, R_X86_64_PC32) {
+ rel_t rel;
+ rel.r_offset = 4;
+ rel.r_info = R_X86_64_PC32;
+ rel.r_addend = kTestAddend;
+ Addr sym_addr = kTestAddress;
+
+ relocations_->ApplyResolvedReloc(&rel, sym_addr);
+
+ // Expected relocation calculation:
+ // *target = sym_addr + (addend - reloc);
+ VerifySymAddressPlusAddendDelta(&rel, sym_addr);
+}
+#endif // SB_IS(ARCH_X64) && defined(USE_RELA)
+
+} // namespace
+} // namespace elf_loader
+} // namespace starboard
+#endif // SB_API_VERSION >= 12 && (SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION
+ // || SB_HAS(MMAP)) && SB_CAN(MAP_EXECUTABLE_MEMORY)
diff --git a/src/starboard/elf_loader/sandbox.cc b/src/starboard/elf_loader/sandbox.cc
new file mode 100644
index 0000000..8b6e9da
--- /dev/null
+++ b/src/starboard/elf_loader/sandbox.cc
@@ -0,0 +1,84 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <string>
+
+#include "starboard/common/log.h"
+#include "starboard/elf_loader/elf_loader.h"
+#include "starboard/elf_loader/elf_loader_switches.h"
+#include "starboard/event.h"
+#include "starboard/mutex.h"
+#include "starboard/shared/starboard/command_line.h"
+#include "starboard/thread_types.h"
+
+starboard::elf_loader::ElfLoader g_elf_loader;
+
+void (*g_sb_event_func)(const SbEvent*) = NULL;
+
+void LoadLibraryAndInitialize(const std::string& library_path,
+ const std::string& content_path) {
+ if (library_path.empty()) {
+ SB_LOG(ERROR) << "Library must be specified with --"
+ << starboard::elf_loader::kEvergreenLibrary
+ << "=path/to/library/relative/to/loader/content.";
+ return;
+ }
+ if (content_path.empty()) {
+ SB_LOG(ERROR) << "Content must be specified with --"
+ << starboard::elf_loader::kEvergreenContent
+ << "=path/to/content/relative/to/loader/content.";
+ return;
+ }
+ if (!g_elf_loader.Load(library_path, content_path, true)) {
+ SB_NOTREACHED() << "Failed to load library at '"
+ << g_elf_loader.GetLibraryPath() << "'.";
+ return;
+ }
+
+ SB_LOG(INFO) << "Successfully loaded '" << g_elf_loader.GetLibraryPath()
+ << "'.";
+
+ g_sb_event_func = reinterpret_cast<void (*)(const SbEvent*)>(
+ g_elf_loader.LookupSymbol("SbEventHandle"));
+
+ if (!g_sb_event_func) {
+ SB_LOG(ERROR) << "Failed to find SbEventHandle.";
+ return;
+ }
+
+ SB_LOG(INFO) << "Found SbEventHandle at address: "
+ << reinterpret_cast<void*>(g_sb_event_func);
+}
+
+void SbEventHandle(const SbEvent* event) {
+ static SbMutex mutex = SB_MUTEX_INITIALIZER;
+
+ SB_CHECK(SbMutexAcquire(&mutex) == kSbMutexAcquired);
+
+ if (!g_sb_event_func) {
+ const SbEventStartData* data =
+ static_cast<SbEventStartData*>(event->data);
+ const starboard::shared::starboard::CommandLine command_line(
+ data->argument_count,
+ const_cast<const char**>(data->argument_values));
+ LoadLibraryAndInitialize(
+ command_line.GetSwitchValue(starboard::elf_loader::kEvergreenLibrary),
+ command_line.GetSwitchValue(starboard::elf_loader::kEvergreenContent));
+ SB_CHECK(g_sb_event_func);
+ }
+
+ g_sb_event_func(event);
+
+ SB_CHECK(SbMutexRelease(&mutex) == true);
+}
diff --git a/src/starboard/linux/x64x11/sbversion/6/__init__.py b/src/starboard/evergreen/__init__.py
similarity index 100%
copy from src/starboard/linux/x64x11/sbversion/6/__init__.py
copy to src/starboard/evergreen/__init__.py
diff --git a/src/starboard/linux/x64x11/sbversion/6/__init__.py b/src/starboard/evergreen/arm/__init__.py
similarity index 100%
copy from src/starboard/linux/x64x11/sbversion/6/__init__.py
copy to src/starboard/evergreen/arm/__init__.py
diff --git a/src/starboard/linux/x64x11/sbversion/6/__init__.py b/src/starboard/evergreen/arm/hardfp/__init__.py
similarity index 100%
copy from src/starboard/linux/x64x11/sbversion/6/__init__.py
copy to src/starboard/evergreen/arm/hardfp/__init__.py
diff --git a/src/starboard/linux/x64x11/mozjs/atomic_public.h b/src/starboard/evergreen/arm/hardfp/atomic_public.h
similarity index 64%
rename from src/starboard/linux/x64x11/mozjs/atomic_public.h
rename to src/starboard/evergreen/arm/hardfp/atomic_public.h
index 503b0a1..d9786c1 100644
--- a/src/starboard/linux/x64x11/mozjs/atomic_public.h
+++ b/src/starboard/evergreen/arm/hardfp/atomic_public.h
@@ -1,4 +1,4 @@
-// Copyright 2018 The Cobalt Authors. All Rights Reserved.
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,9 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef STARBOARD_LINUX_X64X11_MOZJS_ATOMIC_PUBLIC_H_
-#define STARBOARD_LINUX_X64X11_MOZJS_ATOMIC_PUBLIC_H_
+#ifndef STARBOARD_EVERGREEN_ARM_HARDFP_ATOMIC_PUBLIC_H_
+#define STARBOARD_EVERGREEN_ARM_HARDFP_ATOMIC_PUBLIC_H_
-#include "starboard/linux/shared/atomic_public.h"
+#include "starboard/atomic.h"
+#include "starboard/shared/gcc/atomic_gcc_public.h"
-#endif // STARBOARD_LINUX_X64X11_MOZJS_ATOMIC_PUBLIC_H_
+#endif // STARBOARD_EVERGREEN_ARM_HARDFP_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/evergreen/arm/hardfp/configuration_public.h b/src/starboard/evergreen/arm/hardfp/configuration_public.h
new file mode 100644
index 0000000..b813c19
--- /dev/null
+++ b/src/starboard/evergreen/arm/hardfp/configuration_public.h
@@ -0,0 +1,200 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// The Starboard configuration for X86_64. Other devices will have
+// specific Starboard implementations.
+
+// Other source files should never include this header directly, but should
+// include the generic "starboard/configuration.h" instead.
+
+#ifndef STARBOARD_EVERGREEN_ARM_HARDFP_CONFIGURATION_PUBLIC_H_
+#define STARBOARD_EVERGREEN_ARM_HARDFP_CONFIGURATION_PUBLIC_H_
+
+// --- System Header Configuration -------------------------------------------
+
+// Any system headers listed here that are not provided by the platform will be
+// emulated in starboard/types.h.
+
+// Whether the current platform provides the standard header stdarg.h.
+#define SB_HAS_STDARG_H 1
+
+// Whether the current platform provides the standard header stdbool.h.
+#define SB_HAS_STDBOOL_H 1
+
+// Whether the current platform provides the standard header stddef.h.
+#define SB_HAS_STDDEF_H 1
+
+// Whether the current platform provides the standard header stdint.h.
+#define SB_HAS_STDINT_H 1
+
+// Whether the current platform provides the standard header inttypes.h.
+#define SB_HAS_INTTYPES_H 1
+
+// Whether the current platform provides the standard header sys/types.h.
+#define SB_HAS_SYS_TYPES_H 1
+
+// Whether the current platform provides the standard header wchar.h.
+#define SB_HAS_WCHAR_H 1
+
+// Whether the current platform provides the standard header limits.h.
+#define SB_HAS_LIMITS_H 1
+
+// Whether the current platform provides the standard header float.h.
+#define SB_HAS_FLOAT_H 1
+
+// Whether the current platform provides ssize_t.
+#define SB_HAS_SSIZE_T 1
+
+// Type detection for wchar_t.
+#if defined(__WCHAR_MAX__) && \
+ (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff)
+#define SB_IS_WCHAR_T_UTF32 1
+#elif defined(__WCHAR_MAX__) && \
+ (__WCHAR_MAX__ == 0x7fff || __WCHAR_MAX__ == 0xffff)
+#define SB_IS_WCHAR_T_UTF16 1
+#endif
+
+// Chrome only defines these two if ARMEL or MIPSEL are defined.
+#if defined(__ARMEL__)
+// Chrome has an exclusion for iOS here, we should too when we support iOS.
+#define SB_IS_WCHAR_T_UNSIGNED 1
+#elif defined(__MIPSEL__)
+#define SB_IS_WCHAR_T_SIGNED 1
+#endif
+
+// --- Compiler Configuration ------------------------------------------------
+
+// The platform's annotation for forcing a C function to be inlined.
+#define SB_C_FORCE_INLINE __inline__ __attribute__((always_inline))
+
+// The platform's annotation for marking a C function as suggested to be
+// inlined.
+#define SB_C_INLINE inline
+
+// The platform's annotation for marking a C function as forcibly not
+// inlined.
+#define SB_C_NOINLINE __attribute__((noinline))
+
+// The platform's annotation for marking a symbol as exported outside of the
+// current shared library.
+#define SB_EXPORT_PLATFORM __attribute__((visibility("default")))
+
+// The platform's annotation for marking a symbol as imported from outside of
+// the current linking unit.
+#define SB_IMPORT_PLATFORM
+
+// --- Extensions Configuration ----------------------------------------------
+
+// Do not use <unordered_map> and <unordered_set> for the hash table types.
+#define SB_HAS_STD_UNORDERED_HASH 0
+
+// GCC/Clang doesn't define a long long hash function, except for Android and
+// Game consoles.
+#define SB_HAS_LONG_LONG_HASH 0
+
+// GCC/Clang doesn't define a string hash function, except for Game Consoles.
+#define SB_HAS_STRING_HASH 0
+
+// Desktop Linux needs a using statement for the hash functions.
+#define SB_HAS_HASH_USING 0
+
+// Set this to 1 if hash functions for custom types can be defined as a
+// hash_value() function. Otherwise, they need to be placed inside a
+// partially-specified hash struct template with an operator().
+#define SB_HAS_HASH_VALUE 0
+
+// Set this to 1 if use of hash_map or hash_set causes a deprecation warning
+// (which then breaks the build).
+#define SB_HAS_HASH_WARNING 1
+
+// The location to include hash_map on this platform.
+#define SB_HASH_MAP_INCLUDE <ext/hash_map>
+
+// C++'s hash_map and hash_set are often found in different namespaces depending
+// on the compiler.
+#define SB_HASH_NAMESPACE __gnu_cxx
+
+// The location to include hash_set on this platform.
+#define SB_HASH_SET_INCLUDE <ext/hash_set>
+
+// Define this to how this platform copies varargs blocks.
+#define SB_VA_COPY(dest, source) va_copy(dest, source)
+
+// --- Graphics Configuration ------------------------------------------------
+
+// Specifies whether this platform supports a performant accelerated blitter
+// API. The basic requirement is a scaled, clipped, alpha-blended blit.
+#define SB_HAS_BLITTER 0
+
+// Indicates whether or not the given platform supports bilinear filtering.
+// This can be checked to enable/disable renderer tests that verify that this is
+// working properly.
+#define SB_HAS_BILINEAR_FILTERING_SUPPORT 1
+
+// Indicates whether or not the given platform supports rendering of NV12
+// textures. These textures typically originate from video decoders.
+#define SB_HAS_NV12_TEXTURE_SUPPORT 1
+
+// --- I/O Configuration -----------------------------------------------------
+
+// Whether the current platform implements the on screen keyboard interface.
+#define SB_HAS_ON_SCREEN_KEYBOARD 0
+
+// Whether the current platform has speech recognizer.
+#define SB_HAS_SPEECH_RECOGNIZER 0
+
+// Whether the current platform has speech synthesis.
+#define SB_HAS_SPEECH_SYNTHESIS 0
+
+// --- Decoder-only Params ---
+
+// --- Memory Configuration --------------------------------------------------
+
+// Whether this platform has and should use an MMAP function to map physical
+// memory to the virtual address space.
+#if SB_API_VERSION < SB_MMAP_REQUIRED_VERSION
+#define SB_HAS_MMAP 1
+#endif
+
+// Whether this platform can map executable memory. Implies SB_HAS_MMAP. This is
+// required for platforms that want to JIT.
+#define SB_CAN_MAP_EXECUTABLE_MEMORY 1
+
+// --- Network Configuration -------------------------------------------------
+
+// Specifies whether this platform supports IPV6.
+#define SB_HAS_IPV6 1
+
+// Specifies whether this platform supports pipe.
+#define SB_HAS_PIPE 1
+
+// --- Thread Configuration --------------------------------------------------
+
+// --- Timing API ------------------------------------------------------------
+
+// Whether this platform has an API to retrieve how long the current thread
+// has spent in the executing state.
+#define SB_HAS_TIME_THREAD_NOW 1
+
+// --- Tuneable Parameters ---------------------------------------------------
+
+// --- User Configuration ----------------------------------------------------
+
+// --- Platform Specific Audits ----------------------------------------------
+
+#if !defined(__GNUC__)
+#error "Evergreen-arm builds need a GCC-like compiler (for the moment)."
+#endif
+
+#endif // STARBOARD_EVERGREEN_ARM_HARDFP_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/6/gyp_configuration.gypi b/src/starboard/evergreen/arm/hardfp/gyp_configuration.gypi
similarity index 73%
rename from src/starboard/linux/x64x11/blittergles/sbversion/6/gyp_configuration.gypi
rename to src/starboard/evergreen/arm/hardfp/gyp_configuration.gypi
index 3b6dac2..4ba76c1 100644
--- a/src/starboard/linux/x64x11/blittergles/sbversion/6/gyp_configuration.gypi
+++ b/src/starboard/evergreen/arm/hardfp/gyp_configuration.gypi
@@ -16,25 +16,27 @@
# though it may have been modified since its creation.
{
+ 'variables': {
+ 'sb_target_platform': 'evergreen-arm-hardfp',
+ },
'target_defaults': {
- 'default_configuration': 'linux-x64x11-blittergles-sbversion-6_debug',
+ 'default_configuration': 'evergreen-arm-hardfp_debug',
'configurations': {
- 'linux-x64x11-blittergles-sbversion-6_debug': {
+ 'evergreen-arm-hardfp_debug': {
'inherit_from': ['debug_base'],
},
- 'linux-x64x11-blittergles-sbversion-6_devel': {
+ 'evergreen-arm-hardfp_devel': {
'inherit_from': ['devel_base'],
},
- 'linux-x64x11-blittergles-sbversion-6_qa': {
+ 'evergreen-arm-hardfp_qa': {
'inherit_from': ['qa_base'],
},
- 'linux-x64x11-blittergles-sbversion-6_gold': {
+ 'evergreen-arm-hardfp_gold': {
'inherit_from': ['gold_base'],
},
}, # end of configurations
},
-
'includes': [
- '<(DEPTH)/starboard/linux/x64x11/blittergles/shared/gyp_configuration.gypi',
+ '<(DEPTH)/starboard/evergreen/arm/shared/gyp_configuration.gypi',
],
}
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/6/starboard_platform_tests.gyp b/src/starboard/evergreen/arm/hardfp/gyp_configuration.py
similarity index 68%
rename from src/starboard/linux/x64x11/blittergles/sbversion/6/starboard_platform_tests.gyp
rename to src/starboard/evergreen/arm/hardfp/gyp_configuration.py
index 94e7cc2..467ce05 100644
--- a/src/starboard/linux/x64x11/blittergles/sbversion/6/starboard_platform_tests.gyp
+++ b/src/starboard/evergreen/arm/hardfp/gyp_configuration.py
@@ -14,11 +14,12 @@
# This file was initially generated by starboard/tools/create_derived_build.py,
# though it may have been modified since its creation.
+"""Starboard evergreen-arm-hardfp platform configuration for gyp_cobalt."""
-{
- 'includes': [
- # Note that we are 'includes'ing a 'gyp' file, not a 'gypi' file. The idea
- # is that we just want this file to *be* the parent gyp file.
- '<(DEPTH)/starboard/linux/x64x11/blittergles/starboard_platform_tests.gyp',
- ],
-}
+from starboard.evergreen.arm.shared import gyp_configuration as parent_configuration
+
+
+def CreatePlatformConfig():
+ return parent_configuration.EvergreenArmConfiguration(
+ 'evergreen-arm-hardfp',
+ sabi_json_path='starboard/sabi/arm/hardfp/sabi.json')
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/6/starboard_platform.gyp b/src/starboard/evergreen/arm/hardfp/starboard_platform.gyp
similarity index 92%
rename from src/starboard/linux/x64x11/blittergles/sbversion/6/starboard_platform.gyp
rename to src/starboard/evergreen/arm/hardfp/starboard_platform.gyp
index 8163408..8787f61 100644
--- a/src/starboard/linux/x64x11/blittergles/sbversion/6/starboard_platform.gyp
+++ b/src/starboard/evergreen/arm/hardfp/starboard_platform.gyp
@@ -19,6 +19,7 @@
'includes': [
# Note that we are 'includes'ing a 'gyp' file, not a 'gypi' file. The idea
# is that we just want this file to *be* the parent gyp file.
- '<(DEPTH)/starboard/linux/x64x11/blittergles/starboard_platform.gyp',
+ '<(DEPTH)/starboard/evergreen/shared/starboard_platform.gyp',
],
}
+
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/6/atomic_public.h b/src/starboard/evergreen/arm/hardfp/thread_types_public.h
similarity index 72%
rename from src/starboard/linux/x64x11/blittergles/sbversion/6/atomic_public.h
rename to src/starboard/evergreen/arm/hardfp/thread_types_public.h
index d2414dd..fda18eb 100644
--- a/src/starboard/linux/x64x11/blittergles/sbversion/6/atomic_public.h
+++ b/src/starboard/evergreen/arm/hardfp/thread_types_public.h
@@ -15,9 +15,9 @@
// This file was initially generated by starboard/tools/create_derived_build.py,
// though it may have been modified since its creation.
-#ifndef STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_6_ATOMIC_PUBLIC_H_
-#define STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_6_ATOMIC_PUBLIC_H_
+#ifndef STARBOARD_EVERGREEN_ARM_HARDFP_THREAD_TYPES_PUBLIC_H_
+#define STARBOARD_EVERGREEN_ARM_HARDFP_THREAD_TYPES_PUBLIC_H_
-#include "starboard/linux/x64x11/blittergles/atomic_public.h"
+#include "starboard/shared/pthread/types_public.h"
-#endif // STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_6_ATOMIC_PUBLIC_H_
+#endif // STARBOARD_EVERGREEN_ARM_HARDFP_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/sbversion/6/__init__.py b/src/starboard/evergreen/arm/shared/__init__.py
similarity index 100%
copy from src/starboard/linux/x64x11/sbversion/6/__init__.py
copy to src/starboard/evergreen/arm/shared/__init__.py
diff --git a/src/starboard/linux/x64x11/sbversion/6/__init__.py b/src/starboard/evergreen/arm/shared/cobalt/__init__.py
similarity index 100%
copy from src/starboard/linux/x64x11/sbversion/6/__init__.py
copy to src/starboard/evergreen/arm/shared/cobalt/__init__.py
diff --git a/src/starboard/linux/x64x11/mozjs/starboard_platform_tests.gyp b/src/starboard/evergreen/arm/shared/cobalt/configuration.gypi
similarity index 75%
rename from src/starboard/linux/x64x11/mozjs/starboard_platform_tests.gyp
rename to src/starboard/evergreen/arm/shared/cobalt/configuration.gypi
index 0ea8622..89aca9a 100644
--- a/src/starboard/linux/x64x11/mozjs/starboard_platform_tests.gyp
+++ b/src/starboard/evergreen/arm/shared/cobalt/configuration.gypi
@@ -1,4 +1,4 @@
-# Copyright 2018 The Cobalt Authors. All Rights Reserved.
+# Copyright 2020 The Cobalt Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -11,8 +11,11 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+
+# Cobalt Evergreen ARM specific configuration.
+
{
- 'includes': [
- '<(DEPTH)/starboard/linux/shared/starboard_platform_tests.gypi',
- ],
+ 'variables': {
+ 'in_app_dial%': 0,
+ }, # end of variables
}
diff --git a/src/starboard/evergreen/arm/shared/cobalt/configuration.py b/src/starboard/evergreen/arm/shared/cobalt/configuration.py
new file mode 100644
index 0000000..0d71086
--- /dev/null
+++ b/src/starboard/evergreen/arm/shared/cobalt/configuration.py
@@ -0,0 +1,83 @@
+# Copyright 2020 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Starboard Cobalt Evergreen ARM configuration."""
+
+import os
+
+from cobalt.build import cobalt_configuration
+from starboard.tools.testing import test_filter
+
+
+class CobaltARMConfiguration(cobalt_configuration.CobaltConfiguration):
+ """Starboard Cobalt Evergreen ARM configuration."""
+
+ def __init__(self, platform_configuration, application_name,
+ application_directory):
+ super(CobaltARMConfiguration,
+ self).__init__(platform_configuration, application_name,
+ application_directory)
+
+ def GetPostIncludes(self):
+ # If there isn't a configuration.gypi found in the usual place, we'll
+ # supplement with our shared implementation.
+ includes = super(CobaltARMConfiguration, self).GetPostIncludes()
+ for include in includes:
+ if os.path.basename(include) == 'configuration.gypi':
+ return includes
+
+ shared_gypi_path = os.path.join(
+ os.path.dirname(__file__), 'configuration.gypi')
+ if os.path.isfile(shared_gypi_path):
+ includes.append(shared_gypi_path)
+ return includes
+
+ def WebdriverBenchmarksEnabled(self):
+ return True
+
+ def GetTestFilters(self):
+ filters = super(CobaltARMConfiguration, self).GetTestFilters()
+ for target, tests in self.__FILTERED_TESTS.iteritems():
+ filters.extend(test_filter.TestFilter(target, test) for test in tests)
+ return filters
+
+ def GetWebPlatformTestFilters(self):
+ filters = super(CobaltARMConfiguration, self).GetWebPlatformTestFilters()
+ filters += [
+ ('csp/WebPlatformTest.Run/'
+ 'content_security_policy_media_src_media_src_allowed_html'),
+ ('websockets/WebPlatformTest.Run/websockets_*'),
+ ]
+ return filters
+
+ def GetTestEnvVariables(self):
+ return {
+ 'base_unittests': {
+ 'ASAN_OPTIONS': 'detect_leaks=0'
+ },
+ 'crypto_unittests': {
+ 'ASAN_OPTIONS': 'detect_leaks=0'
+ },
+ 'net_unittests': {
+ 'ASAN_OPTIONS': 'detect_leaks=0'
+ }
+ }
+
+ __FILTERED_TESTS = {
+ 'base_unittests': [test_filter.FILTER_ALL],
+ 'bindings_test': ['DateBindingsTest.PosixEpoch'],
+ 'net_unittests': [test_filter.FILTER_ALL],
+ 'renderer_test': [
+ 'PixelTest.CircularSubPixelBorder', 'PixelTest.FilterBlurred100PxText'
+ ],
+ }
diff --git a/src/starboard/evergreen/arm/shared/gyp_configuration.gypi b/src/starboard/evergreen/arm/shared/gyp_configuration.gypi
new file mode 100644
index 0000000..404d3a3
--- /dev/null
+++ b/src/starboard/evergreen/arm/shared/gyp_configuration.gypi
@@ -0,0 +1,50 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file was initially generated by starboard/tools/create_derived_build.py,
+# though it may have been modified since its creation.
+
+{
+ 'variables': {
+ 'yasm_exists': 1,
+
+ 'compiler_flags': [
+ '-isystem<(cobalt_repo_root)/third_party/musl/arch/arm',
+
+ # Force char to be signed.
+ '-fsigned-char',
+ ],
+
+ 'linker_flags': [
+ '-fuse-ld=lld',
+ ],
+ },
+ 'target_defaults': {
+ 'defines' : [
+ # Ensure that the Starboardized __external_threading file is included.
+ '_LIBCPP_HAS_THREAD_API_EXTERNAL',
+
+ # Ensure that only the forward declarations and type definitions are included
+ # in __external_threading.
+ '_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL',
+
+ # Enable GNU extensions to get prototypes like ffsl.
+ '_GNU_SOURCE=1',
+ ],
+ },
+ 'includes': [
+ '<(DEPTH)/starboard/evergreen/shared/compiler_flags.gypi',
+ '<(DEPTH)/starboard/evergreen/shared/gyp_configuration.gypi',
+ ],
+}
diff --git a/src/starboard/evergreen/arm/shared/gyp_configuration.py b/src/starboard/evergreen/arm/shared/gyp_configuration.py
new file mode 100644
index 0000000..d442333
--- /dev/null
+++ b/src/starboard/evergreen/arm/shared/gyp_configuration.py
@@ -0,0 +1,103 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Starboard Evergreen ARM shared platform configuration for gyp_cobalt."""
+
+import os.path
+
+from starboard.build import clang as clang_build
+from starboard.evergreen.shared import gyp_configuration as shared_configuration
+from starboard.tools import build
+from starboard.tools.testing import test_filter
+from starboard.tools.toolchain import ar
+from starboard.tools.toolchain import bash
+from starboard.tools.toolchain import clang
+from starboard.tools.toolchain import clangxx
+from starboard.tools.toolchain import cp
+from starboard.tools.toolchain import evergreen_linker
+from starboard.tools.toolchain import touch
+
+
+class EvergreenArmConfiguration(shared_configuration.EvergreenConfiguration):
+ """Starboard Evergreen ARM platform configuration."""
+
+ def __init__(self,
+ platform_name='evergreen-arm',
+ asan_enabled_by_default=False,
+ goma_supports_compiler=True,
+ sabi_json_path=None):
+ # pylint: disable=useless-super-delegation
+ super(EvergreenArmConfiguration,
+ self).__init__(platform_name, asan_enabled_by_default,
+ goma_supports_compiler, sabi_json_path)
+ self.AppendApplicationConfigurationPath(os.path.dirname(__file__))
+ self._host_toolchain = None
+
+ def GetTargetToolchain(self):
+ return self.GetHostToolchain()
+
+ def GetHostToolchain(self):
+ if not self._host_toolchain:
+ if not hasattr(self, 'host_compiler_environment'):
+ self.host_compiler_environment = build.GetHostCompilerEnvironment(
+ clang_build.GetClangSpecification(), False)
+ cc_path = self.host_compiler_environment['CC_host']
+ cxx_path = self.host_compiler_environment['CXX_host']
+
+ # Takes the provided value of CXX_HOST with a prepended 'gomacc' and an
+ # appended 'bin/clang++' and strips them off, leaving us with an absolute
+ # path to the root directory of our toolchain.
+ begin_path_index = cxx_path.find('/')
+ end_path_index = cxx_path.rfind('/', 0, cxx_path.rfind('/')) + 1
+
+ cxx_path_root = cxx_path[begin_path_index:end_path_index]
+
+ self._host_toolchain = [
+ clang.CCompiler(path=cc_path),
+ clang.CxxCompiler(path=cxx_path),
+ clang.AssemblerWithCPreprocessor(path=cc_path),
+ ar.StaticThinLinker(),
+ ar.StaticLinker(),
+ clangxx.ExecutableLinker(path=cxx_path),
+ evergreen_linker.SharedLibraryLinker(
+ path=cxx_path_root, extra_flags=['-m armelf']),
+ cp.Copy(),
+ touch.Stamp(),
+ bash.Shell(),
+ ]
+ return self._host_toolchain
+
+ def GetTestFilters(self):
+ filters = super(EvergreenArmConfiguration, self).GetTestFilters()
+ for target, tests in self.__FILTERED_TESTS.iteritems():
+ filters.extend(test_filter.TestFilter(target, test) for test in tests)
+ return filters
+
+ def GetVariables(self, configuration):
+ variables = super(EvergreenArmConfiguration, self).GetVariables(configuration)
+ variables.update({
+ 'include_path_platform_deploy_gypi':
+ 'starboard/evergreen/arm/shared/platform_deploy.gypi',
+ })
+ return variables
+
+ __FILTERED_TESTS = { # pylint: disable=invalid-name
+ 'nplb': ['SbSystemGetStackTest.SunnyDayStackDirection',
+ 'SbSystemGetStackTest.SunnyDay',
+ 'SbSystemGetStackTest.SunnyDayShortStack',
+ 'SbSystemSymbolizeTest.SunnyDay'],
+ }
+
+
+def CreatePlatformConfig():
+ return EvergreenArmConfiguration()
diff --git a/src/starboard/evergreen/arm/shared/platform_deploy.gypi b/src/starboard/evergreen/arm/shared/platform_deploy.gypi
new file mode 100644
index 0000000..fef9168
--- /dev/null
+++ b/src/starboard/evergreen/arm/shared/platform_deploy.gypi
@@ -0,0 +1,37 @@
+# Copyright 2020 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+{
+ 'variables': {
+ 'deploy_executable_file': '<(target_deploy_dir)/lib/lib<(executable_name).so',
+ 'executable_file': '<(PRODUCT_DIR)/lib/lib<(executable_name).so',
+ },
+ 'includes': [ '<(DEPTH)/starboard/build/collect_deploy_content.gypi' ],
+ 'actions': [
+ {
+ 'action_name': 'deploy_executable',
+ 'message': 'Strip executable: <(deploy_executable_file)',
+ 'inputs': [
+ '<(executable_file)',
+ '<(content_deploy_stamp_file)',
+ ],
+ 'outputs': [ '<(deploy_executable_file)' ],
+ 'action': [
+ 'arm-linux-gnueabi-strip',
+ '-o', '<(deploy_executable_file)',
+ '<(executable_file)',
+ ],
+ },
+ ],
+}
diff --git a/src/starboard/linux/x64x11/sbversion/6/__init__.py b/src/starboard/evergreen/arm/softfp/__init__.py
similarity index 100%
copy from src/starboard/linux/x64x11/sbversion/6/__init__.py
copy to src/starboard/evergreen/arm/softfp/__init__.py
diff --git a/src/starboard/linux/x64x11/mozjs/atomic_public.h b/src/starboard/evergreen/arm/softfp/atomic_public.h
similarity index 64%
copy from src/starboard/linux/x64x11/mozjs/atomic_public.h
copy to src/starboard/evergreen/arm/softfp/atomic_public.h
index 503b0a1..48e2e37 100644
--- a/src/starboard/linux/x64x11/mozjs/atomic_public.h
+++ b/src/starboard/evergreen/arm/softfp/atomic_public.h
@@ -1,4 +1,4 @@
-// Copyright 2018 The Cobalt Authors. All Rights Reserved.
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,9 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef STARBOARD_LINUX_X64X11_MOZJS_ATOMIC_PUBLIC_H_
-#define STARBOARD_LINUX_X64X11_MOZJS_ATOMIC_PUBLIC_H_
+#ifndef STARBOARD_EVERGREEN_ARM_SOFTFP_ATOMIC_PUBLIC_H_
+#define STARBOARD_EVERGREEN_ARM_SOFTFP_ATOMIC_PUBLIC_H_
-#include "starboard/linux/shared/atomic_public.h"
+#include "starboard/atomic.h"
+#include "starboard/shared/gcc/atomic_gcc_public.h"
-#endif // STARBOARD_LINUX_X64X11_MOZJS_ATOMIC_PUBLIC_H_
+#endif // STARBOARD_EVERGREEN_ARM_SOFTFP_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/evergreen/arm/softfp/configuration_public.h b/src/starboard/evergreen/arm/softfp/configuration_public.h
new file mode 100644
index 0000000..1743bba
--- /dev/null
+++ b/src/starboard/evergreen/arm/softfp/configuration_public.h
@@ -0,0 +1,203 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// The Starboard configuration for X86_64. Other devices will have
+// specific Starboard implementations.
+
+// Other source files should never include this header directly, but should
+// include the generic "starboard/configuration.h" instead.
+
+#ifndef STARBOARD_EVERGREEN_ARM_SOFTFP_CONFIGURATION_PUBLIC_H_
+#define STARBOARD_EVERGREEN_ARM_SOFTFP_CONFIGURATION_PUBLIC_H_
+
+// --- System Header Configuration -------------------------------------------
+
+// Any system headers listed here that are not provided by the platform will be
+// emulated in starboard/types.h.
+
+// Whether the current platform provides the standard header stdarg.h.
+#define SB_HAS_STDARG_H 1
+
+// Whether the current platform provides the standard header stdbool.h.
+#define SB_HAS_STDBOOL_H 1
+
+// Whether the current platform provides the standard header stddef.h.
+#define SB_HAS_STDDEF_H 1
+
+// Whether the current platform provides the standard header stdint.h.
+#define SB_HAS_STDINT_H 1
+
+// Whether the current platform provides the standard header inttypes.h.
+#define SB_HAS_INTTYPES_H 1
+
+// Whether the current platform provides the standard header sys/types.h.
+#define SB_HAS_SYS_TYPES_H 1
+
+// Whether the current platform provides the standard header wchar.h.
+#define SB_HAS_WCHAR_H 1
+
+// Whether the current platform provides the standard header limits.h.
+#define SB_HAS_LIMITS_H 1
+
+// Whether the current platform provides the standard header float.h.
+#define SB_HAS_FLOAT_H 1
+
+// Whether the current platform provides ssize_t.
+#define SB_HAS_SSIZE_T 1
+
+// Type detection for wchar_t.
+#if defined(__WCHAR_MAX__) && \
+ (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff)
+#define SB_IS_WCHAR_T_UTF32 1
+#elif defined(__WCHAR_MAX__) && \
+ (__WCHAR_MAX__ == 0x7fff || __WCHAR_MAX__ == 0xffff)
+#define SB_IS_WCHAR_T_UTF16 1
+#endif
+
+// Chrome only defines these two if ARMEL or MIPSEL are defined.
+#if defined(__ARMEL__)
+// Chrome has an exclusion for iOS here, we should too when we support iOS.
+#define SB_IS_WCHAR_T_UNSIGNED 1
+#elif defined(__MIPSEL__)
+#define SB_IS_WCHAR_T_SIGNED 1
+#endif
+
+// --- Compiler Configuration ------------------------------------------------
+
+// The platform's annotation for forcing a C function to be inlined.
+#define SB_C_FORCE_INLINE __inline__ __attribute__((always_inline))
+
+// The platform's annotation for marking a C function as suggested to be
+// inlined.
+#define SB_C_INLINE inline
+
+// The platform's annotation for marking a C function as forcibly not
+// inlined.
+#define SB_C_NOINLINE __attribute__((noinline))
+
+// The platform's annotation for marking a symbol as exported outside of the
+// current shared library.
+#define SB_EXPORT_PLATFORM __attribute__((visibility("default")))
+
+// The platform's annotation for marking a symbol as imported from outside of
+// the current linking unit.
+#define SB_IMPORT_PLATFORM
+
+// --- Extensions Configuration ----------------------------------------------
+
+// Do not use <unordered_map> and <unordered_set> for the hash table types.
+#define SB_HAS_STD_UNORDERED_HASH 0
+
+// GCC/Clang doesn't define a long long hash function, except for Android and
+// Game consoles.
+#define SB_HAS_LONG_LONG_HASH 0
+
+// GCC/Clang doesn't define a string hash function, except for Game Consoles.
+#define SB_HAS_STRING_HASH 0
+
+// Desktop Linux needs a using statement for the hash functions.
+#define SB_HAS_HASH_USING 0
+
+// Set this to 1 if hash functions for custom types can be defined as a
+// hash_value() function. Otherwise, they need to be placed inside a
+// partially-specified hash struct template with an operator().
+#define SB_HAS_HASH_VALUE 0
+
+// Set this to 1 if use of hash_map or hash_set causes a deprecation warning
+// (which then breaks the build).
+#define SB_HAS_HASH_WARNING 1
+
+// The location to include hash_map on this platform.
+#define SB_HASH_MAP_INCLUDE <ext/hash_map>
+
+// C++'s hash_map and hash_set are often found in different namespaces depending
+// on the compiler.
+#define SB_HASH_NAMESPACE __gnu_cxx
+
+// The location to include hash_set on this platform.
+#define SB_HASH_SET_INCLUDE <ext/hash_set>
+
+// Define this to how this platform copies varargs blocks.
+#define SB_VA_COPY(dest, source) va_copy(dest, source)
+
+// --- Graphics Configuration ------------------------------------------------
+
+// Specifies whether this platform supports a performant accelerated blitter
+// API. The basic requirement is a scaled, clipped, alpha-blended blit.
+#define SB_HAS_BLITTER 0
+
+// Indicates whether or not the given platform supports bilinear filtering.
+// This can be checked to enable/disable renderer tests that verify that this is
+// working properly.
+#define SB_HAS_BILINEAR_FILTERING_SUPPORT 1
+
+// Indicates whether or not the given platform supports rendering of NV12
+// textures. These textures typically originate from video decoders.
+#define SB_HAS_NV12_TEXTURE_SUPPORT 1
+
+// --- I/O Configuration -----------------------------------------------------
+
+// Whether the current platform has microphone supported.
+#define SB_HAS_MICROPHONE 0
+
+// Whether the current platform implements the on screen keyboard interface.
+#define SB_HAS_ON_SCREEN_KEYBOARD 0
+
+// Whether the current platform has speech recognizer.
+#define SB_HAS_SPEECH_RECOGNIZER 0
+
+// Whether the current platform has speech synthesis.
+#define SB_HAS_SPEECH_SYNTHESIS 0
+
+// --- Decoder-only Params ---
+
+// --- Memory Configuration --------------------------------------------------
+
+// Whether this platform has and should use an MMAP function to map physical
+// memory to the virtual address space.
+#if SB_API_VERSION < SB_MMAP_REQUIRED_VERSION
+#define SB_HAS_MMAP 1
+#endif
+
+// Whether this platform can map executable memory. Implies SB_HAS_MMAP. This is
+// required for platforms that want to JIT.
+#define SB_CAN_MAP_EXECUTABLE_MEMORY 1
+
+// --- Network Configuration -------------------------------------------------
+
+// Specifies whether this platform supports IPV6.
+#define SB_HAS_IPV6 1
+
+// Specifies whether this platform supports pipe.
+#define SB_HAS_PIPE 1
+
+// --- Thread Configuration --------------------------------------------------
+
+// --- Timing API ------------------------------------------------------------
+
+// Whether this platform has an API to retrieve how long the current thread
+// has spent in the executing state.
+#define SB_HAS_TIME_THREAD_NOW 1
+
+// --- Tuneable Parameters ---------------------------------------------------
+
+// --- User Configuration ----------------------------------------------------
+
+// --- Platform Specific Audits ----------------------------------------------
+
+#if !defined(__GNUC__)
+#error "Evergreen-arm builds need a GCC-like compiler (for the moment)."
+#endif
+
+#endif // STARBOARD_EVERGREEN_ARM_SOFTFP_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/6/gyp_configuration.gypi b/src/starboard/evergreen/arm/softfp/gyp_configuration.gypi
similarity index 73%
copy from src/starboard/linux/x64x11/blittergles/sbversion/6/gyp_configuration.gypi
copy to src/starboard/evergreen/arm/softfp/gyp_configuration.gypi
index 3b6dac2..cd963f7 100644
--- a/src/starboard/linux/x64x11/blittergles/sbversion/6/gyp_configuration.gypi
+++ b/src/starboard/evergreen/arm/softfp/gyp_configuration.gypi
@@ -16,25 +16,27 @@
# though it may have been modified since its creation.
{
+ 'variables': {
+ 'sb_target_platform': 'evergreen-arm-softfp',
+ },
'target_defaults': {
- 'default_configuration': 'linux-x64x11-blittergles-sbversion-6_debug',
+ 'default_configuration': 'evergreen-arm-softfp_debug',
'configurations': {
- 'linux-x64x11-blittergles-sbversion-6_debug': {
+ 'evergreen-arm-softfp_debug': {
'inherit_from': ['debug_base'],
},
- 'linux-x64x11-blittergles-sbversion-6_devel': {
+ 'evergreen-arm-softfp_devel': {
'inherit_from': ['devel_base'],
},
- 'linux-x64x11-blittergles-sbversion-6_qa': {
+ 'evergreen-arm-softfp_qa': {
'inherit_from': ['qa_base'],
},
- 'linux-x64x11-blittergles-sbversion-6_gold': {
+ 'evergreen-arm-softfp_gold': {
'inherit_from': ['gold_base'],
},
}, # end of configurations
},
-
'includes': [
- '<(DEPTH)/starboard/linux/x64x11/blittergles/shared/gyp_configuration.gypi',
+ '<(DEPTH)/starboard/evergreen/arm/shared/gyp_configuration.gypi',
],
}
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/6/starboard_platform_tests.gyp b/src/starboard/evergreen/arm/softfp/gyp_configuration.py
similarity index 68%
copy from src/starboard/linux/x64x11/blittergles/sbversion/6/starboard_platform_tests.gyp
copy to src/starboard/evergreen/arm/softfp/gyp_configuration.py
index 94e7cc2..8c649b9 100644
--- a/src/starboard/linux/x64x11/blittergles/sbversion/6/starboard_platform_tests.gyp
+++ b/src/starboard/evergreen/arm/softfp/gyp_configuration.py
@@ -14,11 +14,12 @@
# This file was initially generated by starboard/tools/create_derived_build.py,
# though it may have been modified since its creation.
+"""Starboard evergreen-arm-softfp platform configuration for gyp_cobalt."""
-{
- 'includes': [
- # Note that we are 'includes'ing a 'gyp' file, not a 'gypi' file. The idea
- # is that we just want this file to *be* the parent gyp file.
- '<(DEPTH)/starboard/linux/x64x11/blittergles/starboard_platform_tests.gyp',
- ],
-}
+from starboard.evergreen.arm.shared import gyp_configuration as parent_configuration
+
+
+def CreatePlatformConfig():
+ return parent_configuration.EvergreenArmConfiguration(
+ 'evergreen-arm-softfp',
+ sabi_json_path='starboard/sabi/arm/softfp/sabi.json')
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/6/starboard_platform.gyp b/src/starboard/evergreen/arm/softfp/starboard_platform.gyp
similarity index 92%
copy from src/starboard/linux/x64x11/blittergles/sbversion/6/starboard_platform.gyp
copy to src/starboard/evergreen/arm/softfp/starboard_platform.gyp
index 8163408..8787f61 100644
--- a/src/starboard/linux/x64x11/blittergles/sbversion/6/starboard_platform.gyp
+++ b/src/starboard/evergreen/arm/softfp/starboard_platform.gyp
@@ -19,6 +19,7 @@
'includes': [
# Note that we are 'includes'ing a 'gyp' file, not a 'gypi' file. The idea
# is that we just want this file to *be* the parent gyp file.
- '<(DEPTH)/starboard/linux/x64x11/blittergles/starboard_platform.gyp',
+ '<(DEPTH)/starboard/evergreen/shared/starboard_platform.gyp',
],
}
+
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/6/atomic_public.h b/src/starboard/evergreen/arm/softfp/thread_types_public.h
similarity index 72%
copy from src/starboard/linux/x64x11/blittergles/sbversion/6/atomic_public.h
copy to src/starboard/evergreen/arm/softfp/thread_types_public.h
index d2414dd..d739119 100644
--- a/src/starboard/linux/x64x11/blittergles/sbversion/6/atomic_public.h
+++ b/src/starboard/evergreen/arm/softfp/thread_types_public.h
@@ -15,9 +15,9 @@
// This file was initially generated by starboard/tools/create_derived_build.py,
// though it may have been modified since its creation.
-#ifndef STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_6_ATOMIC_PUBLIC_H_
-#define STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_6_ATOMIC_PUBLIC_H_
+#ifndef STARBOARD_EVERGREEN_ARM_SOFTFP_THREAD_TYPES_PUBLIC_H_
+#define STARBOARD_EVERGREEN_ARM_SOFTFP_THREAD_TYPES_PUBLIC_H_
-#include "starboard/linux/x64x11/blittergles/atomic_public.h"
+#include "starboard/shared/pthread/types_public.h"
-#endif // STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_6_ATOMIC_PUBLIC_H_
+#endif // STARBOARD_EVERGREEN_ARM_SOFTFP_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/sbversion/6/__init__.py b/src/starboard/evergreen/arm64/__init__.py
similarity index 100%
copy from src/starboard/linux/x64x11/sbversion/6/__init__.py
copy to src/starboard/evergreen/arm64/__init__.py
diff --git a/src/starboard/raspi/2/mozjs/thread_types_public.h b/src/starboard/evergreen/arm64/atomic_public.h
similarity index 65%
rename from src/starboard/raspi/2/mozjs/thread_types_public.h
rename to src/starboard/evergreen/arm64/atomic_public.h
index 96c08d1..1b5fd76 100644
--- a/src/starboard/raspi/2/mozjs/thread_types_public.h
+++ b/src/starboard/evergreen/arm64/atomic_public.h
@@ -1,4 +1,4 @@
-// Copyright 2018 The Cobalt Authors. All Rights Reserved.
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,9 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef STARBOARD_RASPI_2_MOZJS_THREAD_TYPES_PUBLIC_H_
-#define STARBOARD_RASPI_2_MOZJS_THREAD_TYPES_PUBLIC_H_
+#ifndef STARBOARD_EVERGREEN_ARM64_ATOMIC_PUBLIC_H_
+#define STARBOARD_EVERGREEN_ARM64_ATOMIC_PUBLIC_H_
-#include "starboard/raspi/2/thread_types_public.h"
+#include "starboard/atomic.h"
+#include "starboard/shared/gcc/atomic_gcc_public.h"
-#endif // STARBOARD_RASPI_2_MOZJS_THREAD_TYPES_PUBLIC_H_
+#endif // STARBOARD_EVERGREEN_ARM64_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/evergreen/arm64/configuration_public.h b/src/starboard/evergreen/arm64/configuration_public.h
new file mode 100644
index 0000000..9d5aac5
--- /dev/null
+++ b/src/starboard/evergreen/arm64/configuration_public.h
@@ -0,0 +1,219 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// The Starboard configuration for X86_64. Other devices will have
+// specific Starboard implementations.
+
+// Other source files should never include this header directly, but should
+// include the generic "starboard/configuration.h" instead.
+
+#ifndef STARBOARD_EVERGREEN_ARM64_CONFIGURATION_PUBLIC_H_
+#define STARBOARD_EVERGREEN_ARM64_CONFIGURATION_PUBLIC_H_
+
+// Configuration parameters that allow the application to make some general
+// compile-time decisions with respect to the the number of cores likely to be
+// available on this platform. For a definitive measure, the application should
+// still call SbSystemGetNumberOfProcessors at runtime.
+
+// Whether the current platform's thread scheduler will automatically balance
+// threads between cores, as opposed to systems where threads will only ever run
+// on the specifically pinned core.
+#define SB_HAS_CROSS_CORE_SCHEDULER 1
+
+// Indicates that there is no support for alignment at greater than 16 bytes for
+// items on the stack.
+#define SB_HAS_QUIRK_DOES_NOT_STACK_ALIGN_OVER_16_BYTES 1
+
+// This quirk is used to fix an issue caused by the rewriting of memset to
+// SbMemorySet in third_party/protobuf/src/google/protobuf/stubs/port.h.
+#define SB_HAS_QUIRK_MEMSET_IN_SYSTEM_HEADERS 1
+
+// --- System Header Configuration -------------------------------------------
+
+// Any system headers listed here that are not provided by the platform will be
+// emulated in starboard/types.h.
+
+// Whether the current platform provides the standard header stdarg.h.
+#define SB_HAS_STDARG_H 1
+
+// Whether the current platform provides the standard header stdbool.h.
+#define SB_HAS_STDBOOL_H 1
+
+// Whether the current platform provides the standard header stddef.h.
+#define SB_HAS_STDDEF_H 1
+
+// Whether the current platform provides the standard header stdint.h.
+#define SB_HAS_STDINT_H 1
+
+// Whether the current platform provides the standard header inttypes.h.
+#define SB_HAS_INTTYPES_H 1
+
+// Whether the current platform provides the standard header limits.h.
+#define SB_HAS_LIMITS_H 1
+
+// Whether the current platform provides the standard header float.h.
+#define SB_HAS_FLOAT_H 1
+
+// Whether the current platform provides ssize_t.
+#define SB_HAS_SSIZE_T 0
+
+// Type detection for wchar_t.
+#if defined(__WCHAR_MAX__) && \
+ (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff)
+#define SB_IS_WCHAR_T_UTF32 1
+#elif defined(__WCHAR_MAX__) && \
+ (__WCHAR_MAX__ == 0x7fff || __WCHAR_MAX__ == 0xffff)
+#define SB_IS_WCHAR_T_UTF16 1
+#endif
+
+// Chrome only defines these two if ARMEL or MIPSEL are defined.
+#if defined(__ARMEL__)
+// Chrome has an exclusion for iOS here, we should too when we support iOS.
+#define SB_IS_WCHAR_T_UNSIGNED 1
+#elif defined(__MIPSEL__)
+#define SB_IS_WCHAR_T_SIGNED 1
+#endif
+
+// This quirk is used to fix an issue caused by the rewriting of memset to
+// SbMemorySet in third_party/protobuf/src/google/protobuf/stubs/port.h.
+#define SB_HAS_QUIRK_MEMSET_IN_SYSTEM_HEADERS 1
+
+// --- Compiler Configuration ------------------------------------------------
+
+// The platform's annotation for forcing a C function to be inlined.
+#define SB_C_FORCE_INLINE __inline__ __attribute__((always_inline))
+
+// The platform's annotation for marking a C function as suggested to be
+// inlined.
+#define SB_C_INLINE inline
+
+// The platform's annotation for marking a C function as forcibly not
+// inlined.
+#define SB_C_NOINLINE __attribute__((noinline))
+
+// The platform's annotation for marking a symbol as exported outside of the
+// current shared library.
+#define SB_EXPORT_PLATFORM __attribute__((visibility("default")))
+
+// The platform's annotation for marking a symbol as imported from outside of
+// the current linking unit.
+#define SB_IMPORT_PLATFORM
+
+// --- Extensions Configuration ----------------------------------------------
+
+// Do not use <unordered_map> and <unordered_set> for the hash table types.
+#define SB_HAS_STD_UNORDERED_HASH 0
+
+// GCC/Clang doesn't define a long long hash function, except for Android and
+// Game consoles.
+#define SB_HAS_LONG_LONG_HASH 0
+
+// GCC/Clang doesn't define a string hash function, except for Game Consoles.
+#define SB_HAS_STRING_HASH 0
+
+// Desktop Linux needs a using statement for the hash functions.
+#define SB_HAS_HASH_USING 0
+
+// Set this to 1 if hash functions for custom types can be defined as a
+// hash_value() function. Otherwise, they need to be placed inside a
+// partially-specified hash struct template with an operator().
+#define SB_HAS_HASH_VALUE 0
+
+// Set this to 1 if use of hash_map or hash_set causes a deprecation warning
+// (which then breaks the build).
+#define SB_HAS_HASH_WARNING 1
+
+// The location to include hash_map on this platform.
+#define SB_HASH_MAP_INCLUDE <ext/hash_map>
+
+// C++'s hash_map and hash_set are often found in different namespaces depending
+// on the compiler.
+#define SB_HASH_NAMESPACE __gnu_cxx
+
+// The location to include hash_set on this platform.
+#define SB_HASH_SET_INCLUDE <ext/hash_set>
+
+// Define this to how this platform copies varargs blocks.
+#define SB_VA_COPY(dest, source) va_copy(dest, source)
+
+// --- Graphics Configuration ------------------------------------------------
+
+// Specifies whether this platform supports a performant accelerated blitter
+// API. The basic requirement is a scaled, clipped, alpha-blended blit.
+#define SB_HAS_BLITTER 0
+
+// Indicates whether or not the given platform supports bilinear filtering.
+// This can be checked to enable/disable renderer tests that verify that this is
+// working properly.
+#define SB_HAS_BILINEAR_FILTERING_SUPPORT 1
+
+// Indicates whether or not the given platform supports rendering of NV12
+// textures. These textures typically originate from video decoders.
+#define SB_HAS_NV12_TEXTURE_SUPPORT 1
+
+// --- I/O Configuration -----------------------------------------------------
+
+// Whether the current platform has microphone supported.
+#define SB_HAS_MICROPHONE 1
+
+// Whether the current platform implements the on screen keyboard interface.
+#define SB_HAS_ON_SCREEN_KEYBOARD 0
+
+// Whether the current platform has speech recognizer.
+#define SB_HAS_SPEECH_RECOGNIZER 0
+
+// Whether the current platform has speech synthesis.
+#define SB_HAS_SPEECH_SYNTHESIS 0
+
+// --- Decoder-only Params ---
+
+// --- Memory Configuration --------------------------------------------------
+
+// Whether this platform has and should use an MMAP function to map physical
+// memory to the virtual address space.
+#if SB_API_VERSION < SB_MMAP_REQUIRED_VERSION
+#define SB_HAS_MMAP 1
+#endif
+
+// Whether this platform can map executable memory. Implies SB_HAS_MMAP. This is
+// required for platforms that want to JIT.
+#define SB_CAN_MAP_EXECUTABLE_MEMORY 1
+
+// --- Network Configuration -------------------------------------------------
+
+// Specifies whether this platform supports IPV6.
+#define SB_HAS_IPV6 1
+
+// Specifies whether this platform supports pipe.
+#define SB_HAS_PIPE 1
+
+// --- Thread Configuration --------------------------------------------------
+
+// --- Timing API ------------------------------------------------------------
+
+// Whether this platform has an API to retrieve how long the current thread
+// has spent in the executing state.
+#define SB_HAS_TIME_THREAD_NOW 1
+
+// --- Tuneable Parameters ---------------------------------------------------
+
+// --- User Configuration ----------------------------------------------------
+
+// --- Platform Specific Audits ----------------------------------------------
+
+#if !defined(__GNUC__)
+#error "Evergreen-arm64 builds need a GCC-like compiler (for the moment)."
+#endif
+
+#endif // STARBOARD_EVERGREEN_ARM64_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/evergreen/arm64/gyp_configuration.gypi b/src/starboard/evergreen/arm64/gyp_configuration.gypi
new file mode 100644
index 0000000..b2a0525
--- /dev/null
+++ b/src/starboard/evergreen/arm64/gyp_configuration.gypi
@@ -0,0 +1,58 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file was initially generated by starboard/tools/create_derived_build.py,
+# though it may have been modified since its creation.
+
+{
+ 'variables': {
+ 'yasm_exists': 1,
+ 'sb_target_platform': 'evergreen-arm64',
+
+ 'compiler_flags': [
+ '-isystem<(cobalt_repo_root)/third_party/musl/arch/aarch64',
+ ],
+ },
+
+ 'target_defaults': {
+ 'defines' : [
+ # Ensure that the Starboardized __external_threading file is included.
+ '_LIBCPP_HAS_THREAD_API_EXTERNAL',
+ # Ensure that only the forward declarations and type definitions are included
+ # in __external_threading.
+ '_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL',
+ # Enable GNU extensions to get prototypes like ffsl.
+ '_GNU_SOURCE=1',
+ ],
+ 'default_configuration': 'evergreen-arm64_debug',
+ 'configurations': {
+ 'evergreen-arm64_debug': {
+ 'inherit_from': ['debug_base'],
+ },
+ 'evergreen-arm64_devel': {
+ 'inherit_from': ['devel_base'],
+ },
+ 'evergreen-arm64_qa': {
+ 'inherit_from': ['qa_base'],
+ },
+ 'evergreen-arm64_gold': {
+ 'inherit_from': ['gold_base'],
+ },
+ }, # end of configurations
+ },
+ 'includes': [
+ '<(DEPTH)/starboard/evergreen/shared/compiler_flags.gypi',
+ '<(DEPTH)/starboard/evergreen/shared/gyp_configuration.gypi',
+ ],
+}
diff --git a/src/starboard/evergreen/arm64/gyp_configuration.py b/src/starboard/evergreen/arm64/gyp_configuration.py
new file mode 100644
index 0000000..a607170
--- /dev/null
+++ b/src/starboard/evergreen/arm64/gyp_configuration.py
@@ -0,0 +1,91 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Starboard evergreen-arm64 platform configuration for gyp_cobalt."""
+
+from starboard.build import clang as clang_build
+from starboard.evergreen.shared import gyp_configuration as shared_configuration
+from starboard.tools import build
+from starboard.tools.toolchain import ar
+from starboard.tools.toolchain import bash
+from starboard.tools.toolchain import clang
+from starboard.tools.toolchain import clangxx
+from starboard.tools.toolchain import cp
+from starboard.tools.toolchain import evergreen_linker
+from starboard.tools.toolchain import touch
+
+
+class EvergreenArm64Configuration(shared_configuration.EvergreenConfiguration):
+ """Starboard Evergreen 64-bit ARM platform configuration."""
+
+ def __init__(self,
+ platform_name='evergreen-arm64',
+ asan_enabled_by_default=False,
+ goma_supports_compiler=True,
+ sabi_json_path=None):
+ # pylint: disable=useless-super-delegation
+ super(EvergreenArm64Configuration,
+ self).__init__(platform_name, asan_enabled_by_default,
+ goma_supports_compiler, sabi_json_path)
+ self._host_toolchain = None
+
+ def GetTargetToolchain(self):
+ return self.GetHostToolchain()
+
+ def GetHostToolchain(self):
+ if not self._host_toolchain:
+ if not hasattr(self, 'host_compiler_environment'):
+ self.host_compiler_environment = build.GetHostCompilerEnvironment(
+ clang_build.GetClangSpecification(), False)
+ cc_path = self.host_compiler_environment['CC_host']
+ cxx_path = self.host_compiler_environment['CXX_host']
+
+ # Takes the provided value of CXX_HOST with a prepended 'gomacc' and an
+ # appended 'bin/clang++' and strips them off, leaving us with an absolute
+ # path to the root directory of our toolchain.
+ begin_path_index = cxx_path.find('/')
+ end_path_index = cxx_path.rfind('/', 0, cxx_path.rfind('/')) + 1
+
+ cxx_path_root = cxx_path[begin_path_index:end_path_index]
+
+ self._host_toolchain = [
+ clang.CCompiler(path=cc_path),
+ clang.CxxCompiler(path=cxx_path),
+ clang.AssemblerWithCPreprocessor(path=cc_path),
+ ar.StaticThinLinker(),
+ ar.StaticLinker(),
+ clangxx.ExecutableLinker(path=cxx_path),
+ evergreen_linker.SharedLibraryLinker(
+ path=cxx_path_root, extra_flags=['-m aarch64elf']),
+ cp.Copy(),
+ touch.Stamp(),
+ bash.Shell(),
+ ]
+ return self._host_toolchain
+
+ def GetTestFilters(self):
+ # pylint: disable=useless-super-delegation
+ return super(EvergreenArm64Configuration, self).GetTestFilters()
+
+ def GetVariables(self, configuration):
+ variables = super(EvergreenArm64Configuration, self).GetVariables(configuration)
+ variables.update({
+ 'include_path_platform_deploy_gypi':
+ 'starboard/evergreen/arm64/platform_deploy.gypi',
+ })
+ return variables
+
+
+def CreatePlatformConfig():
+ return EvergreenArm64Configuration(
+ sabi_json_path='starboard/sabi/arm64/sabi.json')
diff --git a/src/starboard/evergreen/arm64/platform_deploy.gypi b/src/starboard/evergreen/arm64/platform_deploy.gypi
new file mode 100644
index 0000000..f32c77f
--- /dev/null
+++ b/src/starboard/evergreen/arm64/platform_deploy.gypi
@@ -0,0 +1,37 @@
+# Copyright 2020 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+{
+ 'variables': {
+ 'deploy_executable_file': '<(target_deploy_dir)/lib/lib<(executable_name).so',
+ 'executable_file': '<(PRODUCT_DIR)/lib/lib<(executable_name).so',
+ },
+ 'includes': [ '<(DEPTH)/starboard/build/collect_deploy_content.gypi' ],
+ 'actions': [
+ {
+ 'action_name': 'deploy_executable',
+ 'message': 'Strip executable: <(deploy_executable_file)',
+ 'inputs': [
+ '<(executable_file)',
+ '<(content_deploy_stamp_file)',
+ ],
+ 'outputs': [ '<(deploy_executable_file)' ],
+ 'action': [
+ 'aarch64-linux-gnu-strip',
+ '-o', '<(deploy_executable_file)',
+ '<(executable_file)',
+ ],
+ },
+ ],
+}
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/6/starboard_platform.gyp b/src/starboard/evergreen/arm64/starboard_platform.gyp
similarity index 78%
copy from src/starboard/linux/x64x11/blittergles/sbversion/6/starboard_platform.gyp
copy to src/starboard/evergreen/arm64/starboard_platform.gyp
index 8163408..8fa33ef 100644
--- a/src/starboard/linux/x64x11/blittergles/sbversion/6/starboard_platform.gyp
+++ b/src/starboard/evergreen/arm64/starboard_platform.gyp
@@ -12,13 +12,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# This file was initially generated by starboard/tools/create_derived_build.py,
-# though it may have been modified since its creation.
-
{
'includes': [
# Note that we are 'includes'ing a 'gyp' file, not a 'gypi' file. The idea
# is that we just want this file to *be* the parent gyp file.
- '<(DEPTH)/starboard/linux/x64x11/blittergles/starboard_platform.gyp',
+ '<(DEPTH)/starboard/evergreen/shared/starboard_platform.gyp',
],
}
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/6/atomic_public.h b/src/starboard/evergreen/arm64/thread_types_public.h
similarity index 72%
copy from src/starboard/linux/x64x11/blittergles/sbversion/6/atomic_public.h
copy to src/starboard/evergreen/arm64/thread_types_public.h
index d2414dd..c156579 100644
--- a/src/starboard/linux/x64x11/blittergles/sbversion/6/atomic_public.h
+++ b/src/starboard/evergreen/arm64/thread_types_public.h
@@ -15,9 +15,9 @@
// This file was initially generated by starboard/tools/create_derived_build.py,
// though it may have been modified since its creation.
-#ifndef STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_6_ATOMIC_PUBLIC_H_
-#define STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_6_ATOMIC_PUBLIC_H_
+#ifndef STARBOARD_EVERGREEN_ARM64_THREAD_TYPES_PUBLIC_H_
+#define STARBOARD_EVERGREEN_ARM64_THREAD_TYPES_PUBLIC_H_
-#include "starboard/linux/x64x11/blittergles/atomic_public.h"
+#include "starboard/shared/pthread/types_public.h"
-#endif // STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_6_ATOMIC_PUBLIC_H_
+#endif // STARBOARD_EVERGREEN_ARM64_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/evergreen/sabi/sabi_flags.gypi b/src/starboard/evergreen/sabi/sabi_flags.gypi
new file mode 100644
index 0000000..160ef7f
--- /dev/null
+++ b/src/starboard/evergreen/sabi/sabi_flags.gypi
@@ -0,0 +1,80 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Starboard Application Binary Interface
+#
+# This file translates the set of ABI variables, which should be overridden by
+# each platform, into platform-specific sets of compiler flags.
+
+{
+ 'variables': {
+ 'conditions': [
+ # arm
+ ['target_arch=="arm"', {
+ 'compiler_flags': [
+ '-march=arm<(target_arch_sub)',
+ ],
+ 'conditions': [
+ ['floating_point_abi=="soft"', {
+ 'compiler_flags': [
+ '-mfloat-abi=soft',
+ ],
+ }, {
+ 'compiler_flags': [
+ '-mfloat-abi=<(floating_point_abi)',
+ '-mfpu=<(floating_point_fpu)',
+ ],
+ }],
+ ['floating_point_abi=="hard"', {
+ 'compiler_flags': [
+ '-target', 'arm<(target_arch_sub)-none-eabihf',
+ ],
+ }, {
+ 'compiler_flags': [
+ '-target', 'arm<(target_arch_sub)-none-eabi',
+ ],
+ }],
+ ],
+ }],
+ # arm64
+ ['target_arch=="arm64"', {
+ 'compiler_flags': [
+ '-march=arm64<(target_arch_sub)',
+ '-target', 'arm64<(target_arch_sub)-unknown-unknown-elf',
+
+ # There is no software floating point support for arm64 / aarch64
+ # architectures. Thus, -mfloat-abi and -mfpu would simply be ignored.
+
+ # char is unsigned by default for arm64.
+ '-fsigned-char',
+ ],
+ }],
+ # x86
+ ['target_arch=="x86"', {
+ 'compiler_flags': [
+ '-march=i686',
+ '-target', 'i686-unknown-unknown-elf',
+ ],
+ }],
+ # x64
+ ['target_arch=="x64"', {
+ 'compiler_flags': [
+ '-march=x86-64',
+ '-target', 'x86_64-unknown-linux-elf',
+ ],
+ }],
+ ],
+ },
+}
+
diff --git a/src/starboard/linux/x64x11/sbversion/6/__init__.py b/src/starboard/evergreen/shared/__init__.py
similarity index 100%
copy from src/starboard/linux/x64x11/sbversion/6/__init__.py
copy to src/starboard/evergreen/shared/__init__.py
diff --git a/src/starboard/evergreen/shared/compiler_flags.gypi b/src/starboard/evergreen/shared/compiler_flags.gypi
new file mode 100644
index 0000000..91af007
--- /dev/null
+++ b/src/starboard/evergreen/shared/compiler_flags.gypi
@@ -0,0 +1,192 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Platform specific compiler flags for Evergreen. Included from
+# gyp_configuration.gypi.
+
+{
+ 'variables': {
+ 'compiler_flags_host': [
+ '-O2',
+ ],
+ 'compiler_flags_debug': [
+ '-frtti',
+ '-O0',
+ ],
+ 'compiler_flags_devel': [
+ '-frtti',
+ '-O2',
+ ],
+ 'compiler_flags_qa': [
+ '-fno-rtti',
+ '-gline-tables-only',
+ ],
+ 'compiler_flags_qa_size': [
+ '-Os',
+ ],
+ 'compiler_flags_qa_speed': [
+ '-O2',
+ ],
+ 'compiler_flags_gold': [
+ '-fno-rtti',
+ '-gline-tables-only',
+ ],
+ 'compiler_flags_gold_size': [
+ '-Os',
+ ],
+ 'compiler_flags_gold_speed': [
+ '-O2',
+ ],
+ 'conditions': [
+ ['clang==1', {
+ 'linker_flags': [
+ '-fuse-ld=lld',
+ '-nostdlib',
+ ],
+ 'common_clang_flags': [
+ '-fcolor-diagnostics',
+ # Default visibility to hidden, to enable dead stripping.
+ '-fvisibility=hidden',
+ '-Wno-c++11-compat',
+ # This complains about 'override', which we use heavily.
+ '-Wno-c++11-extensions',
+ # Warns on switches on enums that cover all enum values but
+ # also contain a default: branch. Chrome is full of that.
+ '-Wno-covered-switch-default',
+ # protobuf uses hash_map.
+ '-Wno-deprecated',
+ '-fno-exceptions',
+ # Enable unwind tables used by libunwind for stack traces.
+ '-funwind-tables',
+ # Disable usage of frame pointers.
+ '-fomit-frame-pointer',
+ # Don't warn about the "struct foo f = {0};" initialization pattern.
+ '-Wno-missing-field-initializers',
+ # Do not warn for implicit sign conversions.
+ '-Wno-sign-conversion',
+ '-fno-strict-aliasing', # See http://crbug.com/32204
+ '-Wno-unnamed-type-template-args',
+ # Triggered by the COMPILE_ASSERT macro.
+ '-Wno-unused-local-typedef',
+ # Do not warn if a function or variable cannot be implicitly
+ # instantiated.
+ '-Wno-undefined-var-template',
+ # Do not warn about an implicit exception spec mismatch.
+ '-Wno-implicit-exception-spec-mismatch',
+ # It's OK not to use some input parameters.
+ '-Wno-unused-parameter',
+ '-Wno-conversion',
+ '-Wno-bitwise-op-parentheses',
+ '-Wno-shift-op-parentheses',
+ '-Wno-shorten-64-to-32',
+ '-fno-use-cxa-atexit',
+ ],
+ }],
+ ['cobalt_fastbuild==0', {
+ 'compiler_flags_debug': [
+ '-g',
+ ],
+ 'compiler_flags_devel': [
+ '-g',
+ ],
+ 'compiler_flags_qa': [
+ '-gline-tables-only',
+ ],
+ 'compiler_flags_gold': [
+ '-gline-tables-only',
+ ],
+ }],
+ ],
+ },
+
+ 'target_defaults': {
+ 'defines': [
+ # By default, <EGL/eglplatform.h> pulls in some X11 headers that have some
+ # nasty macros (|Status|, for example) that conflict with Chromium base.
+ 'MESA_EGL_NO_X11_HEADERS'
+ ],
+ 'cflags': [
+ '-fPIC',
+ '-nostdlibinc',
+ '-isystem<(cobalt_repo_root)/third_party/llvm-project/libcxxabi/include',
+ '-isystem<(cobalt_repo_root)/third_party/llvm-project/libunwind/include',
+ '-isystem<(cobalt_repo_root)/third_party/llvm-project/libcxx/include',
+ '-isystem<(cobalt_repo_root)/third_party/musl/include',
+ '-isystem<(cobalt_repo_root)/third_party/musl/arch/generic',
+ ],
+ 'cflags_cc': [
+ '-nostdinc++',
+ '-std=c++11',
+ ],
+ 'target_conditions': [
+ ['sb_pedantic_warnings==1', {
+ 'cflags': [
+ '-Wall',
+ '-Wextra',
+ '-Wunreachable-code',
+ '<@(common_clang_flags)',
+ ],
+ },{
+ 'cflags': [
+ '<@(common_clang_flags)',
+ # 'this' pointer cannot be NULL...pointer may be assumed
+ # to always convert to true.
+ '-Wno-undefined-bool-conversion',
+ # Skia doesn't use overrides.
+ '-Wno-inconsistent-missing-override',
+ # Do not warn for implicit type conversions that may change a value.
+ '-Wno-conversion',
+ # shifting a negative signed value is undefined
+ '-Wno-shift-negative-value',
+ # Width of bit-field exceeds width of its type- value will be truncated
+ '-Wno-bitfield-width',
+ '-Wno-undefined-var-template',
+ ],
+ }],
+ ['use_asan==1', {
+ 'cflags': [
+ '-fsanitize=address',
+ '-fno-omit-frame-pointer',
+ ],
+ 'ldflags': [
+ '-fsanitize=address',
+ # Force linking of the helpers in sanitizer_options.cc
+ '-Wl,-u_sanitizer_options_link_helper',
+ ],
+ 'defines': [
+ 'ADDRESS_SANITIZER',
+ ],
+ 'conditions': [
+ ['asan_symbolizer_path!=""', {
+ 'defines': [
+ 'ASAN_SYMBOLIZER_PATH="<@(asan_symbolizer_path)"',
+ ],
+ }],
+ ],
+ }],
+ ['use_tsan==1', {
+ 'cflags': [
+ '-fsanitize=thread',
+ '-fno-omit-frame-pointer',
+ ],
+ 'ldflags': [
+ '-fsanitize=thread',
+ ],
+ 'defines': [
+ 'THREAD_SANITIZER',
+ ],
+ }],
+ ],
+ }, # end of target_defaults
+}
diff --git a/src/starboard/evergreen/shared/gyp_configuration.gypi b/src/starboard/evergreen/shared/gyp_configuration.gypi
new file mode 100644
index 0000000..e6a8911
--- /dev/null
+++ b/src/starboard/evergreen/shared/gyp_configuration.gypi
@@ -0,0 +1,70 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file was initially generated by starboard/tools/create_derived_build.py,
+# though it may have been modified since its creation.
+
+{
+ 'variables': {
+ 'sb_evergreen': 1,
+ 'sb_speech_supported': 0,
+
+ 'enable_vr': 0,
+ 'default_renderer_options_dependency': '<(DEPTH)/cobalt/renderer/default_options_starboard.gyp:default_options',
+ 'javascript_engine': 'v8',
+ 'cobalt_v8_buildtime_snapshot': 1,
+ 'cobalt_v8_enable_embedded_builtins': 1,
+
+ # Override that omits the "data" subdirectory.
+ # TODO: Remove when omitted for all platforms in base_configuration.gypi.
+ 'sb_static_contents_output_data_dir': '<(PRODUCT_DIR)/content',
+
+ 'final_executable_type': 'shared_library',
+ 'gtest_target_type': 'shared_library',
+
+ 'compiler_flags': [
+ # We'll pretend not to be Linux, but Starboard instead.
+ '-U__linux__',
+
+ # Pretend not to be unix, so that _LIBCPP_HAS_CATOPEN is not defined in
+ # third_party/llvm-project/libcxx/include/__config. Then leaks catopen,
+ # catgets and catclose are plugged.
+ '-U__unix__',
+ ],
+
+ # Using an inner scope for 'variables' so that it can be made a default
+ # (and so overridden elsewhere), but yet still used immediately in this
+ # file.
+ 'variables': {
+ 'use_dlmalloc_allocator%': 0,
+ },
+ },
+ 'target_defaults': {
+ 'defines' : [
+ '_LIBCPP_HAS_MUSL_LIBC',
+ '__STDC_FORMAT_MACROS', # so that we get PRI*
+
+ # File format of the shared object we will generate.
+ '__ELF__',
+
+ # Use scalar portable implementations instead of Clang/GCC vector
+ # extensions in SkVx.h.
+ 'SKNX_NO_SIMD',
+ ],
+ },
+ 'includes': [
+ '<(DEPTH)/starboard/evergreen/sabi/sabi_flags.gypi',
+ '<(DEPTH)/starboard/sabi/sabi.gypi',
+ ],
+}
diff --git a/src/starboard/evergreen/shared/gyp_configuration.py b/src/starboard/evergreen/shared/gyp_configuration.py
new file mode 100644
index 0000000..3d9860f
--- /dev/null
+++ b/src/starboard/evergreen/shared/gyp_configuration.py
@@ -0,0 +1,117 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Starboard Evergreen shared platform configuration."""
+
+import os
+
+from starboard.build import clang
+from starboard.build import platform_configuration
+from starboard.tools import build
+from starboard.tools import paths
+from starboard.tools.testing import test_filter
+
+
+class EvergreenConfiguration(platform_configuration.PlatformConfiguration):
+ """Starboard Evergreen platform configuration."""
+
+ def __init__(self,
+ platform,
+ asan_enabled_by_default=True,
+ goma_supports_compiler=True,
+ sabi_json_path=None):
+ self.goma_supports_compiler = goma_supports_compiler
+ self.sabi_json_path = sabi_json_path
+ super(EvergreenConfiguration, self).__init__(platform,
+ asan_enabled_by_default)
+
+ def GetBuildFormat(self):
+ """Returns the desired build format."""
+ # The comma means that ninja and qtcreator_ninja will be chained and use the
+ # same input information so that .gyp files will only have to be parsed
+ # once.
+ return 'ninja,qtcreator_ninja'
+
+ def GetVariables(self, config_name):
+ variables = super(EvergreenConfiguration, self).GetVariables(
+ config_name, use_clang=1)
+ variables.update({
+ 'javascript_engine':
+ 'v8',
+ 'cobalt_enable_jit':
+ 1,
+ 'cobalt_repo_root':
+ paths.REPOSITORY_ROOT,
+ 'include_path_platform_deploy_gypi':
+ 'starboard/evergreen/shared/platform_deploy.gypi',
+ })
+ return variables
+
+ def GetLauncherPath(self):
+ """Gets the path to the launcher module for this platform."""
+ return os.path.dirname(__file__)
+
+ def GetGeneratorVariables(self, config_name):
+ del config_name
+ generator_variables = {
+ 'qtcreator_session_name_prefix': 'cobalt',
+ }
+ return generator_variables
+
+ def GetEnvironmentVariables(self):
+ if not hasattr(self, 'host_compiler_environment'):
+ self.host_compiler_environment = build.GetHostCompilerEnvironment(
+ clang.GetClangSpecification(), self.goma_supports_compiler)
+
+ env_variables = self.host_compiler_environment
+ env_variables.update({
+ 'CC': self.host_compiler_environment['CC_host'],
+ 'CXX': self.host_compiler_environment['CXX_host'],
+ })
+ return env_variables
+
+ def GetPathToSabiJsonFile(self):
+ return self.sabi_json_path
+
+ def GetTestFilters(self):
+ filters = super(EvergreenConfiguration, self).GetTestFilters()
+ for target, tests in self.__FILTERED_TESTS.iteritems():
+ filters.extend(test_filter.TestFilter(target, test) for test in tests)
+ return filters
+
+ __FILTERED_TESTS = { # pylint: disable=invalid-name
+ 'nplb': ['MemoryReportingTest.CapturesMemMapUnmap',
+ 'MemoryReportingTest.CapturesOperatorDeleteNothrow',
+ 'SbAudioSinkTest.*',
+ 'SbDrmTest.AnySupportedKeySystems'],
+
+ # player_filter_tests test the platform's Starboard implementation of
+ # the filter-based player, which is not exposed through the Starboard
+ # interface. Since Evergreen has no visibility of the platform's
+ # specific Starboard implementation, rely on the platform to test this
+ # directly instead.
+ 'player_filter_tests': [test_filter.FILTER_ALL],
+ }
+
+ def GetTestTargets(self):
+ tests = super(EvergreenConfiguration, self).GetTestTargets()
+ return [test for test in tests if test not in self.__BLACKLISTED_TESTS]
+
+ __BLACKLISTED_TESTS = [ # pylint: disable=invalid-name
+ # elf_loader_test and installation_manager_test are explicitly tests that
+ # validate the correctness of the underlying platform. We should not be
+ # running these tests in Evergreen mode, and instead will rely on the
+ # platform to test this directly instead.
+ 'elf_loader_test',
+ 'installation_manager_test',
+ ]
diff --git a/src/starboard/evergreen/shared/launcher.py b/src/starboard/evergreen/shared/launcher.py
new file mode 100644
index 0000000..5f18643
--- /dev/null
+++ b/src/starboard/evergreen/shared/launcher.py
@@ -0,0 +1,192 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Evergreen implementation of Starboard launcher abstraction."""
+
+import logging
+import os
+import shutil
+
+import _env # pylint: disable=unused-import
+from starboard.tools import abstract_launcher
+from starboard.tools import paths
+from starboard.tools import port_symlink
+
+_BASE_STAGING_DIRECTORY = 'evergreen_staging'
+_LOADER_TARGET = 'elf_loader_sandbox'
+
+
+class Launcher(abstract_launcher.AbstractLauncher):
+ """Class for launching Evergreen targets on arbitrary platforms.
+
+ This Evergreen launcher leverages the platform-specific launchers to start the
+ Evergreen loader on a particular device. A staging directory is built that
+ resembles a typical deploy directory, with the Evergreen target and its
+ content included in the Evergreen loader's content. The platform-specific
+ launcher, given command-line switches to tell the Evergreen loader where the
+ Evergreen target and its content are, can run the loader without needing to
+ know about Evergreen per-se.
+
+ The Evergreen launcher does not require its own implementation for many
+ abstract launcher methods and trampolines them to the platform-specific
+ launcher.
+ """
+
+ def __init__(self, platform, target_name, config, device_id, **kwargs):
+ super(Launcher, self).__init__(platform, target_name, config, device_id,
+ **kwargs)
+ self.loader_platform = kwargs.get('loader_platform')
+ if not self.loader_platform:
+ raise ValueError('|loader_platform| cannot be |None|.')
+
+ self.loader_config = kwargs.get('loader_config')
+ if not self.loader_config:
+ raise ValueError('|loader_config| cannot be |None|.')
+
+ self.loader_out_directory = kwargs.get('loader_out_directory')
+ if not self.loader_out_directory:
+ self.loader_out_directory = paths.BuildOutputDirectory(
+ self.loader_platform, self.loader_config)
+
+ # The relationship of loader platforms and configurations to evergreen
+ # platforms and configurations is many-to-many. We need a separate directory
+ # for each of them, i.e. linux-x64x11_debug__evergreen-x64_gold.
+ self.combined_config = '{}_{}__{}_{}'.format(self.loader_platform,
+ self.loader_config, platform,
+ config)
+
+ self.staging_directory = os.path.join(
+ os.path.dirname(self.out_directory), _BASE_STAGING_DIRECTORY,
+ self.combined_config)
+
+ # TODO: Figure out a place for the launcher to do this prep work that is not
+ # part of the constructor.
+ self._StageTargetsAndContents()
+
+ # Ensure the path, relative to the content of the ELF Loader, to the
+ # Evergreen target and its content are passed as command line switches.
+ target_command_line_params = [
+ '--evergreen_library=app/{}/lib/lib{}.so'.format(
+ self.target_name, self.target_name),
+ '--evergreen_content=app/{}/content'.format(self.target_name)
+ ]
+
+ if self.target_command_line_params:
+ target_command_line_params.extend(self.target_command_line_params)
+
+ self.launcher = abstract_launcher.LauncherFactory(
+ self.loader_platform,
+ _LOADER_TARGET,
+ self.loader_config,
+ device_id,
+ target_params=target_command_line_params,
+ output_file=self.output_file,
+ out_directory=self.staging_directory,
+ coverage_directory=self.coverage_directory,
+ env_variables=self.env_variables)
+
+ def Run(self):
+ """Redirects to the ELF Loader platform's abstract loader implementation."""
+
+ return_code = 1
+
+ try:
+ return_code = self.launcher.Run()
+ except Exception: # pylint: disable=broad-except
+ logging.exception('Error occurred while running test.')
+
+ return return_code
+
+ def Kill(self):
+ """Redirects to the ELF Loader platform's abstract loader implementation."""
+ self.launcher.Kill()
+
+ def _StageTargetsAndContents(self):
+ """Stage targets and their contents in our staging directory.
+
+ The existing launcher infrastructure expects a specific directory structure
+ regardless of whether or not we are running locally:
+
+ platform: raspi-2 raspi-2_devel
+ config: devel +-- deploy
+ target_name: nplb +-- nplb
+ +-- content
+ +-- nplb
+
+ This function effectively builds a directory structure that matches both of
+ these expectations while minimizing the hard copies made.
+
+ Note: The Linux launcher does not yet look in the deploy directory and
+ instead runs the target from the top of its out-directory. This will
+ be changed in the future.
+ """
+
+ if os.path.exists(self.staging_directory):
+ shutil.rmtree(self.staging_directory)
+ os.makedirs(self.staging_directory)
+
+ # out/evergreen_staging/linux-x64x11_devel__evergreen-x64_devel/deploy/elf_loader_sandbox
+ staging_directory_loader = os.path.join(self.staging_directory, 'deploy',
+ _LOADER_TARGET)
+
+ # out/evergreen_staging/linux-x64x11_devel__evergreen-x64_devel/deploy/elf_loader_sandbox/content/app/nplb/
+ staging_directory_evergreen = os.path.join(staging_directory_loader,
+ 'content', 'app',
+ self.target_name)
+
+ # Make a hard copy of the ELF Loader's deploy directory in the location
+ # specified by |staging_directory_loader|. A symbolic link here would cause
+ # future symbolic links to fall through to the original out-directories.
+ shutil.copytree(
+ os.path.join(self.loader_out_directory, 'deploy', _LOADER_TARGET),
+ staging_directory_loader)
+
+ port_symlink.MakeSymLink(
+ os.path.join(self.out_directory, 'deploy', self.target_name),
+ staging_directory_evergreen)
+
+ # TODO: Make the Linux launcher run from the deploy directory, no longer
+ # create these symlinks, and remove the NOTE from the docstring.
+ port_symlink.MakeSymLink(
+ os.path.join(staging_directory_loader, _LOADER_TARGET),
+ os.path.join(self.staging_directory, _LOADER_TARGET))
+ port_symlink.MakeSymLink(
+ os.path.join(staging_directory_loader, 'content'),
+ os.path.join(self.staging_directory, 'content'))
+
+ def SupportsSuspendResume(self):
+ return self.launcher.SupportsSuspendResume()
+
+ def SendResume(self):
+ return self.launcher.SendResume()
+
+ def SendSuspend(self):
+ return self.launcher.SendSuspend()
+
+ def SupportsDeepLink(self):
+ return self.launcher.SupportsDeepLink()
+
+ def SendDeepLink(self, link):
+ return self.launcher.SendDeepLink(link)
+
+ def GetStartupTimeout(self):
+ return self.launcher.GetStartupTimeout()
+
+ def GetHostAndPortGivenPort(self, port):
+ return self.launcher.GetHostAndPortGivenPort(port)
+
+ def GetTargetPath(self):
+ return self.launcher.GetTargetPath()
+
+ def GetDeviceIp(self):
+ return self.launcher.GetDeviceIp()
diff --git a/src/starboard/evergreen/shared/platform_deploy.gypi b/src/starboard/evergreen/shared/platform_deploy.gypi
new file mode 100644
index 0000000..3ad944a
--- /dev/null
+++ b/src/starboard/evergreen/shared/platform_deploy.gypi
@@ -0,0 +1,44 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+{
+ 'variables': {
+ 'deploy_executable_file': '<(target_deploy_dir)/lib/lib<(executable_name).so',
+ 'executable_file': '<(PRODUCT_DIR)/lib/lib<(executable_name).so',
+ },
+ 'includes': [
+ '<(DEPTH)/starboard/build/collect_deploy_content.gypi',
+ ],
+ 'actions': [
+ {
+ 'action_name': 'deploy_executable',
+ 'message': 'Deploy <(deploy_executable_file)',
+ 'inputs': [
+ '<(content_deploy_stamp_file)',
+ '<(executable_file)',
+ ],
+ 'outputs': [ '<(deploy_executable_file)' ],
+ 'action': [
+ 'python',
+ '<(DEPTH)/starboard/tools/port_symlink.py',
+ '-f',
+ '-r',
+ '--link',
+ '<(executable_file)',
+ '<(deploy_executable_file)',
+ ],
+ },
+ ],
+}
+
diff --git a/src/starboard/evergreen/shared/starboard_platform.gyp b/src/starboard/evergreen/shared/starboard_platform.gyp
new file mode 100644
index 0000000..768b46b
--- /dev/null
+++ b/src/starboard/evergreen/shared/starboard_platform.gyp
@@ -0,0 +1,44 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+{
+ 'includes': [
+ '<(DEPTH)/starboard/stub/stub_sources.gypi',
+ '<(DEPTH)/starboard/evergreen/shared/starboard_platform.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'starboard_platform',
+ 'type': 'static_library',
+ 'sources': [
+ '<@(stub_sources)',
+ 'atomic_public.h',
+ 'configuration_public.h',
+ 'thread_types_public.h',
+ ],
+ 'conditions': [
+ ['sb_speech_supported == 0', {
+ 'sources!': [
+ '<@(speech_stub_sources)',
+ ],
+ }],
+ ],
+ 'defines': [
+ # This must be defined when building Starboard, and must not when
+ # building Starboard client code.
+ 'STARBOARD_IMPLEMENTATION',
+ ],
+ },
+ ],
+}
diff --git a/src/starboard/evergreen/shared/starboard_platform.gypi b/src/starboard/evergreen/shared/starboard_platform.gypi
new file mode 100644
index 0000000..1a205c7
--- /dev/null
+++ b/src/starboard/evergreen/shared/starboard_platform.gypi
@@ -0,0 +1,28 @@
+# Copyright 2016 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+{
+ 'variables': {
+ 'speech_stub_sources': [
+ '<(DEPTH)/starboard/shared/stub/speech_recognizer_cancel.cc',
+ '<(DEPTH)/starboard/shared/stub/speech_recognizer_create.cc',
+ '<(DEPTH)/starboard/shared/stub/speech_recognizer_destroy.cc',
+ '<(DEPTH)/starboard/shared/stub/speech_recognizer_is_supported.cc',
+ '<(DEPTH)/starboard/shared/stub/speech_recognizer_start.cc',
+ '<(DEPTH)/starboard/shared/stub/speech_recognizer_stop.cc',
+ '<(DEPTH)/starboard/shared/stub/speech_synthesis_cancel.cc',
+ '<(DEPTH)/starboard/shared/stub/speech_synthesis_is_supported.cc',
+ '<(DEPTH)/starboard/shared/stub/speech_synthesis_speak.cc',
+ ],
+ },
+}
diff --git a/src/starboard/linux/x64x11/sbversion/6/__init__.py b/src/starboard/evergreen/x64/__init__.py
similarity index 100%
copy from src/starboard/linux/x64x11/sbversion/6/__init__.py
copy to src/starboard/evergreen/x64/__init__.py
diff --git a/src/starboard/raspi/2/mozjs/thread_types_public.h b/src/starboard/evergreen/x64/atomic_public.h
similarity index 65%
copy from src/starboard/raspi/2/mozjs/thread_types_public.h
copy to src/starboard/evergreen/x64/atomic_public.h
index 96c08d1..c3fc6c7 100644
--- a/src/starboard/raspi/2/mozjs/thread_types_public.h
+++ b/src/starboard/evergreen/x64/atomic_public.h
@@ -1,4 +1,4 @@
-// Copyright 2018 The Cobalt Authors. All Rights Reserved.
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,9 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef STARBOARD_RASPI_2_MOZJS_THREAD_TYPES_PUBLIC_H_
-#define STARBOARD_RASPI_2_MOZJS_THREAD_TYPES_PUBLIC_H_
+#ifndef STARBOARD_EVERGREEN_X64_ATOMIC_PUBLIC_H_
+#define STARBOARD_EVERGREEN_X64_ATOMIC_PUBLIC_H_
-#include "starboard/raspi/2/thread_types_public.h"
+#include "starboard/atomic.h"
+#include "starboard/shared/gcc/atomic_gcc_public.h"
-#endif // STARBOARD_RASPI_2_MOZJS_THREAD_TYPES_PUBLIC_H_
+#endif // STARBOARD_EVERGREEN_X64_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/sbversion/6/__init__.py b/src/starboard/evergreen/x64/cobalt/__init__.py
similarity index 100%
copy from src/starboard/linux/x64x11/sbversion/6/__init__.py
copy to src/starboard/evergreen/x64/cobalt/__init__.py
diff --git a/src/starboard/linux/x64x11/mozjs/starboard_platform_tests.gyp b/src/starboard/evergreen/x64/cobalt/configuration.gypi
similarity index 75%
copy from src/starboard/linux/x64x11/mozjs/starboard_platform_tests.gyp
copy to src/starboard/evergreen/x64/cobalt/configuration.gypi
index 0ea8622..5fcbf9f 100644
--- a/src/starboard/linux/x64x11/mozjs/starboard_platform_tests.gyp
+++ b/src/starboard/evergreen/x64/cobalt/configuration.gypi
@@ -1,4 +1,4 @@
-# Copyright 2018 The Cobalt Authors. All Rights Reserved.
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -11,8 +11,11 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+
+# Cobalt Evergreen x86_64 specific configuration.
+
{
- 'includes': [
- '<(DEPTH)/starboard/linux/shared/starboard_platform_tests.gypi',
- ],
+ 'variables': {
+ 'in_app_dial%': 1,
+ }, # end of variables
}
diff --git a/src/starboard/evergreen/x64/cobalt/configuration.py b/src/starboard/evergreen/x64/cobalt/configuration.py
new file mode 100644
index 0000000..9d0947d
--- /dev/null
+++ b/src/starboard/evergreen/x64/cobalt/configuration.py
@@ -0,0 +1,70 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Starboard Cobalt Evergreen x64 configuration."""
+
+import os
+
+from cobalt.build import cobalt_configuration
+from starboard.tools.testing import test_filter
+
+
+class CobaltX64Configuration(cobalt_configuration.CobaltConfiguration):
+ """Starboard Cobalt Evergreen x64 configuration."""
+
+ def __init__(self, platform_configuration, application_name,
+ application_directory):
+ super(CobaltX64Configuration,
+ self).__init__(platform_configuration, application_name,
+ application_directory)
+
+ def GetPostIncludes(self):
+ # If there isn't a configuration.gypi found in the usual place, we'll
+ # supplement with our shared implementation.
+ includes = super(CobaltX64Configuration, self).GetPostIncludes()
+ for include in includes:
+ if os.path.basename(include) == 'configuration.gypi':
+ return includes
+
+ shared_gypi_path = os.path.join(
+ os.path.dirname(__file__), 'configuration.gypi')
+ if os.path.isfile(shared_gypi_path):
+ includes.append(shared_gypi_path)
+ return includes
+
+ def WebdriverBenchmarksEnabled(self):
+ return True
+
+ def GetTestFilters(self):
+ filters = super(CobaltX64Configuration, self).GetTestFilters()
+ for target, tests in self.__FILTERED_TESTS.iteritems():
+ filters.extend(test_filter.TestFilter(target, test) for test in tests)
+ return filters
+
+ def GetTestEnvVariables(self):
+ return {
+ 'base_unittests': {
+ 'ASAN_OPTIONS': 'detect_leaks=0'
+ },
+ 'crypto_unittests': {
+ 'ASAN_OPTIONS': 'detect_leaks=0'
+ },
+ 'net_unittests': {
+ 'ASAN_OPTIONS': 'detect_leaks=0'
+ }
+ }
+
+ __FILTERED_TESTS = {
+ 'base_unittests': [test_filter.FILTER_ALL],
+ 'net_unittests': [test_filter.FILTER_ALL],
+ }
diff --git a/src/starboard/evergreen/x64/configuration_public.h b/src/starboard/evergreen/x64/configuration_public.h
new file mode 100644
index 0000000..fe9c06d
--- /dev/null
+++ b/src/starboard/evergreen/x64/configuration_public.h
@@ -0,0 +1,210 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// The Starboard configuration for x64. Other devices will have
+// specific Starboard implementations.
+
+// Other source files should never include this header directly, but should
+// include the generic "starboard/configuration.h" instead.
+
+#ifndef STARBOARD_EVERGREEN_X64_CONFIGURATION_PUBLIC_H_
+#define STARBOARD_EVERGREEN_X64_CONFIGURATION_PUBLIC_H_
+
+// Configuration parameters that allow the application to make some general
+// compile-time decisions with respect to the the number of cores likely to be
+// available on this platform. For a definitive measure, the application should
+// still call SbSystemGetNumberOfProcessors at runtime.
+
+// Whether the current platform's thread scheduler will automatically balance
+// threads between cores, as opposed to systems where threads will only ever run
+// on the specifically pinned core.
+#define SB_HAS_CROSS_CORE_SCHEDULER 1
+
+// --- System Header Configuration -------------------------------------------
+
+// Any system headers listed here that are not provided by the platform will be
+// emulated in starboard/types.h.
+
+// Whether the current platform provides the standard header stdarg.h.
+#define SB_HAS_STDARG_H 1
+
+// Whether the current platform provides the standard header stdbool.h.
+#define SB_HAS_STDBOOL_H 1
+
+// Whether the current platform provides the standard header stddef.h.
+#define SB_HAS_STDDEF_H 1
+
+// Whether the current platform provides the standard header stdint.h.
+#define SB_HAS_STDINT_H 1
+
+// Whether the current platform provides the standard header inttypes.h.
+#define SB_HAS_INTTYPES_H 1
+
+// Whether the current platform provides the standard header sys/types.h.
+#define SB_HAS_SYS_TYPES_H 0
+
+// Whether the current platform provides the standard header limits.h.
+#define SB_HAS_LIMITS_H 1
+
+// Whether the current platform provides the standard header float.h.
+#define SB_HAS_FLOAT_H 1
+
+// Whether the current platform provides ssize_t.
+#define SB_HAS_SSIZE_T 0
+
+// Type detection for wchar_t.
+#if defined(__WCHAR_MAX__) && \
+ (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff)
+#define SB_IS_WCHAR_T_UTF32 1
+#elif defined(__WCHAR_MAX__) && \
+ (__WCHAR_MAX__ == 0x7fff || __WCHAR_MAX__ == 0xffff)
+#define SB_IS_WCHAR_T_UTF16 1
+#endif
+
+// Chrome only defines these two if ARMEL or MIPSEL are defined.
+#if defined(__ARMEL__)
+// Chrome has an exclusion for iOS here, we should too when we support iOS.
+#define SB_IS_WCHAR_T_UNSIGNED 1
+#elif defined(__MIPSEL__)
+#define SB_IS_WCHAR_T_SIGNED 1
+#endif
+
+// This quirk is used to fix an issue caused by the rewriting of memset to
+// SbMemorySet in third_party/protobuf/src/google/protobuf/stubs/port.h.
+#define SB_HAS_QUIRK_MEMSET_IN_SYSTEM_HEADERS 1
+
+// --- Compiler Configuration ------------------------------------------------
+
+// The platform's annotation for forcing a C function to be inlined.
+#define SB_C_FORCE_INLINE __inline__ __attribute__((always_inline))
+
+// The platform's annotation for marking a C function as suggested to be
+// inlined.
+#define SB_C_INLINE inline
+
+// The platform's annotation for marking a C function as forcibly not
+// inlined.
+#define SB_C_NOINLINE __attribute__((noinline))
+
+// The platform's annotation for marking a symbol as exported outside of the
+// current shared library.
+#define SB_EXPORT_PLATFORM __attribute__((visibility("default")))
+
+// The platform's annotation for marking a symbol as imported from outside of
+// the current linking unit.
+#define SB_IMPORT_PLATFORM
+
+// --- Extensions Configuration ----------------------------------------------
+
+// Do not use <unordered_map> and <unordered_set> for the hash table types.
+#define SB_HAS_STD_UNORDERED_HASH 0
+
+// GCC/Clang doesn't define a long long hash function, except for Android and
+// Game consoles.
+#define SB_HAS_LONG_LONG_HASH 0
+
+// GCC/Clang doesn't define a string hash function, except for Game Consoles.
+#define SB_HAS_STRING_HASH 0
+
+// Desktop Linux needs a using statement for the hash functions.
+#define SB_HAS_HASH_USING 0
+
+// Set this to 1 if hash functions for custom types can be defined as a
+// hash_value() function. Otherwise, they need to be placed inside a
+// partially-specified hash struct template with an operator().
+#define SB_HAS_HASH_VALUE 0
+
+// Set this to 1 if use of hash_map or hash_set causes a deprecation warning
+// (which then breaks the build).
+#define SB_HAS_HASH_WARNING 1
+
+// The location to include hash_map on this platform.
+#define SB_HASH_MAP_INCLUDE <ext/hash_map>
+
+// C++'s hash_map and hash_set are often found in different namespaces depending
+// on the compiler.
+#define SB_HASH_NAMESPACE __gnu_cxx
+
+// The location to include hash_set on this platform.
+#define SB_HASH_SET_INCLUDE <ext/hash_set>
+
+// Define this to how this platform copies varargs blocks.
+#define SB_VA_COPY(dest, source) va_copy(dest, source)
+
+// --- Graphics Configuration ------------------------------------------------
+
+// Specifies whether this platform supports a performant accelerated blitter
+// API. The basic requirement is a scaled, clipped, alpha-blended blit.
+#define SB_HAS_BLITTER 0
+
+// Indicates whether or not the given platform supports bilinear filtering.
+// This can be checked to enable/disable renderer tests that verify that this is
+// working properly.
+#define SB_HAS_BILINEAR_FILTERING_SUPPORT 1
+
+// Indicates whether or not the given platform supports rendering of NV12
+// textures. These textures typically originate from video decoders.
+#define SB_HAS_NV12_TEXTURE_SUPPORT 0
+
+// --- I/O Configuration -----------------------------------------------------
+
+// Whether the current platform implements the on screen keyboard interface.
+#define SB_HAS_ON_SCREEN_KEYBOARD 0
+
+// Whether the current platform has speech recognizer.
+#define SB_HAS_SPEECH_RECOGNIZER 0
+
+// Whether the current platform has speech synthesis.
+#define SB_HAS_SPEECH_SYNTHESIS 0
+
+// --- Decoder-only Params ---
+
+// --- Memory Configuration --------------------------------------------------
+
+// Whether this platform has and should use an MMAP function to map physical
+// memory to the virtual address space.
+#if SB_API_VERSION < SB_MMAP_REQUIRED_VERSION
+#define SB_HAS_MMAP 1
+#endif
+
+// Whether this platform can map executable memory. Implies SB_HAS_MMAP. This is
+// required for platforms that want to JIT.
+#define SB_CAN_MAP_EXECUTABLE_MEMORY 1
+// --- Network Configuration -------------------------------------------------
+
+// Specifies whether this platform supports IPV6.
+#define SB_HAS_IPV6 1
+
+// Specifies whether this platform supports pipe.
+#define SB_HAS_PIPE 1
+
+// --- Thread Configuration --------------------------------------------------
+
+// --- Timing API ------------------------------------------------------------
+
+// Whether this platform has an API to retrieve how long the current thread
+// has spent in the executing state.
+#define SB_HAS_TIME_THREAD_NOW 1
+
+// --- Tuneable Parameters ---------------------------------------------------
+
+// --- User Configuration ----------------------------------------------------
+
+// --- Platform Specific Audits ----------------------------------------------
+
+#if !defined(__GNUC__)
+#error "Evergreen-x64 builds need a GCC-like compiler (for the moment)."
+#endif
+
+#endif // STARBOARD_EVERGREEN_X64_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/evergreen/x64/gyp_configuration.gypi b/src/starboard/evergreen/x64/gyp_configuration.gypi
new file mode 100644
index 0000000..dcb689e
--- /dev/null
+++ b/src/starboard/evergreen/x64/gyp_configuration.gypi
@@ -0,0 +1,58 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file was initially generated by starboard/tools/create_derived_build.py,
+# though it may have been modified since its creation.
+
+{
+ 'variables': {
+ 'yasm_exists': 1,
+ 'sb_target_platform': 'evergreen-x64',
+
+ 'compiler_flags': [
+ '-isystem<(cobalt_repo_root)/third_party/musl/arch/x86_64',
+ ],
+ },
+
+ 'target_defaults': {
+ 'defines' : [
+ # Ensure that the Starboardized __external_threading file is included.
+ '_LIBCPP_HAS_THREAD_API_EXTERNAL',
+ # Ensure that only the forward declarations and type definitions are included
+ # in __external_threading.
+ '_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL',
+ # Enable GNU extensions to get prototypes like ffsl.
+ '_GNU_SOURCE=1',
+ ],
+ 'default_configuration': 'evergreen-x64_debug',
+ 'configurations': {
+ 'evergreen-x64_debug': {
+ 'inherit_from': ['debug_base'],
+ },
+ 'evergreen-x64_devel': {
+ 'inherit_from': ['devel_base'],
+ },
+ 'evergreen-x64_qa': {
+ 'inherit_from': ['qa_base'],
+ },
+ 'evergreen-x64_gold': {
+ 'inherit_from': ['gold_base'],
+ },
+ }, # end of configurations
+ },
+ 'includes': [
+ '<(DEPTH)/starboard/evergreen/shared/gyp_configuration.gypi',
+ '<(DEPTH)/starboard/evergreen/shared/compiler_flags.gypi',
+ ],
+}
diff --git a/src/starboard/evergreen/x64/gyp_configuration.py b/src/starboard/evergreen/x64/gyp_configuration.py
new file mode 100644
index 0000000..9c572b0
--- /dev/null
+++ b/src/starboard/evergreen/x64/gyp_configuration.py
@@ -0,0 +1,110 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Starboard evergreen-x64 platform configuration for gyp_cobalt."""
+
+import os.path
+
+from starboard.build import clang as clang_build
+from starboard.evergreen.shared import gyp_configuration as shared_configuration
+from starboard.tools import build
+from starboard.tools import paths
+from starboard.tools.toolchain import ar
+from starboard.tools.toolchain import bash
+from starboard.tools.toolchain import clang
+from starboard.tools.toolchain import clangxx
+from starboard.tools.toolchain import cp
+from starboard.tools.toolchain import evergreen_linker
+from starboard.tools.toolchain import touch
+
+
+class EvergreenX64Configuration(shared_configuration.EvergreenConfiguration):
+ """Starboard Evergreen x64 platform configuration."""
+
+ def __init__(self,
+ platform_name='evergreen-x64',
+ asan_enabled_by_default=False,
+ goma_supports_compiler=True,
+ sabi_json_path=None):
+ # pylint: disable=useless-super-delegation
+ super(EvergreenX64Configuration,
+ self).__init__(platform_name, asan_enabled_by_default,
+ goma_supports_compiler, sabi_json_path)
+ self.AppendApplicationConfigurationPath(os.path.dirname(__file__))
+ self._host_toolchain = None
+
+ def GetTargetToolchain(self):
+ return self.GetHostToolchain()
+
+ def GetHostToolchain(self):
+ if not self._host_toolchain:
+ if not hasattr(self, 'host_compiler_environment'):
+ self.host_compiler_environment = build.GetHostCompilerEnvironment(
+ clang_build.GetClangSpecification(), False)
+ cc_path = self.host_compiler_environment['CC_host']
+ cxx_path = self.host_compiler_environment['CXX_host']
+
+ # Takes the provided value of CXX_HOST with a prepended 'gomacc' and an
+ # appended 'bin/clang++' and strips them off, leaving us with an absolute
+ # path to the root directory of our toolchain.
+ begin_path_index = cxx_path.find('/')
+ end_path_index = cxx_path.rfind('/', 0, cxx_path.rfind('/')) + 1
+
+ cxx_path_root = cxx_path[begin_path_index:end_path_index]
+
+ self._host_toolchain = [
+ clang.CCompiler(path=cc_path),
+ clang.CxxCompiler(path=cxx_path),
+ clang.AssemblerWithCPreprocessor(path=cc_path),
+ ar.StaticThinLinker(),
+ ar.StaticLinker(),
+ clangxx.ExecutableLinker(path=cxx_path),
+ evergreen_linker.SharedLibraryLinker(
+ path=cxx_path_root, extra_flags=['-m elf_x86_64']),
+ cp.Copy(),
+ touch.Stamp(),
+ bash.Shell(),
+ ]
+ return self._host_toolchain
+
+ def GetTestFilters(self):
+ filters = super(EvergreenX64Configuration, self).GetTestFilters()
+ # Remove the exclusion filter on SbDrmTest.AnySupportedKeySystems.
+ # Generally, children of linux/shared do not support widevine, but children
+ # of linux/x64x11 do, if the content decryption module is present.
+
+ has_cdm = os.path.isfile(
+ os.path.join(paths.REPOSITORY_ROOT, 'third_party', 'cdm', 'cdm',
+ 'include', 'content_decryption_module.h'))
+
+ if not has_cdm:
+ return filters
+
+ for test_filter in filters:
+ if (test_filter.target_name == 'nplb' and
+ test_filter.test_name == 'SbDrmTest.AnySupportedKeySystems'):
+ filters.remove(test_filter)
+ return filters
+
+ def GetVariables(self, configuration):
+ variables = super(EvergreenX64Configuration, self).GetVariables(configuration)
+ variables.update({
+ 'include_path_platform_deploy_gypi':
+ 'starboard/evergreen/x64/platform_deploy.gypi',
+ })
+ return variables
+
+
+def CreatePlatformConfig():
+ return EvergreenX64Configuration(
+ sabi_json_path='starboard/sabi/x64/sysv/sabi.json')
diff --git a/src/starboard/evergreen/x64/platform_deploy.gypi b/src/starboard/evergreen/x64/platform_deploy.gypi
new file mode 100644
index 0000000..f2524b5
--- /dev/null
+++ b/src/starboard/evergreen/x64/platform_deploy.gypi
@@ -0,0 +1,37 @@
+# Copyright 2020 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+{
+ 'variables': {
+ 'deploy_executable_file': '<(target_deploy_dir)/lib/lib<(executable_name).so',
+ 'executable_file': '<(PRODUCT_DIR)/lib/lib<(executable_name).so',
+ },
+ 'includes': [ '<(DEPTH)/starboard/build/collect_deploy_content.gypi' ],
+ 'actions': [
+ {
+ 'action_name': 'deploy_executable',
+ 'message': 'Strip executable: <(deploy_executable_file)',
+ 'inputs': [
+ '<(executable_file)',
+ '<(content_deploy_stamp_file)',
+ ],
+ 'outputs': [ '<(deploy_executable_file)' ],
+ 'action': [
+ 'strip',
+ '-o', '<(deploy_executable_file)',
+ '<(executable_file)',
+ ],
+ },
+ ],
+}
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/6/starboard_platform.gyp b/src/starboard/evergreen/x64/starboard_platform.gyp
similarity index 78%
copy from src/starboard/linux/x64x11/blittergles/sbversion/6/starboard_platform.gyp
copy to src/starboard/evergreen/x64/starboard_platform.gyp
index 8163408..8fa33ef 100644
--- a/src/starboard/linux/x64x11/blittergles/sbversion/6/starboard_platform.gyp
+++ b/src/starboard/evergreen/x64/starboard_platform.gyp
@@ -12,13 +12,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# This file was initially generated by starboard/tools/create_derived_build.py,
-# though it may have been modified since its creation.
-
{
'includes': [
# Note that we are 'includes'ing a 'gyp' file, not a 'gypi' file. The idea
# is that we just want this file to *be* the parent gyp file.
- '<(DEPTH)/starboard/linux/x64x11/blittergles/starboard_platform.gyp',
+ '<(DEPTH)/starboard/evergreen/shared/starboard_platform.gyp',
],
}
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/6/atomic_public.h b/src/starboard/evergreen/x64/thread_types_public.h
similarity index 72%
copy from src/starboard/linux/x64x11/blittergles/sbversion/6/atomic_public.h
copy to src/starboard/evergreen/x64/thread_types_public.h
index d2414dd..e420a58 100644
--- a/src/starboard/linux/x64x11/blittergles/sbversion/6/atomic_public.h
+++ b/src/starboard/evergreen/x64/thread_types_public.h
@@ -15,9 +15,9 @@
// This file was initially generated by starboard/tools/create_derived_build.py,
// though it may have been modified since its creation.
-#ifndef STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_6_ATOMIC_PUBLIC_H_
-#define STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_6_ATOMIC_PUBLIC_H_
+#ifndef STARBOARD_EVERGREEN_X64_THREAD_TYPES_PUBLIC_H_
+#define STARBOARD_EVERGREEN_X64_THREAD_TYPES_PUBLIC_H_
-#include "starboard/linux/x64x11/blittergles/atomic_public.h"
+#include "starboard/shared/pthread/types_public.h"
-#endif // STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_6_ATOMIC_PUBLIC_H_
+#endif // STARBOARD_EVERGREEN_X64_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/sbversion/6/__init__.py b/src/starboard/evergreen/x86/__init__.py
similarity index 100%
rename from src/starboard/linux/x64x11/sbversion/6/__init__.py
rename to src/starboard/evergreen/x86/__init__.py
diff --git a/src/starboard/raspi/2/mozjs/thread_types_public.h b/src/starboard/evergreen/x86/atomic_public.h
similarity index 65%
copy from src/starboard/raspi/2/mozjs/thread_types_public.h
copy to src/starboard/evergreen/x86/atomic_public.h
index 96c08d1..9b310a7 100644
--- a/src/starboard/raspi/2/mozjs/thread_types_public.h
+++ b/src/starboard/evergreen/x86/atomic_public.h
@@ -1,4 +1,4 @@
-// Copyright 2018 The Cobalt Authors. All Rights Reserved.
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,9 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef STARBOARD_RASPI_2_MOZJS_THREAD_TYPES_PUBLIC_H_
-#define STARBOARD_RASPI_2_MOZJS_THREAD_TYPES_PUBLIC_H_
+#ifndef STARBOARD_EVERGREEN_X86_ATOMIC_PUBLIC_H_
+#define STARBOARD_EVERGREEN_X86_ATOMIC_PUBLIC_H_
-#include "starboard/raspi/2/thread_types_public.h"
+#include "starboard/atomic.h"
+#include "starboard/shared/gcc/atomic_gcc_public.h"
-#endif // STARBOARD_RASPI_2_MOZJS_THREAD_TYPES_PUBLIC_H_
+#endif // STARBOARD_EVERGREEN_X86_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/evergreen/x86/configuration_public.h b/src/starboard/evergreen/x86/configuration_public.h
new file mode 100644
index 0000000..56b5909
--- /dev/null
+++ b/src/starboard/evergreen/x86/configuration_public.h
@@ -0,0 +1,181 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// The Starboard configuration for x86. Other devices will have
+// specific Starboard implementations.
+
+// Other source files should never include this header directly, but should
+// include the generic "starboard/configuration.h" instead.
+
+#ifndef STARBOARD_EVERGREEN_X86_CONFIGURATION_PUBLIC_H_
+#define STARBOARD_EVERGREEN_X86_CONFIGURATION_PUBLIC_H_
+
+// Configuration parameters that allow the application to make some general
+// compile-time decisions with respect to the the number of cores likely to be
+// available on this platform. For a definitive measure, the application should
+// still call SbSystemGetNumberOfProcessors at runtime.
+
+// Whether the current platform's thread scheduler will automatically balance
+// threads between cores, as opposed to systems where threads will only ever run
+// on the specifically pinned core.
+#define SB_HAS_CROSS_CORE_SCHEDULER 1
+
+// --- System Header Configuration -------------------------------------------
+
+// Any system headers listed here that are not provided by the platform will be
+// emulated in starboard/types.h.
+
+// Whether the current platform provides the standard header stdarg.h.
+#define SB_HAS_STDARG_H 1
+
+// Whether the current platform provides the standard header stdbool.h.
+#define SB_HAS_STDBOOL_H 1
+
+// Whether the current platform provides the standard header stddef.h.
+#define SB_HAS_STDDEF_H 1
+
+// Whether the current platform provides the standard header stdint.h.
+#define SB_HAS_STDINT_H 1
+
+// Whether the current platform provides the standard header inttypes.h.
+#define SB_HAS_INTTYPES_H 1
+
+// Whether the current platform provides the standard header sys/types.h.
+#define SB_HAS_SYS_TYPES_H 0
+
+// Whether the current platform provides the standard header limits.h.
+#define SB_HAS_LIMITS_H 1
+
+// Whether the current platform provides the standard header float.h.
+#define SB_HAS_FLOAT_H 1
+
+// Whether the current platform provides ssize_t.
+#define SB_HAS_SSIZE_T 0
+
+// Type detection for wchar_t.
+#if defined(__WCHAR_MAX__) && \
+ (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff)
+#define SB_IS_WCHAR_T_UTF32 1
+#elif defined(__WCHAR_MAX__) && \
+ (__WCHAR_MAX__ == 0x7fff || __WCHAR_MAX__ == 0xffff)
+#define SB_IS_WCHAR_T_UTF16 1
+#endif
+
+// Chrome only defines these two if ARMEL or MIPSEL are defined.
+#if defined(__ARMEL__)
+// Chrome has an exclusion for iOS here, we should too when we support iOS.
+#define SB_IS_WCHAR_T_UNSIGNED 1
+#elif defined(__MIPSEL__)
+#define SB_IS_WCHAR_T_SIGNED 1
+#endif
+
+// --- Compiler Configuration ------------------------------------------------
+
+// The platform's annotation for forcing a C function to be inlined.
+#define SB_C_FORCE_INLINE __inline__ __attribute__((always_inline))
+
+// The platform's annotation for marking a C function as suggested to be
+// inlined.
+#define SB_C_INLINE inline
+
+// The platform's annotation for marking a C function as forcibly not
+// inlined.
+#define SB_C_NOINLINE __attribute__((noinline))
+
+// The platform's annotation for marking a symbol as exported outside of the
+// current shared library.
+#define SB_EXPORT_PLATFORM __attribute__((visibility("default")))
+
+// The platform's annotation for marking a symbol as imported from outside of
+// the current linking unit.
+#define SB_IMPORT_PLATFORM
+
+// --- Extensions Configuration ----------------------------------------------
+
+// Do not use <unordered_map> and <unordered_set> for the hash table types.
+#define SB_HAS_STD_UNORDERED_HASH 0
+
+// GCC/Clang doesn't define a long long hash function, except for Android and
+// Game consoles.
+#define SB_HAS_LONG_LONG_HASH 0
+
+// GCC/Clang doesn't define a string hash function, except for Game Consoles.
+#define SB_HAS_STRING_HASH 0
+
+// Desktop Linux needs a using statement for the hash functions.
+#define SB_HAS_HASH_USING 0
+
+// Set this to 1 if hash functions for custom types can be defined as a
+// hash_value() function. Otherwise, they need to be placed inside a
+// partially-specified hash struct template with an operator().
+#define SB_HAS_HASH_VALUE 0
+
+// Set this to 1 if use of hash_map or hash_set causes a deprecation warning
+// (which then breaks the build).
+#define SB_HAS_HASH_WARNING 1
+
+// The location to include hash_map on this platform.
+#define SB_HASH_MAP_INCLUDE <ext/hash_map>
+
+// C++'s hash_map and hash_set are often found in different namespaces depending
+// on the compiler.
+#define SB_HASH_NAMESPACE __gnu_cxx
+
+// The location to include hash_set on this platform.
+#define SB_HASH_SET_INCLUDE <ext/hash_set>
+
+// Define this to how this platform copies varargs blocks.
+#define SB_VA_COPY(dest, source) va_copy(dest, source)
+
+// --- Graphics Configuration ------------------------------------------------
+
+// Specifies whether this platform supports a performant accelerated blitter
+// API. The basic requirement is a scaled, clipped, alpha-blended blit.
+#define SB_HAS_BLITTER 0
+
+// Indicates whether or not the given platform supports bilinear filtering.
+// This can be checked to enable/disable renderer tests that verify that this is
+// working properly.
+#define SB_HAS_BILINEAR_FILTERING_SUPPORT 1
+
+// Indicates whether or not the given platform supports rendering of NV12
+// textures. These textures typically originate from video decoders.
+#define SB_HAS_NV12_TEXTURE_SUPPORT 1
+
+// --- Decoder-only Params ---
+
+// --- Memory Configuration --------------------------------------------------
+
+// Whether this platform can map executable memory. Implies SB_HAS_MMAP. This is
+// required for platforms that want to JIT.
+#define SB_CAN_MAP_EXECUTABLE_MEMORY 1
+
+// --- Network Configuration -------------------------------------------------
+
+// Specifies whether this platform supports pipe.
+#define SB_HAS_PIPE 1
+
+// --- Thread Configuration --------------------------------------------------
+
+// --- Tuneable Parameters ---------------------------------------------------
+
+// --- User Configuration ----------------------------------------------------
+
+// --- Platform Specific Audits ----------------------------------------------
+
+#if !defined(__GNUC__)
+#error "evergreen-x86 builds need a GCC-like compiler (for the moment)."
+#endif
+
+#endif // STARBOARD_EVERGREEN_X86_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/evergreen/x86/gyp_configuration.gypi b/src/starboard/evergreen/x86/gyp_configuration.gypi
new file mode 100644
index 0000000..f8a868f
--- /dev/null
+++ b/src/starboard/evergreen/x86/gyp_configuration.gypi
@@ -0,0 +1,58 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file was initially generated by starboard/tools/create_derived_build.py,
+# though it may have been modified since its creation.
+
+{
+ 'variables': {
+ 'yasm_exists': 1,
+ 'sb_target_platform': 'evergreen-x86',
+
+ 'compiler_flags': [
+ '-isystem<(cobalt_repo_root)/third_party/musl/arch/i386',
+ ],
+ },
+
+ 'target_defaults': {
+ 'defines' : [
+ # Ensure that the Starboardized __external_threading file is included.
+ '_LIBCPP_HAS_THREAD_API_EXTERNAL',
+ # Ensure that only the forward declarations and type definitions are included
+ # in __external_threading.
+ '_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL',
+ # Enable GNU extensions to get prototypes like ffsl.
+ '_GNU_SOURCE=1',
+ ],
+ 'default_configuration': 'evergreen-x86_debug',
+ 'configurations': {
+ 'evergreen-x86_debug': {
+ 'inherit_from': ['debug_base'],
+ },
+ 'evergreen-x86_devel': {
+ 'inherit_from': ['devel_base'],
+ },
+ 'evergreen-x86_qa': {
+ 'inherit_from': ['qa_base'],
+ },
+ 'evergreen-x86_gold': {
+ 'inherit_from': ['gold_base'],
+ },
+ }, # end of configurations
+ },
+ 'includes': [
+ '<(DEPTH)/starboard/evergreen/shared/gyp_configuration.gypi',
+ '<(DEPTH)/starboard/evergreen/shared/compiler_flags.gypi',
+ ],
+}
diff --git a/src/starboard/evergreen/x86/gyp_configuration.py b/src/starboard/evergreen/x86/gyp_configuration.py
new file mode 100644
index 0000000..a67484c
--- /dev/null
+++ b/src/starboard/evergreen/x86/gyp_configuration.py
@@ -0,0 +1,101 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Starboard evergreen-x86 platform configuration for gyp_cobalt."""
+
+import os.path
+
+from starboard.build import clang as clang_build
+from starboard.evergreen.shared import gyp_configuration as shared_configuration
+from starboard.tools import build
+from starboard.tools import paths
+from starboard.tools.toolchain import ar
+from starboard.tools.toolchain import bash
+from starboard.tools.toolchain import clang
+from starboard.tools.toolchain import clangxx
+from starboard.tools.toolchain import cp
+from starboard.tools.toolchain import evergreen_linker
+from starboard.tools.toolchain import touch
+
+
+class EvergreenX86Configuration(shared_configuration.EvergreenConfiguration):
+ """Starboard Evergreen x86 platform configuration."""
+
+ def __init__(self,
+ platform_name='evergreen-x86',
+ asan_enabled_by_default=False,
+ goma_supports_compiler=True,
+ sabi_json_path=None):
+ # pylint: disable=useless-super-delegation
+ super(EvergreenX86Configuration,
+ self).__init__(platform_name, asan_enabled_by_default,
+ goma_supports_compiler, sabi_json_path)
+ self._host_toolchain = None
+
+ def GetTargetToolchain(self):
+ return self.GetHostToolchain()
+
+ def GetHostToolchain(self):
+ if not self._host_toolchain:
+ if not hasattr(self, 'host_compiler_environment'):
+ self.host_compiler_environment = build.GetHostCompilerEnvironment(
+ clang_build.GetClangSpecification(), False)
+ cc_path = self.host_compiler_environment['CC_host']
+ cxx_path = self.host_compiler_environment['CXX_host']
+
+ # Takes the provided value of CXX_HOST with a prepended 'gomacc' and an
+ # appended 'bin/clang++' and strips them off, leaving us with an absolute
+ # path to the root directory of our toolchain.
+ begin_path_index = cxx_path.find('/')
+ end_path_index = cxx_path.rfind('/', 0, cxx_path.rfind('/')) + 1
+
+ cxx_path_root = cxx_path[begin_path_index:end_path_index]
+
+ self._host_toolchain = [
+ clang.CCompiler(path=cc_path),
+ clang.CxxCompiler(path=cxx_path),
+ clang.AssemblerWithCPreprocessor(path=cc_path),
+ ar.StaticThinLinker(),
+ ar.StaticLinker(),
+ clangxx.ExecutableLinker(path=cxx_path),
+ evergreen_linker.SharedLibraryLinker(
+ path=cxx_path_root, extra_flags=['-m elf_i686']),
+ cp.Copy(),
+ touch.Stamp(),
+ bash.Shell(),
+ ]
+ return self._host_toolchain
+
+ def GetTestFilters(self):
+ filters = super(EvergreenX86Configuration, self).GetTestFilters()
+ # Remove the exclusion filter on SbDrmTest.AnySupportedKeySystems.
+ # Generally, children of linux/shared do not support widevine, but children
+ # of linux/x64x11 do, if the content decryption module is present.
+
+ has_cdm = os.path.isfile(
+ os.path.join(paths.REPOSITORY_ROOT, 'third_party', 'cdm', 'cdm',
+ 'include', 'content_decryption_module.h'))
+
+ if not has_cdm:
+ return filters
+
+ for test_filter in filters:
+ if (test_filter.target_name == 'nplb' and
+ test_filter.test_name == 'SbDrmTest.AnySupportedKeySystems'):
+ filters.remove(test_filter)
+ return filters
+
+
+def CreatePlatformConfig():
+ return EvergreenX86Configuration(
+ sabi_json_path='starboard/sabi/x86/sabi.json')
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/6/starboard_platform.gyp b/src/starboard/evergreen/x86/starboard_platform.gyp
similarity index 78%
copy from src/starboard/linux/x64x11/blittergles/sbversion/6/starboard_platform.gyp
copy to src/starboard/evergreen/x86/starboard_platform.gyp
index 8163408..8fa33ef 100644
--- a/src/starboard/linux/x64x11/blittergles/sbversion/6/starboard_platform.gyp
+++ b/src/starboard/evergreen/x86/starboard_platform.gyp
@@ -12,13 +12,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# This file was initially generated by starboard/tools/create_derived_build.py,
-# though it may have been modified since its creation.
-
{
'includes': [
# Note that we are 'includes'ing a 'gyp' file, not a 'gypi' file. The idea
# is that we just want this file to *be* the parent gyp file.
- '<(DEPTH)/starboard/linux/x64x11/blittergles/starboard_platform.gyp',
+ '<(DEPTH)/starboard/evergreen/shared/starboard_platform.gyp',
],
}
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/6/atomic_public.h b/src/starboard/evergreen/x86/thread_types_public.h
similarity index 72%
copy from src/starboard/linux/x64x11/blittergles/sbversion/6/atomic_public.h
copy to src/starboard/evergreen/x86/thread_types_public.h
index d2414dd..261f06a 100644
--- a/src/starboard/linux/x64x11/blittergles/sbversion/6/atomic_public.h
+++ b/src/starboard/evergreen/x86/thread_types_public.h
@@ -15,9 +15,9 @@
// This file was initially generated by starboard/tools/create_derived_build.py,
// though it may have been modified since its creation.
-#ifndef STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_6_ATOMIC_PUBLIC_H_
-#define STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_6_ATOMIC_PUBLIC_H_
+#ifndef STARBOARD_EVERGREEN_X86_THREAD_TYPES_PUBLIC_H_
+#define STARBOARD_EVERGREEN_X86_THREAD_TYPES_PUBLIC_H_
-#include "starboard/linux/x64x11/blittergles/atomic_public.h"
+#include "starboard/shared/pthread/types_public.h"
-#endif // STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_6_ATOMIC_PUBLIC_H_
+#endif // STARBOARD_EVERGREEN_X86_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/examples/glclear/main.cc b/src/starboard/examples/glclear/main.cc
index 2a12c7a..d74d90f 100644
--- a/src/starboard/examples/glclear/main.cc
+++ b/src/starboard/examples/glclear/main.cc
@@ -172,7 +172,7 @@
SbEglInt32 context_attrib_list[] = {
SB_EGL_CONTEXT_CLIENT_VERSION, 3, SB_EGL_NONE,
};
-#if defined(GLES3_SUPPORTED)
+#if SB_API_VERSION < SB_GLES3_DEPRECATED_VERSION && defined(GLES3_SUPPORTED)
// Attempt to create an OpenGL ES 3.0 context.
context_ = EGL_CALL_SIMPLE(eglCreateContext(
display_, config, SB_EGL_NO_CONTEXT, context_attrib_list));
diff --git a/src/starboard/input.h b/src/starboard/input.h
index 3014ce6..3c608bf 100644
--- a/src/starboard/input.h
+++ b/src/starboard/input.h
@@ -150,14 +150,12 @@
// Event data for |kSbEventTypeInput| events.
typedef struct SbInputData {
-#if SB_API_VERSION >= 10
// The time that should be reported for this event. This is intended to
// facilitate calculation of time-sensitive information (e.g. velocity for
// kSbInputEventTypeMove). This may be set to 0 to have the relevant systems
// automatically set the timestamp. However, this may happen at a later time,
// so the relative time between events may not be preserved.
SbTimeMonotonic timestamp;
-#endif
// The window in which the input was generated.
SbWindow window;
diff --git a/src/starboard/key.h b/src/starboard/key.h
index e61a74c..8626ffb 100644
--- a/src/starboard/key.h
+++ b/src/starboard/key.h
@@ -241,10 +241,8 @@
// A button that will switch between different available audio tracks.
kSbKeyMediaAudioTrack = 0x3001,
-#if SB_API_VERSION >= 10
// A button that will trigger voice input.
kSbKeyMicrophone = 0x3002,
-#endif // SB_API_VERSION >= 10
// Mouse buttons, starting with the left mouse button.
kSbKeyMouse1 = 0x7000,
diff --git a/src/starboard/linux/shared/BUILD.gn b/src/starboard/linux/shared/BUILD.gn
index 7121e20..8e843ac 100644
--- a/src/starboard/linux/shared/BUILD.gn
+++ b/src/starboard/linux/shared/BUILD.gn
@@ -501,8 +501,9 @@
"//starboard/shared/starboard/player/filter/audio_decoder_internal.h",
"//starboard/shared/starboard/player/filter/audio_frame_tracker.cc",
"//starboard/shared/starboard/player/filter/audio_frame_tracker.h",
- "//starboard/shared/starboard/player/filter/audio_renderer_internal.cc",
"//starboard/shared/starboard/player/filter/audio_renderer_internal.h",
+ "//starboard/shared/starboard/player/filter/audio_renderer_internal_impl.cc",
+ "//starboard/shared/starboard/player/filter/audio_renderer_internal_impl.h",
"//starboard/shared/starboard/player/filter/audio_renderer_sink.h",
"//starboard/shared/starboard/player/filter/audio_renderer_sink_impl.cc",
"//starboard/shared/starboard/player/filter/audio_renderer_sink_impl.h",
@@ -523,8 +524,9 @@
"//starboard/shared/starboard/player/filter/punchout_video_renderer_sink.h",
"//starboard/shared/starboard/player/filter/video_decoder_internal.h",
"//starboard/shared/starboard/player/filter/video_frame_internal.h",
- "//starboard/shared/starboard/player/filter/video_renderer_internal.cc",
"//starboard/shared/starboard/player/filter/video_renderer_internal.h",
+ "//starboard/shared/starboard/player/filter/video_renderer_internal_impl.cc",
+ "//starboard/shared/starboard/player/filter/video_renderer_internal_impl.h",
"//starboard/shared/starboard/player/filter/wsola_internal.cc",
"//starboard/shared/starboard/player/filter/wsola_internal.h",
"//starboard/shared/starboard/player/input_buffer_internal.cc",
@@ -536,18 +538,15 @@
"//starboard/shared/starboard/player/player_create.cc",
"//starboard/shared/starboard/player/player_destroy.cc",
"//starboard/shared/starboard/player/player_get_current_frame.cc",
- "//starboard/shared/starboard/player/player_get_info.cc",
"//starboard/shared/starboard/player/player_get_preferred_output_mode_prefer_punchout.cc",
"//starboard/shared/starboard/player/player_internal.cc",
"//starboard/shared/starboard/player/player_internal.h",
- "//starboard/shared/starboard/player/player_seek.cc",
"//starboard/shared/starboard/player/player_set_bounds.cc",
"//starboard/shared/starboard/player/player_set_playback_rate.cc",
"//starboard/shared/starboard/player/player_set_volume.cc",
"//starboard/shared/starboard/player/player_worker.cc",
"//starboard/shared/starboard/player/player_worker.h",
"//starboard/shared/starboard/player/player_write_end_of_stream.cc",
- "//starboard/shared/starboard/player/player_write_sample.cc",
"//starboard/shared/starboard/queue_application.cc",
"//starboard/shared/starboard/string_concat.cc",
"//starboard/shared/starboard/string_concat_wide.cc",
diff --git a/src/starboard/linux/shared/configuration.cc b/src/starboard/linux/shared/configuration.cc
new file mode 100644
index 0000000..bc5a3b1
--- /dev/null
+++ b/src/starboard/linux/shared/configuration.cc
@@ -0,0 +1,68 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/linux/shared/configuration.h"
+
+#include "cobalt/extension/configuration.h"
+#include "starboard/common/configuration_defaults.h"
+
+// Omit namespace linux due to symbol name conflict.
+namespace starboard {
+namespace shared {
+
+namespace {
+
+int CobaltEglSwapInterval() {
+ return 0;
+}
+
+bool CobaltEnableJit() {
+ return true;
+}
+
+const CobaltExtensionConfigurationApi kConfigurationApi = {
+ kCobaltExtensionConfigurationName,
+ 1,
+ &common::CobaltUserOnExitStrategyDefault,
+ &common::CobaltRenderDirtyRegionOnlyDefault,
+ &CobaltEglSwapInterval,
+ &common::CobaltFallbackSplashScreenUrlDefault,
+ &common::CobaltEnableQuicDefault,
+ &common::CobaltSkiaCacheSizeInBytesDefault,
+ &common::CobaltOffscreenTargetCacheSizeInBytesDefault,
+ &common::CobaltEncodedImageCacheSizeInBytesDefault,
+ &common::CobaltImageCacheSizeInBytesDefault,
+ &common::CobaltLocalTypefaceCacheSizeInBytesDefault,
+ &common::CobaltRemoteTypefaceCacheSizeInBytesDefault,
+ &common::CobaltMeshCacheSizeInBytesDefault,
+ &common::CobaltSoftwareSurfaceCacheSizeInBytesDefault,
+ &common::CobaltImageCacheCapacityMultiplierWhenPlayingVideoDefault,
+ &common::CobaltSkiaGlyphAtlasWidthDefault,
+ &common::CobaltSkiaGlyphAtlasHeightDefault,
+ &common::CobaltJsGarbageCollectionThresholdInBytesDefault,
+ &common::CobaltReduceCpuMemoryByDefault,
+ &common::CobaltReduceGpuMemoryByDefault,
+ &common::CobaltGcZealDefault,
+ &common::CobaltRasterizerTypeDefault,
+ &CobaltEnableJit,
+};
+
+} // namespace
+
+const void* GetConfigurationApi() {
+ return &kConfigurationApi;
+}
+
+} // namespace shared
+} // namespace starboard
diff --git a/src/starboard/linux/shared/configuration.gni b/src/starboard/linux/shared/configuration.gni
index a997d81..c4562c3 100644
--- a/src/starboard/linux/shared/configuration.gni
+++ b/src/starboard/linux/shared/configuration.gni
@@ -18,7 +18,8 @@
# The source of EGL and GLES headers and libraries.
# Valid values (case and everything sensitive!):
# "none" - No EGL + GLES implementation is available on this platform.
-# "system_gles3" - Use the system implementation of EGL + GLES3. The
+# "system_gles3" - Deprecated. Use system_gles2 instead.
+# Use the system implementation of EGL + GLES3. The
# headers and libraries must be on the system include and
# link paths.
# "system_gles2" - Use the system implementation of EGL + GLES2. The
@@ -30,7 +31,7 @@
# ANGLE implementation for the platform.
# Choosing an unsupported value will result in a GYP error:
# "cobalt/renderer/egl_and_gles/egl_and_gles_<gl_type>.gyp not found"
-gl_type = "system_gles3"
+gl_type = "system_gles2"
# Use media source extension implementation that is conformed to the
# Candidate Recommendation of July 5th 2016.
diff --git a/src/starboard/linux/shared/configuration.h b/src/starboard/linux/shared/configuration.h
new file mode 100644
index 0000000..95861de
--- /dev/null
+++ b/src/starboard/linux/shared/configuration.h
@@ -0,0 +1,27 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_LINUX_SHARED_CONFIGURATION_H_
+#define STARBOARD_LINUX_SHARED_CONFIGURATION_H_
+
+// Omit namespace linux due to symbol name conflict.
+namespace starboard {
+namespace shared {
+
+const void* GetConfigurationApi();
+
+} // namespace shared
+} // namespace starboard
+
+#endif // STARBOARD_LINUX_SHARED_CONFIGURATION_H_
diff --git a/src/starboard/linux/shared/configuration_constants.cc b/src/starboard/linux/shared/configuration_constants.cc
index eec85fc..f95a9f3 100644
--- a/src/starboard/linux/shared/configuration_constants.cc
+++ b/src/starboard/linux/shared/configuration_constants.cc
@@ -57,9 +57,6 @@
// Specifies whether this platform updates audio frames asynchronously.
const bool kSbHasAsyncAudioFramesReporting = false;
-// Allow playing audioless video.
-const bool kSbHasAudiolessVideo = true;
-
// Specifies whether this platform has webm/vp9 support. This should be set to
// non-zero on platforms with webm/vp9 support.
const bool kSbHasMediaWebmVp9Support = false;
@@ -142,6 +139,11 @@
// The string form of SB_PATH_SEP_CHAR.
const char* kSbPathSepString = ":";
+// Specifies the preferred byte order of color channels in a pixel. Refer to
+// starboard/configuration.h for the possible values. EGL/GLES platforms should
+// generally prefer a byte order of RGBA, regardless of endianness.
+const int kSbPreferredRgbaByteOrder = SB_PREFERRED_RGBA_BYTE_ORDER_RGBA;
+
// The maximum number of users that can be signed in at the same time.
const uint32_t kSbUserMaxSignedIn = 1;
diff --git a/src/starboard/linux/shared/configuration_public.h b/src/starboard/linux/shared/configuration_public.h
index 9c32fa1..f7f15e7 100644
--- a/src/starboard/linux/shared/configuration_public.h
+++ b/src/starboard/linux/shared/configuration_public.h
@@ -195,10 +195,12 @@
// API. The basic requirement is a scaled, clipped, alpha-blended blit.
#define SB_HAS_BLITTER 0
+#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
// Specifies the preferred byte order of color channels in a pixel. Refer to
// starboard/configuration.h for the possible values. EGL/GLES platforms should
// generally prefer a byte order of RGBA, regardless of endianness.
#define SB_PREFERRED_RGBA_BYTE_ORDER SB_PREFERRED_RGBA_BYTE_ORDER_RGBA
+#endif // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
// Indicates whether or not the given platform supports bilinear filtering.
// This can be checked to enable/disable renderer tests that verify that this is
@@ -259,11 +261,6 @@
#endif // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
-// Allow playing audioless video.
-#define SB_HAS_AUDIOLESS_VIDEO 1
-#endif // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
-
-#if SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
// Allow ac3 and ec3 support
#define SB_HAS_AC3_AUDIO 1
#endif // SB_API_VERSION < SB_FEATURE_RUNTIME_CONFIGS_VERSION
diff --git a/src/starboard/linux/shared/drm_create_system.cc b/src/starboard/linux/shared/drm_create_system.cc
index cde9aa9..43d517e 100644
--- a/src/starboard/linux/shared/drm_create_system.cc
+++ b/src/starboard/linux/shared/drm_create_system.cc
@@ -23,13 +23,9 @@
void* context,
SbDrmSessionUpdateRequestFunc update_request_callback,
SbDrmSessionUpdatedFunc session_updated_callback,
- SbDrmSessionKeyStatusesChangedFunc key_statuses_changed_callback
-#if SB_API_VERSION >= 10
- ,
+ SbDrmSessionKeyStatusesChangedFunc key_statuses_changed_callback,
SbDrmServerCertificateUpdatedFunc server_certificate_updated_callback,
- SbDrmSessionClosedFunc session_closed_callback
-#endif // SB_API_VERSION >= 10
- ) {
+ SbDrmSessionClosedFunc session_closed_callback) {
using starboard::shared::widevine::DrmSystemWidevine;
if (!update_request_callback || !session_updated_callback) {
return kSbDrmSystemInvalid;
@@ -37,26 +33,15 @@
if (!key_statuses_changed_callback) {
return kSbDrmSystemInvalid;
}
-#if SB_API_VERSION >= 10
if (!server_certificate_updated_callback || !session_closed_callback) {
return kSbDrmSystemInvalid;
}
-#endif // SB_API_VERSION >= 10
if (!DrmSystemWidevine::IsKeySystemSupported(key_system)) {
SB_DLOG(WARNING) << "Invalid key system " << key_system;
return kSbDrmSystemInvalid;
}
- return new DrmSystemWidevine(context, update_request_callback,
- session_updated_callback,
- key_statuses_changed_callback
-#if SB_API_VERSION >= 10
- ,
- server_certificate_updated_callback
-#endif // SB_API_VERSION >= 10
-#if SB_HAS(DRM_SESSION_CLOSED)
- ,
- session_closed_callback
-#endif // SB_HAS(DRM_SESSION_CLOSED)
- ,
- "Linux", "Linux");
+ return new DrmSystemWidevine(
+ context, update_request_callback, session_updated_callback,
+ key_statuses_changed_callback, server_certificate_updated_callback,
+ session_closed_callback, "Linux", "Linux");
}
diff --git a/src/starboard/linux/shared/gyp_configuration.gypi b/src/starboard/linux/shared/gyp_configuration.gypi
index b565543..cf8dc21 100644
--- a/src/starboard/linux/shared/gyp_configuration.gypi
+++ b/src/starboard/linux/shared/gyp_configuration.gypi
@@ -21,7 +21,6 @@
# TODO: Remove when omitted for all platforms in base_configuration.gypi.
'sb_static_contents_output_data_dir': '<(PRODUCT_DIR)/content',
- 'target_arch%': 'x64',
'target_os': 'linux',
'yasm_exists': 1,
'sb_widevine_platform' : 'linux',
diff --git a/src/starboard/linux/shared/libraries.gypi b/src/starboard/linux/shared/libraries.gypi
index 505de3d..45fccd0 100644
--- a/src/starboard/linux/shared/libraries.gypi
+++ b/src/starboard/linux/shared/libraries.gypi
@@ -25,11 +25,6 @@
'-Wl,--wrap=eglSwapBuffers',
],
- 'cobalt_platform_dependencies': [
- # GL Linux makes some GL calls within decode_target_internal.cc.
- '<(DEPTH)/starboard/egl_and_gles/egl_and_gles.gyp:egl_and_gles',
- ],
-
'platform_libraries': [
'-lX11',
'-lXcomposite',
diff --git a/src/starboard/linux/shared/media_is_audio_supported.cc b/src/starboard/linux/shared/media_is_audio_supported.cc
index bea80a7..5128fb0 100644
--- a/src/starboard/linux/shared/media_is_audio_supported.cc
+++ b/src/starboard/linux/shared/media_is_audio_supported.cc
@@ -14,11 +14,23 @@
#include "starboard/shared/starboard/media/media_support_internal.h"
+#include "starboard/common/log.h"
#include "starboard/configuration.h"
#include "starboard/configuration_constants.h"
#include "starboard/media.h"
-bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec, int64_t bitrate) {
+bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec,
+#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+ const char* content_type,
+#endif // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+ int64_t bitrate) {
+#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+ if (!content_type) {
+ SB_LOG(WARNING) << "|content_type| cannot be nullptr.";
+ return false;
+ }
+#endif // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+
if (audio_codec == kSbMediaAudioCodecAac) {
return bitrate <= kSbMediaMaxAudioBitrateInBitsPerSecond;
}
diff --git a/src/starboard/linux/shared/media_is_video_supported.cc b/src/starboard/linux/shared/media_is_video_supported.cc
index 488abba..a323a8c 100644
--- a/src/starboard/linux/shared/media_is_video_supported.cc
+++ b/src/starboard/linux/shared/media_is_video_supported.cc
@@ -14,6 +14,7 @@
#include "starboard/shared/starboard/media/media_support_internal.h"
+#include "starboard/common/log.h"
#include "starboard/configuration.h"
#include "starboard/configuration_constants.h"
#if SB_API_VERSION >= 11
@@ -31,6 +32,9 @@
using starboard::shared::vpx::is_vpx_supported;
bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec,
+#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+ const char* content_type,
+#endif // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
#if SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
int profile,
int level,
@@ -42,12 +46,8 @@
int frame_width,
int frame_height,
int64_t bitrate,
- int fps
-#if SB_API_VERSION >= 10
- ,
- bool decode_to_texture_required
-#endif // SB_API_VERSION >= 10
- ) {
+ int fps,
+ bool decode_to_texture_required) {
#if SB_API_VERSION < 11
const auto kSbMediaVideoCodecAv1 = kSbMediaVideoCodecVp10;
#endif // SB_API_VERSION < 11
@@ -56,6 +56,13 @@
SB_UNREFERENCED_PARAMETER(profile);
SB_UNREFERENCED_PARAMETER(level);
+#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+ if (!content_type) {
+ SB_LOG(WARNING) << "|content_type| cannot be nullptr.";
+ return false;
+ }
+#endif // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+
if (!IsSDRVideo(bit_depth, primary_id, transfer_id, matrix_id)) {
if (bit_depth != 10 && bit_depth != 12) {
return false;
@@ -67,7 +74,6 @@
}
#endif // SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
-#if SB_API_VERSION >= 10
if (decode_to_texture_required) {
bool has_gles_support = false;
@@ -83,7 +89,6 @@
// Assume that all GLES2 Linux platforms can play decode-to-texture video
// just as well as normal video.
}
-#endif // SB_API_VERSION >= 10
return ((video_codec == kSbMediaVideoCodecAv1 && is_aom_supported()) ||
video_codec == kSbMediaVideoCodecH264 ||
diff --git a/src/starboard/linux/shared/starboard_platform.gypi b/src/starboard/linux/shared/starboard_platform.gypi
index 028dcb6..fdebe88 100644
--- a/src/starboard/linux/shared/starboard_platform.gypi
+++ b/src/starboard/linux/shared/starboard_platform.gypi
@@ -26,6 +26,8 @@
'<@(filter_based_player_sources)',
'<(DEPTH)/starboard/linux/shared/atomic_public.h',
'<(DEPTH)/starboard/linux/shared/audio_sink_type_dispatcher.cc',
+ '<(DEPTH)/starboard/linux/shared/configuration.cc',
+ '<(DEPTH)/starboard/linux/shared/configuration.h',
'<(DEPTH)/starboard/linux/shared/configuration_public.h',
'<(DEPTH)/starboard/linux/shared/configuration_constants.cc',
'<(DEPTH)/starboard/linux/shared/decode_target_get_info.cc',
@@ -37,6 +39,7 @@
'<(DEPTH)/starboard/linux/shared/player_components_factory.cc',
'<(DEPTH)/starboard/linux/shared/system_get_connection_type.cc',
'<(DEPTH)/starboard/linux/shared/system_get_device_type.cc',
+ '<(DEPTH)/starboard/linux/shared/system_get_extensions.cc',
'<(DEPTH)/starboard/linux/shared/system_get_path.cc',
'<(DEPTH)/starboard/linux/shared/system_has_capability.cc',
'<(DEPTH)/starboard/shared/alsa/alsa_audio_sink_type.cc',
@@ -294,14 +297,12 @@
'<(DEPTH)/starboard/shared/starboard/player/player_create.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_destroy.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_get_current_frame.cc',
- '<(DEPTH)/starboard/shared/starboard/player/player_get_info.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_get_info2.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_get_maximum_number_of_samples_per_write.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_get_preferred_output_mode_prefer_punchout.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_internal.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_internal.h',
'<(DEPTH)/starboard/shared/starboard/player/player_output_mode_supported.cc',
- '<(DEPTH)/starboard/shared/starboard/player/player_seek.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_seek2.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_set_bounds.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_set_playback_rate.cc',
@@ -309,7 +310,6 @@
'<(DEPTH)/starboard/shared/starboard/player/player_worker.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_worker.h',
'<(DEPTH)/starboard/shared/starboard/player/player_write_end_of_stream.cc',
- '<(DEPTH)/starboard/shared/starboard/player/player_write_sample.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_write_sample2.cc',
'<(DEPTH)/starboard/shared/starboard/queue_application.cc',
'<(DEPTH)/starboard/shared/starboard/string_concat.cc',
@@ -334,7 +334,6 @@
'<(DEPTH)/starboard/shared/stub/cryptography_set_authenticated_data.cc',
'<(DEPTH)/starboard/shared/stub/cryptography_set_initialization_vector.cc',
'<(DEPTH)/starboard/shared/stub/cryptography_transform.cc',
- '<(DEPTH)/starboard/shared/stub/system_get_extensions.cc',
'<(DEPTH)/starboard/shared/stub/image_decode.cc',
'<(DEPTH)/starboard/shared/stub/image_is_decode_supported.cc',
'<(DEPTH)/starboard/shared/stub/media_set_audio_write_duration.cc',
@@ -454,6 +453,7 @@
}],
['sb_evergreen_compatible == 1', {
'starboard_platform_dependencies': [
+ '<(DEPTH)/starboard/elf_loader/evergreen_config.gyp:evergreen_config',
'<(DEPTH)/third_party/llvm-project/libunwind/libunwind.gyp:unwind_starboard',
]},
],
diff --git a/src/starboard/linux/shared/system_get_extensions.cc b/src/starboard/linux/shared/system_get_extensions.cc
new file mode 100644
index 0000000..bb7cb7a
--- /dev/null
+++ b/src/starboard/linux/shared/system_get_extensions.cc
@@ -0,0 +1,40 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/system.h"
+
+#include "cobalt/extension/configuration.h"
+#include "starboard/common/string.h"
+#if SB_IS(EVERGREEN_COMPATIBLE)
+#include "starboard/elf_loader/evergreen_config.h"
+#endif
+#include "starboard/linux/shared/configuration.h"
+
+const void* SbSystemGetExtension(const char* name) {
+#if SB_IS(EVERGREEN_COMPATIBLE)
+ const starboard::elf_loader::EvergreenConfig* evergreen_config =
+ starboard::elf_loader::EvergreenConfig::GetInstance();
+ if (evergreen_config != NULL &&
+ evergreen_config->custom_get_extension_ != NULL) {
+ const void* ext = evergreen_config->custom_get_extension_(name);
+ if (ext != NULL) {
+ return ext;
+ }
+ }
+#endif
+ if (SbStringCompareAll(name, kCobaltExtensionConfigurationName) == 0) {
+ return starboard::shared::GetConfigurationApi();
+ }
+ return NULL;
+}
diff --git a/src/starboard/linux/shared/system_get_path.cc b/src/starboard/linux/shared/system_get_path.cc
index ee5d301..06abade 100644
--- a/src/starboard/linux/shared/system_get_path.cc
+++ b/src/starboard/linux/shared/system_get_path.cc
@@ -26,6 +26,9 @@
#include "starboard/common/string.h"
#include "starboard/configuration_constants.h"
#include "starboard/directory.h"
+#if SB_IS(EVERGREEN_COMPATIBLE)
+#include "starboard/elf_loader/evergreen_config.h"
+#endif
#include "starboard/user.h"
namespace {
@@ -87,6 +90,29 @@
return true;
}
+#if SB_IS(EVERGREEN_COMPATIBLE)
+// May override the content path if there is EvergreenConfig published.
+// The override allows for switching to different content paths based
+// on the Evergreen binary executed.
+// Returns false if it failed.
+bool GetEvergreenContentPathOverride(char* out_path, int path_size) {
+ const starboard::elf_loader::EvergreenConfig* evergreen_config =
+ starboard::elf_loader::EvergreenConfig::GetInstance();
+ if (!evergreen_config) {
+ return true;
+ }
+ if (evergreen_config->content_path_.empty()) {
+ return true;
+ }
+
+ if (SbStringCopy(out_path, evergreen_config->content_path_.c_str(),
+ path_size) >= path_size) {
+ return false;
+ }
+ return true;
+}
+#endif
+
// Places up to |path_size| - 1 characters of the path to the directory
// containing the current executable in |out_path|, ensuring it is
// NULL-terminated. Returns success status. The result being greater than
@@ -156,6 +182,12 @@
if (SbStringConcat(path.data(), "/content", kPathSize) >= kPathSize) {
return false;
}
+#if SB_IS(EVERGREEN_COMPATIBLE)
+ if (!GetEvergreenContentPathOverride(path.data(), kPathSize)) {
+ return false;
+ }
+
+#endif
break;
case kSbSystemPathCacheDirectory:
diff --git a/src/starboard/linux/shared/system_has_capability.cc b/src/starboard/linux/shared/system_has_capability.cc
index 401e712..7473825 100644
--- a/src/starboard/linux/shared/system_has_capability.cc
+++ b/src/starboard/linux/shared/system_has_capability.cc
@@ -22,10 +22,8 @@
return false;
case kSbSystemCapabilityCanQueryGPUMemoryStats:
return false;
-#if SB_API_VERSION >= 10
case kSbSystemCapabilitySetsInputTimestamp:
return false;
-#endif
}
SB_DLOG(WARNING) << "Unrecognized capability: " << capability_id;
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/10/configuration_public.h b/src/starboard/linux/x64x11/blittergles/sbversion/10/configuration_public.h
index 5b3ac1e..3356def 100644
--- a/src/starboard/linux/x64x11/blittergles/sbversion/10/configuration_public.h
+++ b/src/starboard/linux/x64x11/blittergles/sbversion/10/configuration_public.h
@@ -71,6 +71,10 @@
// textures. These textures typically originate from video decoders.
#define SB_HAS_NV12_TEXTURE_SUPPORT 1
+#ifndef COBALT_FORCE_DIRECT_GLES_RASTERIZER
+#define COBALT_FORCE_DIRECT_GLES_RASTERIZER 1
+#endif
+
// --- Shared Configuration and Overrides ------------------------------------
// Include the Linux configuration that's common between all Desktop Linuxes.
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/6/configuration_public.h b/src/starboard/linux/x64x11/blittergles/sbversion/6/configuration_public.h
deleted file mode 100644
index beb7a18..0000000
--- a/src/starboard/linux/x64x11/blittergles/sbversion/6/configuration_public.h
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2019 The Cobalt Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// This file was initially generated by starboard/tools/create_derived_build.py,
-// though it may have been modified since its creation.
-
-#ifndef STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_6_CONFIGURATION_PUBLIC_H_
-#define STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_6_CONFIGURATION_PUBLIC_H_
-
-#undef SB_API_VERSION
-#define SB_API_VERSION 6
-
-// --- Architecture Configuration --------------------------------------------
-
-// Whether the current platform is big endian. SB_IS_LITTLE_ENDIAN will be
-// automatically set based on this.
-#define SB_IS_BIG_ENDIAN 0
-
-// Whether the current platform is an ARM architecture.
-#define SB_IS_ARCH_ARM 0
-
-// Whether the current platform is a MIPS architecture.
-#define SB_IS_ARCH_MIPS 0
-
-// Whether the current platform is a PPC architecture.
-#define SB_IS_ARCH_PPC 0
-
-// Whether the current platform is an x86 architecture.
-#define SB_IS_ARCH_X86 1
-
-// Whether the current platform is a 32-bit architecture.
-#define SB_IS_32_BIT 0
-
-// Whether the current platform is a 64-bit architecture.
-#define SB_IS_64_BIT 1
-
-// Whether the current platform's pointers are 32-bit.
-// Whether the current platform's longs are 32-bit.
-#define SB_HAS_32_BIT_POINTERS 0
-#define SB_HAS_32_BIT_LONG 0
-
-// Whether the current platform's pointers are 64-bit.
-// Whether the current platform's longs are 64-bit.
-#define SB_HAS_64_BIT_POINTERS 1
-#define SB_HAS_64_BIT_LONG 1
-
-// Configuration parameters that allow the application to make some general
-// compile-time decisions with respect to the the number of cores likely to be
-// available on this platform. For a definitive measure, the application should
-// still call SbSystemGetNumberOfProcessors at runtime.
-
-// Whether the current platform's thread scheduler will automatically balance
-// threads between cores, as opposed to systems where threads will only ever run
-// on the specifically pinned core.
-#define SB_HAS_CROSS_CORE_SCHEDULER 1
-
-// --- Graphics Configuration ------------------------------------------------
-
-// Indicates whether or not the given platform supports rendering of NV12
-// textures. These textures typically originate from video decoders.
-#define SB_HAS_NV12_TEXTURE_SUPPORT 1
-
-// --- Shared Configuration and Overrides ------------------------------------
-
-// Include the Linux configuration that's common between all Desktop Linuxes.
-#include "starboard/linux/shared/configuration_public.h"
-
-// Include the Blitter - GLES configuration that's common between all Blitter -
-// GLES configurations.
-#include "starboard/linux/x64x11/blittergles/shared/configuration_public.h"
-
-// Starboard API versions 11 and earlier must define this variable, and have
-// microphone supported.
-#define SB_HAS_MICROPHONE 1
-
-// Whether the current platform has speech synthesis.
-#undef SB_HAS_SPEECH_SYNTHESIS
-#define SB_HAS_SPEECH_SYNTHESIS 0
-
-#endif // STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_6_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/6/gyp_configuration.py b/src/starboard/linux/x64x11/blittergles/sbversion/6/gyp_configuration.py
deleted file mode 100644
index 228c1ba..0000000
--- a/src/starboard/linux/x64x11/blittergles/sbversion/6/gyp_configuration.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright 2019 The Cobalt Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# This file was initially generated by starboard/tools/create_derived_build.py,
-# though it may have been modified since its creation.
-"""Starboard Linux X64X11 Blittergles Sbversion 6 platform configuration."""
-
-from starboard.linux.x64x11 import gyp_configuration as parent_configuration
-
-
-class LinuxX64X11BlitterglesSbversion6Configuration(
- parent_configuration.LinuxX64X11Configuration):
-
- def GetVariables(self, config_name):
- variables = super(LinuxX64X11BlitterglesSbversion6Configuration,
- self).GetVariables(config_name)
- # V8 requires new Starboard features so we must use SpiderMonkey in older
- # versions of Starboard.
- variables.update({
- 'javascript_engine': 'mozjs-45',
- 'cobalt_enable_jit': 0,
- })
- return variables
-
-
-def CreatePlatformConfig():
- return LinuxX64X11BlitterglesSbversion6Configuration(
- 'linux-x64x11-blittergles-sbversion-6')
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/6/thread_types_public.h b/src/starboard/linux/x64x11/blittergles/sbversion/6/thread_types_public.h
deleted file mode 100644
index 6e977ae..0000000
--- a/src/starboard/linux/x64x11/blittergles/sbversion/6/thread_types_public.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2019 The Cobalt Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// This file was initially generated by starboard/tools/create_derived_build.py,
-// though it may have been modified since its creation.
-
-#ifndef STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_6_THREAD_TYPES_PUBLIC_H_
-#define STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_6_THREAD_TYPES_PUBLIC_H_
-
-#include "starboard/linux/x64x11/blittergles/thread_types_public.h"
-
-#endif // STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_6_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/blittergles/starboard_platform.gyp b/src/starboard/linux/x64x11/blittergles/starboard_platform.gyp
index 67b3b7e..b7cc9ca 100644
--- a/src/starboard/linux/x64x11/blittergles/starboard_platform.gyp
+++ b/src/starboard/linux/x64x11/blittergles/starboard_platform.gyp
@@ -82,10 +82,10 @@
'<(DEPTH)/starboard/shared/blittergles/shader_program.h',
'<(DEPTH)/starboard/shared/starboard/blitter_blit_rect_to_rect_tiled.cc',
'<(DEPTH)/starboard/shared/starboard/blitter_blit_rects_to_rects.cc',
- '<(DEPTH)/starboard/shared/stub/system_gles.cc',
+ '<(DEPTH)/starboard/shared/stub/system_gles.cc',
],
'sources!': [
- '<(DEPTH)/starboard/shared/gles/system_gles2.cc',
+ '<(DEPTH)/starboard/shared/gles/system_gles2.cc',
],
'defines': [
# This must be defined when building Starboard, and must not when
diff --git a/src/starboard/linux/x64x11/clang/3.6/gyp_configuration.py b/src/starboard/linux/x64x11/clang/3.6/gyp_configuration.py
index 1c3847b..7baf5ea 100644
--- a/src/starboard/linux/x64x11/clang/3.6/gyp_configuration.py
+++ b/src/starboard/linux/x64x11/clang/3.6/gyp_configuration.py
@@ -19,6 +19,12 @@
from starboard.linux.shared import gyp_configuration as shared_configuration
from starboard.tools import build
+from starboard.tools.toolchain import ar
+from starboard.tools.toolchain import bash
+from starboard.tools.toolchain import clang
+from starboard.tools.toolchain import clangxx
+from starboard.tools.toolchain import cp
+from starboard.tools.toolchain import touch
class LinuxX64X11Clang36Configuration(shared_configuration.LinuxConfiguration):
@@ -66,6 +72,42 @@
})
return variables
+ def GetTargetToolchain(self):
+ environment_variables = self.GetEnvironmentVariables()
+ cc_path = environment_variables['CC']
+ cxx_path = environment_variables['CXX']
+
+ return [
+ clang.CCompiler(path=cc_path),
+ clang.CxxCompiler(path=cxx_path),
+ clang.AssemblerWithCPreprocessor(path=cc_path),
+ ar.StaticThinLinker(),
+ ar.StaticLinker(),
+ clangxx.ExecutableLinker(path=cxx_path, write_group=True),
+ clangxx.SharedLibraryLinker(path=cxx_path),
+ cp.Copy(),
+ touch.Stamp(),
+ bash.Shell(),
+ ]
+
+ def GetHostToolchain(self):
+ environment_variables = self.GetEnvironmentVariables()
+ cc_path = environment_variables['CC_host']
+ cxx_path = environment_variables['CXX_host']
+
+ return [
+ clang.CCompiler(path=cc_path),
+ clang.CxxCompiler(path=cxx_path),
+ clang.AssemblerWithCPreprocessor(path=cc_path),
+ ar.StaticThinLinker(),
+ ar.StaticLinker(),
+ clangxx.ExecutableLinker(path=cxx_path, write_group=True),
+ clangxx.SharedLibraryLinker(path=cxx_path),
+ cp.Copy(),
+ touch.Stamp(),
+ bash.Shell(),
+ ]
+
def CreatePlatformConfig():
try:
diff --git a/src/starboard/linux/x64x11/gczeal/configuration.cc b/src/starboard/linux/x64x11/gczeal/configuration.cc
new file mode 100644
index 0000000..d692d79
--- /dev/null
+++ b/src/starboard/linux/x64x11/gczeal/configuration.cc
@@ -0,0 +1,74 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/linux/x64x11/gczeal/configuration.h"
+
+#include "cobalt/extension/configuration.h"
+#include "starboard/common/configuration_defaults.h"
+
+// Omit namespace linux due to symbol name conflict.
+namespace starboard {
+namespace x64x11 {
+namespace gczeal {
+
+namespace {
+
+int CobaltEglSwapInterval() {
+ return 0;
+}
+
+bool CobaltGcZeal() {
+ return true;
+}
+
+bool CobaltEnableJit() {
+ return true;
+}
+
+const CobaltExtensionConfigurationApi kConfigurationApi = {
+ kCobaltExtensionConfigurationName,
+ 1,
+ &common::CobaltUserOnExitStrategyDefault,
+ &common::CobaltRenderDirtyRegionOnlyDefault,
+ &CobaltEglSwapInterval,
+ &common::CobaltFallbackSplashScreenUrlDefault,
+ &common::CobaltEnableQuicDefault,
+ &common::CobaltSkiaCacheSizeInBytesDefault,
+ &common::CobaltOffscreenTargetCacheSizeInBytesDefault,
+ &common::CobaltEncodedImageCacheSizeInBytesDefault,
+ &common::CobaltImageCacheSizeInBytesDefault,
+ &common::CobaltLocalTypefaceCacheSizeInBytesDefault,
+ &common::CobaltRemoteTypefaceCacheSizeInBytesDefault,
+ &common::CobaltMeshCacheSizeInBytesDefault,
+ &common::CobaltSoftwareSurfaceCacheSizeInBytesDefault,
+ &common::CobaltImageCacheCapacityMultiplierWhenPlayingVideoDefault,
+ &common::CobaltSkiaGlyphAtlasWidthDefault,
+ &common::CobaltSkiaGlyphAtlasHeightDefault,
+ &common::CobaltJsGarbageCollectionThresholdInBytesDefault,
+ &common::CobaltReduceCpuMemoryByDefault,
+ &common::CobaltReduceGpuMemoryByDefault,
+ &CobaltGcZeal,
+ &common::CobaltRasterizerTypeDefault,
+ &CobaltEnableJit,
+};
+
+} // namespace
+
+const void* GetConfigurationApi() {
+ return &kConfigurationApi;
+}
+
+} // namespace gczeal
+} // namespace x64x11
+} // namespace starboard
diff --git a/src/starboard/linux/x64x11/gczeal/configuration.h b/src/starboard/linux/x64x11/gczeal/configuration.h
new file mode 100644
index 0000000..5248102
--- /dev/null
+++ b/src/starboard/linux/x64x11/gczeal/configuration.h
@@ -0,0 +1,29 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_LINUX_X64X11_GCZEAL_CONFIGURATION_H_
+#define STARBOARD_LINUX_X64X11_GCZEAL_CONFIGURATION_H_
+
+// Omit namespace linux due to symbol name conflict.
+namespace starboard {
+namespace x64x11 {
+namespace gczeal {
+
+const void* GetConfigurationApi();
+
+} // namespace gczeal
+} // namespace x64x11
+} // namespace starboard
+
+#endif // STARBOARD_LINUX_X64X11_GCZEAL_CONFIGURATION_H_
diff --git a/src/starboard/linux/x64x11/gczeal/starboard_platform.gyp b/src/starboard/linux/x64x11/gczeal/starboard_platform.gyp
index 82c4436..029148d 100644
--- a/src/starboard/linux/x64x11/gczeal/starboard_platform.gyp
+++ b/src/starboard/linux/x64x11/gczeal/starboard_platform.gyp
@@ -12,6 +12,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.
{
+ 'variables': {
+ 'sources': [
+ '<(DEPTH)/starboard/linux/x64x11/gczeal/configuration.cc',
+ '<(DEPTH)/starboard/linux/x64x11/gczeal/configuration.h'
+ '<(DEPTH)/starboard/linux/x64x11/gczeal/system_get_extensions.cc',
+ ],
+ 'sources!': [
+ '<(DEPTH)/starboard/linux/shared/system_get_extensions.cc',
+ ],
+ },
'includes': [
'../shared/starboard_platform_target.gypi',
],
diff --git a/src/starboard/linux/x64x11/gczeal/system_get_extensions.cc b/src/starboard/linux/x64x11/gczeal/system_get_extensions.cc
new file mode 100644
index 0000000..9d6382a
--- /dev/null
+++ b/src/starboard/linux/x64x11/gczeal/system_get_extensions.cc
@@ -0,0 +1,26 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/system.h"
+
+#include "cobalt/extension/configuration.h"
+#include "starboard/common/string.h"
+#include "starboard/linux/x64x11/gczeal/configuration.h"
+
+const void* SbSystemGetExtension(const char* name) {
+ if (SbStringCompareAll(name, kCobaltExtensionConfigurationName) == 0) {
+ return starboard::shared::GetConfigurationApi();
+ }
+ return NULL;
+}
diff --git a/src/starboard/linux/x64x11/gyp_configuration.gypi b/src/starboard/linux/x64x11/gyp_configuration.gypi
index baea958..7571506 100644
--- a/src/starboard/linux/x64x11/gyp_configuration.gypi
+++ b/src/starboard/linux/x64x11/gyp_configuration.gypi
@@ -15,7 +15,7 @@
{
'variables': {
'variables': {
- 'sb_evergreen_compatible': '<!(python <(DEPTH)/build/file_exists.py <(DEPTH)/starboard/elf_loader/evergreen_info.gyp)',
+ 'sb_evergreen_compatible': 1,
}
},
'target_defaults': {
diff --git a/src/starboard/linux/x64x11/main.cc b/src/starboard/linux/x64x11/main.cc
index 954077b..cdb21c5 100644
--- a/src/starboard/linux/x64x11/main.cc
+++ b/src/starboard/linux/x64x11/main.cc
@@ -24,6 +24,13 @@
tzset();
starboard::shared::signal::InstallCrashSignalHandlers();
starboard::shared::signal::InstallSuspendSignalHandlers();
+
+#if SB_HAS_QUIRK(BACKTRACE_DLOPEN_BUG)
+ // Call backtrace() once to work around potential
+ // crash bugs in glibc, in dlopen()
+ SbLogRawDumpStack(3);
+#endif
+
starboard::shared::x11::ApplicationX11 application;
int result = 0;
{
diff --git a/src/starboard/linux/x64x11/mozjs/configuration_public.h b/src/starboard/linux/x64x11/mozjs/configuration_public.h
deleted file mode 100644
index d342943..0000000
--- a/src/starboard/linux/x64x11/mozjs/configuration_public.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2018 The Cobalt Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef STARBOARD_LINUX_X64X11_MOZJS_CONFIGURATION_PUBLIC_H_
-#define STARBOARD_LINUX_X64X11_MOZJS_CONFIGURATION_PUBLIC_H_
-
-// Include the X64X11 Linux configuration.
-#include "starboard/linux/x64x11/configuration_public.h"
-
-#endif // STARBOARD_LINUX_X64X11_MOZJS_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/mozjs/gyp_configuration.gypi b/src/starboard/linux/x64x11/mozjs/gyp_configuration.gypi
deleted file mode 100644
index 24749cf..0000000
--- a/src/starboard/linux/x64x11/mozjs/gyp_configuration.gypi
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright 2018 The Cobalt Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-{
- 'target_defaults': {
- 'default_configuration': 'linux-x64x11-mozjs_debug',
- 'configurations': {
- 'linux-x64x11-mozjs_debug': {
- 'inherit_from': ['debug_base'],
- },
- 'linux-x64x11-mozjs_devel': {
- 'inherit_from': ['devel_base'],
- },
- 'linux-x64x11-mozjs_qa': {
- 'inherit_from': ['qa_base'],
- },
- 'linux-x64x11-mozjs_gold': {
- 'inherit_from': ['gold_base'],
- },
- }, # end of configurations
- },
-
- 'includes': [
- '../gyp_configuration.gypi',
- ],
-}
diff --git a/src/starboard/linux/x64x11/mozjs/gyp_configuration.py b/src/starboard/linux/x64x11/mozjs/gyp_configuration.py
deleted file mode 100644
index e8bba52..0000000
--- a/src/starboard/linux/x64x11/mozjs/gyp_configuration.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright 2018 The Cobalt Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Starboard Linux X64 X11 mozjs platform configuration."""
-
-from starboard.linux.x64x11 import gyp_configuration as linux_configuration
-
-
-class LinuxX64X11MozjsConfiguration(linux_configuration.LinuxX64X11Configuration
- ):
- """Starboard Linux X64 X11 mozjs platform configuration."""
-
- def GetVariables(self, config_name):
- variables = super(LinuxX64X11MozjsConfiguration,
- self).GetVariables(config_name)
- variables.update({
- 'javascript_engine': 'mozjs-45',
- 'cobalt_enable_jit': 0,
- })
- return variables
-
-
-def CreatePlatformConfig():
- return LinuxX64X11MozjsConfiguration(
- 'linux-x64x11-mozjs', sabi_json_path='starboard/sabi/x64/sysv/sabi.json')
diff --git a/src/starboard/linux/x64x11/mozjs/starboard_platform.gyp b/src/starboard/linux/x64x11/mozjs/starboard_platform.gyp
deleted file mode 100644
index 9ef3bfc..0000000
--- a/src/starboard/linux/x64x11/mozjs/starboard_platform.gyp
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright 2018 The Cobalt Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-{
- 'includes': [
- '../shared/starboard_platform_target.gypi',
- ],
-}
diff --git a/src/starboard/linux/x64x11/sbversion/10/configuration_public.h b/src/starboard/linux/x64x11/sbversion/10/configuration_public.h
index 61d198d..4b7de4e 100644
--- a/src/starboard/linux/x64x11/sbversion/10/configuration_public.h
+++ b/src/starboard/linux/x64x11/sbversion/10/configuration_public.h
@@ -71,6 +71,10 @@
// textures. These textures typically originate from video decoders.
#define SB_HAS_NV12_TEXTURE_SUPPORT 1
+#ifndef COBALT_FORCE_DIRECT_GLES_RASTERIZER
+#define COBALT_FORCE_DIRECT_GLES_RASTERIZER 1
+#endif
+
// --- Shared Configuration and Overrides ------------------------------------
// Include the Linux configuration that's common between all Desktop Linuxes.
diff --git a/src/starboard/linux/x64x11/sbversion/6/atomic_public.h b/src/starboard/linux/x64x11/sbversion/6/atomic_public.h
deleted file mode 100644
index 14cedc9..0000000
--- a/src/starboard/linux/x64x11/sbversion/6/atomic_public.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2018 The Cobalt Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// This file was initially generated by create_derived_build.py,
-// though it may have been modified since its creation.
-
-#ifndef STARBOARD_LINUX_X64X11_SBVERSION_6_ATOMIC_PUBLIC_H_
-#define STARBOARD_LINUX_X64X11_SBVERSION_6_ATOMIC_PUBLIC_H_
-
-#include "starboard/linux/x64x11/atomic_public.h"
-
-#endif // STARBOARD_LINUX_X64X11_SBVERSION_6_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/sbversion/6/configuration_public.h b/src/starboard/linux/x64x11/sbversion/6/configuration_public.h
deleted file mode 100644
index ff0ff15..0000000
--- a/src/starboard/linux/x64x11/sbversion/6/configuration_public.h
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2018 The Cobalt Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// This file was initially generated by create_derived_build.py,
-// though it may have been modified since its creation.
-
-#ifndef STARBOARD_LINUX_X64X11_SBVERSION_6_CONFIGURATION_PUBLIC_H_
-#define STARBOARD_LINUX_X64X11_SBVERSION_6_CONFIGURATION_PUBLIC_H_
-
-#undef SB_API_VERSION
-#define SB_API_VERSION 6
-
-// --- Architecture Configuration --------------------------------------------
-
-// Whether the current platform is big endian. SB_IS_LITTLE_ENDIAN will be
-// automatically set based on this.
-#define SB_IS_BIG_ENDIAN 0
-
-// Whether the current platform is an ARM architecture.
-#define SB_IS_ARCH_ARM 0
-
-// Whether the current platform is a MIPS architecture.
-#define SB_IS_ARCH_MIPS 0
-
-// Whether the current platform is a PPC architecture.
-#define SB_IS_ARCH_PPC 0
-
-// Whether the current platform is an x86 architecture.
-#define SB_IS_ARCH_X86 1
-
-// Whether the current platform is a 32-bit architecture.
-#define SB_IS_32_BIT 0
-
-// Whether the current platform is a 64-bit architecture.
-#define SB_IS_64_BIT 1
-
-// Whether the current platform's pointers are 32-bit.
-// Whether the current platform's longs are 32-bit.
-#define SB_HAS_32_BIT_POINTERS 0
-#define SB_HAS_32_BIT_LONG 0
-
-// Whether the current platform's pointers are 64-bit.
-// Whether the current platform's longs are 64-bit.
-#define SB_HAS_64_BIT_POINTERS 1
-#define SB_HAS_64_BIT_LONG 1
-
-// Configuration parameters that allow the application to make some general
-// compile-time decisions with respect to the the number of cores likely to be
-// available on this platform. For a definitive measure, the application should
-// still call SbSystemGetNumberOfProcessors at runtime.
-
-// Whether the current platform's thread scheduler will automatically balance
-// threads between cores, as opposed to systems where threads will only ever run
-// on the specifically pinned core.
-#define SB_HAS_CROSS_CORE_SCHEDULER 1
-
-// --- Graphics Configuration ------------------------------------------------
-
-// Indicates whether or not the given platform supports rendering of NV12
-// textures. These textures typically originate from video decoders.
-#define SB_HAS_NV12_TEXTURE_SUPPORT 1
-
-// --- Shared Configuration and Overrides ------------------------------------
-
-// Include the Linux configuration that's common between all Desktop Linuxes.
-#include "starboard/linux/shared/configuration_public.h"
-
-// Starboard API versions 11 and earlier must define this variable, and have
-// microphone supported.
-#define SB_HAS_MICROPHONE 1
-
-// Whether the current platform has speech synthesis.
-#undef SB_HAS_SPEECH_SYNTHESIS
-#define SB_HAS_SPEECH_SYNTHESIS 0
-
-#endif // STARBOARD_LINUX_X64X11_SBVERSION_6_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/sbversion/6/gyp_configuration.gypi b/src/starboard/linux/x64x11/sbversion/6/gyp_configuration.gypi
deleted file mode 100644
index 9b8d915..0000000
--- a/src/starboard/linux/x64x11/sbversion/6/gyp_configuration.gypi
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright 2018 The Cobalt Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# This file was initially generated by create_derived_build.py,
-# though it may have been modified since its creation.
-
-{
- 'target_defaults': {
- 'default_configuration': 'linux-x64x11-sbversion-6_debug',
- 'configurations': {
- 'linux-x64x11-sbversion-6_debug': {
- 'inherit_from': ['debug_base'],
- },
- 'linux-x64x11-sbversion-6_devel': {
- 'inherit_from': ['devel_base'],
- },
- 'linux-x64x11-sbversion-6_qa': {
- 'inherit_from': ['qa_base'],
- },
- 'linux-x64x11-sbversion-6_gold': {
- 'inherit_from': ['gold_base'],
- },
- }, # end of configurations
- },
-
- 'variables': {
- 'enable_map_to_mesh': 1,
- },
-
- 'includes': [
- '<(DEPTH)/starboard/linux/x64x11/shared/gyp_configuration.gypi',
- ],
-}
diff --git a/src/starboard/linux/x64x11/sbversion/6/gyp_configuration.py b/src/starboard/linux/x64x11/sbversion/6/gyp_configuration.py
deleted file mode 100644
index a60fc25..0000000
--- a/src/starboard/linux/x64x11/sbversion/6/gyp_configuration.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright 2018 The Cobalt Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# This file was initially generated by create_derived_build.py,
-# though it may have been modified since its creation.
-
-from starboard.linux.x64x11 import gyp_configuration as parent_configuration
-
-
-class LinuxX64X11Sbversion6Configuration(
- parent_configuration.LinuxX64X11Configuration):
-
- def GetVariables(self, config_name):
- variables = super(LinuxX64X11Sbversion6Configuration,
- self).GetVariables(config_name)
- # V8 requires new Starboard features so we must use SpiderMonkey in older
- # versions of Starboard.
- variables.update({
- 'javascript_engine': 'mozjs-45',
- 'cobalt_enable_jit': 0,
- })
- return variables
-
-
-def CreatePlatformConfig():
- return LinuxX64X11Sbversion6Configuration('linux-x64x11-sbversion-6')
diff --git a/src/starboard/linux/x64x11/sbversion/6/starboard_platform.gyp b/src/starboard/linux/x64x11/sbversion/6/starboard_platform.gyp
deleted file mode 100644
index 95cd6ef..0000000
--- a/src/starboard/linux/x64x11/sbversion/6/starboard_platform.gyp
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright 2018 The Cobalt Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# This file was initially generated by create_derived_build.py,
-# though it may have been modified since its creation.
-
-{
- 'includes': [
- # Note that we are 'includes'ing a 'gyp' file, not a 'gypi' file. The idea
- # is that we just want this file to *be* the parent gyp file.
- '<(DEPTH)/starboard/linux/x64x11/starboard_platform.gyp',
- ],
-}
diff --git a/src/starboard/linux/x64x11/sbversion/6/starboard_platform_tests.gyp b/src/starboard/linux/x64x11/sbversion/6/starboard_platform_tests.gyp
deleted file mode 100644
index 6eb123d..0000000
--- a/src/starboard/linux/x64x11/sbversion/6/starboard_platform_tests.gyp
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright 2018 The Cobalt Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# This file was initially generated by create_derived_build.py,
-# though it may have been modified since its creation.
-
-{
- 'includes': [
- # Note that we are 'includes'ing a 'gyp' file, not a 'gypi' file. The idea
- # is that we just want this file to *be* the parent gyp file.
- '<(DEPTH)/starboard/linux/x64x11/starboard_platform_tests.gyp',
- ],
-}
diff --git a/src/starboard/linux/x64x11/sbversion/6/thread_types_public.h b/src/starboard/linux/x64x11/sbversion/6/thread_types_public.h
deleted file mode 100644
index 8c70c99..0000000
--- a/src/starboard/linux/x64x11/sbversion/6/thread_types_public.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2018 The Cobalt Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// This file was initially generated by create_derived_build.py,
-// though it may have been modified since its creation.
-
-#ifndef STARBOARD_LINUX_X64X11_SBVERSION_6_THREAD_TYPES_PUBLIC_H_
-#define STARBOARD_LINUX_X64X11_SBVERSION_6_THREAD_TYPES_PUBLIC_H_
-
-#include "starboard/linux/x64x11/thread_types_public.h"
-
-#endif // STARBOARD_LINUX_X64X11_SBVERSION_6_THREAD_TYPES_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/skia/configuration.cc b/src/starboard/linux/x64x11/skia/configuration.cc
new file mode 100644
index 0000000..cc918a5
--- /dev/null
+++ b/src/starboard/linux/x64x11/skia/configuration.cc
@@ -0,0 +1,70 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/linux/x64x11/skia/configuration.h"
+
+#include "cobalt/extension/configuration.h"
+#include "starboard/common/configuration_defaults.h"
+
+// Omit namespace linux due to symbol name conflict.
+namespace starboard {
+namespace x64x11 {
+namespace skia {
+
+namespace {
+
+int CobaltEglSwapInterval() {
+ return 0;
+}
+
+const char* CobaltRasterizerType() {
+ return "hardware";
+}
+
+const CobaltExtensionConfigurationApi kConfigurationApi = {
+ kCobaltExtensionConfigurationName,
+ 1,
+ &common::CobaltUserOnExitStrategyDefault,
+ &common::CobaltRenderDirtyRegionOnlyDefault,
+ &CobaltEglSwapInterval,
+ &common::CobaltFallbackSplashScreenUrlDefault,
+ &common::CobaltEnableQuicDefault,
+ &common::CobaltSkiaCacheSizeInBytesDefault,
+ &common::CobaltOffscreenTargetCacheSizeInBytesDefault,
+ &common::CobaltEncodedImageCacheSizeInBytesDefault,
+ &common::CobaltImageCacheSizeInBytesDefault,
+ &common::CobaltLocalTypefaceCacheSizeInBytesDefault,
+ &common::CobaltRemoteTypefaceCacheSizeInBytesDefault,
+ &common::CobaltMeshCacheSizeInBytesDefault,
+ &common::CobaltSoftwareSurfaceCacheSizeInBytesDefault,
+ &common::CobaltImageCacheCapacityMultiplierWhenPlayingVideoDefault,
+ &common::CobaltSkiaGlyphAtlasWidthDefault,
+ &common::CobaltSkiaGlyphAtlasHeightDefault,
+ &common::CobaltJsGarbageCollectionThresholdInBytesDefault,
+ &common::CobaltReduceCpuMemoryByDefault,
+ &common::CobaltReduceGpuMemoryByDefault,
+ &common::CobaltGcZealDefault,
+ &CobaltRasterizerType,
+ &common::CobaltEnableJitDefault,
+};
+
+} // namespace
+
+const void* GetConfigurationApi() {
+ return &kConfigurationApi;
+}
+
+} // namespace skia
+} // namespace x64x11
+} // namespace starboard
diff --git a/src/starboard/linux/x64x11/skia/configuration.h b/src/starboard/linux/x64x11/skia/configuration.h
new file mode 100644
index 0000000..54b1205
--- /dev/null
+++ b/src/starboard/linux/x64x11/skia/configuration.h
@@ -0,0 +1,29 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_LINUX_X64X11_SKIA_CONFIGURATION_H_
+#define STARBOARD_LINUX_X64X11_SKIA_CONFIGURATION_H_
+
+// Omit namespace linux due to symbol name conflict.
+namespace starboard {
+namespace x64x11 {
+namespace skia {
+
+const void* GetConfigurationApi();
+
+} // namespace skia
+} // namespace x64x11
+} // namespace starboard
+
+#endif // STARBOARD_LINUX_X64X11_SKIA_CONFIGURATION_H_
diff --git a/src/starboard/linux/x64x11/skia/starboard_platform.gyp b/src/starboard/linux/x64x11/skia/starboard_platform.gyp
index 665c74c..a026091 100644
--- a/src/starboard/linux/x64x11/skia/starboard_platform.gyp
+++ b/src/starboard/linux/x64x11/skia/starboard_platform.gyp
@@ -15,4 +15,16 @@
'includes': [
'../shared/starboard_platform_target.gypi',
],
+ 'target_defaults': {
+ 'sources': [
+ '<(DEPTH)/starboard/linux/x64x11/skia/configuration.cc',
+ '<(DEPTH)/starboard/linux/x64x11/skia/configuration.h',
+ '<(DEPTH)/starboard/linux/x64x11/skia/system_get_extensions.cc',
+ ],
+ 'sources!': [
+ '<(DEPTH)/starboard/linux/shared/configuration.cc',
+ '<(DEPTH)/starboard/linux/shared/configuration.h',
+ '<(DEPTH)/starboard/linux/shared/system_get_extensions.cc',
+ ],
+ },
}
diff --git a/src/starboard/linux/x64x11/skia/system_get_extensions.cc b/src/starboard/linux/x64x11/skia/system_get_extensions.cc
new file mode 100644
index 0000000..4743dab
--- /dev/null
+++ b/src/starboard/linux/x64x11/skia/system_get_extensions.cc
@@ -0,0 +1,26 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/system.h"
+
+#include "cobalt/extension/configuration.h"
+#include "starboard/common/string.h"
+#include "starboard/linux/x64x11/skia/configuration.h"
+
+const void* SbSystemGetExtension(const char* name) {
+ if (SbStringCompareAll(name, kCobaltExtensionConfigurationName) == 0) {
+ return starboard::x64x11::skia::GetConfigurationApi();
+ }
+ return NULL;
+}
diff --git a/src/starboard/linux/x64x11/system_get_property_impl.cc b/src/starboard/linux/x64x11/system_get_property_impl.cc
index 3b11fea..c503210 100644
--- a/src/starboard/linux/x64x11/system_get_property_impl.cc
+++ b/src/starboard/linux/x64x11/system_get_property_impl.cc
@@ -28,52 +28,6 @@
const char* kFriendlyName = "Linux Desktop";
const char* kPlatformName = "X11; Linux x86_64";
-#if SB_API_VERSION < 10
-
-bool GetPlatformUuid(char* out_value, int value_length) {
- struct ifreq interface;
- struct ifconf config;
- char buf[1024];
-
- int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
- if (fd == -1) {
- return false;
- }
- config.ifc_len = sizeof(buf);
- config.ifc_buf = buf;
- int result = ioctl(fd, SIOCGIFCONF, &config);
- if (result == -1) {
- return false;
- }
-
- struct ifreq* cur_interface = config.ifc_req;
- const struct ifreq* const end = cur_interface +
- (config.ifc_len / sizeof(struct ifreq));
-
- for (; cur_interface != end; ++cur_interface) {
- SbStringCopy(interface.ifr_name,
- cur_interface->ifr_name,
- sizeof(cur_interface->ifr_name));
- if (ioctl(fd, SIOCGIFFLAGS, &interface) == -1) {
- continue;
- }
- if (interface.ifr_flags & IFF_LOOPBACK) {
- continue;
- }
- if (ioctl(fd, SIOCGIFHWADDR, &interface) == -1) {
- continue;
- }
- SbStringFormatF(out_value, value_length, "%x:%x:%x:%x:%x:%x",
- interface.ifr_addr.sa_data[0], interface.ifr_addr.sa_data[1],
- interface.ifr_addr.sa_data[2], interface.ifr_addr.sa_data[3],
- interface.ifr_addr.sa_data[4], interface.ifr_addr.sa_data[5]);
- return true;
- }
- return false;
-}
-
-#endif // SB_API_VERSION < 10
-
} // namespace
// Omit namespace linux due to symbol name conflict.
@@ -109,18 +63,14 @@
#endif
case kSbSystemPropertySpeechApiKey:
return false;
-
+ case kSbSystemPropertyUserAgentAuxField:
+ return false;
case kSbSystemPropertyFriendlyName:
return CopyStringAndTestIfSuccess(out_value, value_length, kFriendlyName);
case kSbSystemPropertyPlatformName:
return CopyStringAndTestIfSuccess(out_value, value_length, kPlatformName);
-#if SB_API_VERSION < 10
- case kSbSystemPropertyPlatformUuid:
- return GetPlatformUuid(out_value, value_length);
-#endif // SB_API_VERSION < 10
-
#if SB_API_VERSION >= 11
case kSbSystemPropertyCertificationScope:
if (kCertificationScope[0] == '\0')
diff --git a/src/starboard/loader_app/installation_manager.cc b/src/starboard/loader_app/installation_manager.cc
new file mode 100644
index 0000000..b463471
--- /dev/null
+++ b/src/starboard/loader_app/installation_manager.cc
@@ -0,0 +1,707 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/loader_app/installation_manager.h"
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "starboard/common/log.h"
+#include "starboard/common/mutex.h"
+#include "starboard/common/scoped_ptr.h"
+#include "starboard/configuration_constants.h"
+#include "starboard/directory.h"
+#include "starboard/file.h"
+#include "starboard/loader_app/installation_store.pb.h"
+#include "starboard/once.h"
+#include "starboard/string.h"
+
+namespace starboard {
+namespace loader_app {
+namespace installation_manager {
+
+class InstallationManager {
+ public:
+ explicit InstallationManager(int max_num_installations);
+
+ int Initialize();
+
+ int GetInstallationStatus(int installation_index);
+ int GetInstallationNumTriesLeft(int installation_index);
+ int RollForwardIfNeeded();
+ int DecrementInstallationNumTries(int installation_index);
+
+ int RevertToSuccessfulInstallation();
+ int GetInstallationPath(int installation_index, char* path, int path_length);
+ int GetCurrentInstallationIndex();
+ int MarkInstallationSuccessful(int installation_index);
+ int SelectNewInstallationIndex();
+ int RequestRollForwardToInstallation(int installation_index);
+
+ private:
+ bool IsValidIndex(int i);
+ void ValidatePriorities();
+ int FindCurrentInstallationIndex();
+ void CreateInstallationStore();
+ std::string DumpInstallationSlots();
+ void LogLastSystemError(const char* msg);
+ void ShiftPrioritiesInRange(int high_priority,
+ int low_priority,
+ int shift_amount);
+ bool InitInstallationStorePath();
+ bool LoadInstallationStore();
+ bool SaveInstallationStore();
+ bool CreateInstallationDirs();
+ bool GetInstallationPathInternal(int installation_index,
+ char* path,
+ int path_length);
+
+ cobalt::loader::InstallationStore installation_store_;
+ bool initialized_;
+ int current_installation_;
+ std::string store_path_;
+ std::string storage_dir_;
+ std::string content_dir_;
+ const int max_num_installations_;
+ const int lowest_priority_;
+ const int highest_priority_;
+};
+
+InstallationManager::InstallationManager(int max_num_installations)
+ : initialized_(false),
+ current_installation_(-1),
+ max_num_installations_(max_num_installations),
+ lowest_priority_(max_num_installations_ - 1),
+ highest_priority_(0) {
+ SB_CHECK(max_num_installations_ >= 2);
+}
+
+int InstallationManager::Initialize() {
+ if (initialized_) {
+ return IM_ERROR;
+ }
+ if (!InitInstallationStorePath()) {
+ SB_LOG(ERROR) << "Initialize: failed to init paths";
+ return IM_ERROR;
+ }
+
+ // If there is no existing store, create one.
+ if (!LoadInstallationStore()) {
+ CreateInstallationStore();
+ current_installation_ = FindCurrentInstallationIndex();
+ if (!IsValidIndex(current_installation_)) {
+ SB_LOG(ERROR) << "Initialize: Unable to find current installation"
+ << current_installation_;
+ return IM_ERROR;
+ }
+ if (!CreateInstallationDirs()) {
+ SB_LOG(ERROR) << "Initialize: Unable to create installations dirs";
+ return IM_ERROR;
+ }
+ initialized_ = SaveInstallationStore();
+ } else {
+ current_installation_ = FindCurrentInstallationIndex();
+ if (!IsValidIndex(current_installation_)) {
+ SB_LOG(ERROR) << "Initialize: Unable to find current installation"
+ << current_installation_;
+ return IM_ERROR;
+ }
+ initialized_ = true;
+ }
+ if (!initialized_) {
+ SB_LOG(ERROR) << "Initialize: failed";
+ }
+ SB_DLOG(INFO) << DumpInstallationSlots();
+ return initialized_ ? IM_SUCCESS : IM_ERROR;
+}
+
+void InstallationManager::CreateInstallationStore() {
+ int priority = highest_priority_;
+ for (int i = 0; i < max_num_installations_; i++) {
+ installation_store_.add_installations();
+ installation_store_.mutable_installations(i)->set_is_successful(false);
+ installation_store_.mutable_installations(i)->set_num_tries_left(
+ IM_MAX_NUM_TRIES);
+ installation_store_.mutable_installations(i)->set_priority(priority++);
+ }
+ installation_store_.set_roll_forward_to_installation(-1);
+}
+
+std::string InstallationManager::DumpInstallationSlots() {
+ std::ostringstream out;
+ out << "size=";
+ const int kBufSize = 50;
+ char buf_num[kBufSize];
+ SbStringFormatF(buf_num, kBufSize, "%d",
+ installation_store_.installations_size());
+ out << buf_num;
+
+ out << " roll_forward_to_installation=";
+ SbStringFormatF(buf_num, kBufSize, "%d",
+ installation_store_.roll_forward_to_installation());
+ out << buf_num;
+ out << ";";
+ for (int i = 0; i < installation_store_.installations_size(); i++) {
+ out << " installation_";
+ SbStringFormatF(buf_num, kBufSize, "%d", i);
+ out << buf_num;
+ out << " is_successful=";
+ if (installation_store_.installations(i).is_successful()) {
+ out << "true";
+ } else {
+ out << "false";
+ }
+
+ out << " num_tries_left=";
+ SbStringFormatF(buf_num, kBufSize, "%d",
+ installation_store_.installations(i).num_tries_left());
+ out << buf_num;
+
+ out << " priority=";
+ SbStringFormatF(buf_num, kBufSize, "%d",
+ installation_store_.installations(i).priority());
+ out << buf_num;
+ out << ";";
+ }
+ return out.str();
+}
+
+int InstallationManager::GetInstallationStatus(int installation_index) {
+ if (!initialized_) {
+ SB_LOG(ERROR) << "GetInstallationStatus: not initialized";
+ return IM_INSTALLATION_STATUS_ERROR;
+ }
+ if (!IsValidIndex(installation_index)) {
+ SB_LOG(ERROR) << "GetInstallationStatus: invalid index: "
+ << installation_index;
+ return IM_INSTALLATION_STATUS_ERROR;
+ }
+ return installation_store_.installations(installation_index).is_successful();
+}
+
+int InstallationManager::GetInstallationNumTriesLeft(int installation_index) {
+ if (!initialized_) {
+ SB_LOG(ERROR) << "GetInstallationNumTriesLeft: not initialized";
+ return IM_ERROR;
+ }
+
+ if (!IsValidIndex(installation_index)) {
+ SB_LOG(ERROR) << "GetInstallationNumTriesLeft: invalid index: "
+ << installation_index;
+ return IM_ERROR;
+ }
+ return installation_store_.installations(installation_index).num_tries_left();
+}
+
+int InstallationManager::DecrementInstallationNumTries(int installation_index) {
+ if (!initialized_) {
+ SB_LOG(ERROR) << "DecrementInstallationNumTries: not initialized";
+ return IM_ERROR;
+ }
+ if (!IsValidIndex(installation_index)) {
+ SB_LOG(ERROR) << "DecrementInstallationNumTries: invalid index: "
+ << installation_index;
+ return IM_ERROR;
+ }
+
+ int num_tries_left =
+ installation_store_.installations(installation_index).num_tries_left();
+ if (num_tries_left <= 0) {
+ return IM_ERROR;
+ }
+ installation_store_.mutable_installations(installation_index)
+ ->set_num_tries_left(--num_tries_left);
+
+ if (!SaveInstallationStore()) {
+ SB_LOG(ERROR) << "DecrementInstallationNumTries: failed to save store";
+ return IM_ERROR;
+ }
+ return IM_SUCCESS;
+}
+
+//
+// Revert to a previous successful installation and make it
+// the highest priority. The current installation becomes the
+// lowest priority.
+//
+// high [-] [x]
+// [ ] [ ]
+// [x] => [ ]
+// low [ ] [-]
+//
+int InstallationManager::RevertToSuccessfulInstallation() {
+ if (!initialized_) {
+ SB_LOG(ERROR) << "RevertToSuccessfulInstallation: not initialized";
+ return IM_ERROR;
+ }
+ int fallback_priority = lowest_priority_;
+ int fallback_installation = -1;
+
+ SB_DLOG(INFO) << "RevertToSuccessfulInstallation: Start "
+ << DumpInstallationSlots();
+ // Find the highest priority successful installation for fallback.
+ for (int i = 0; i < installation_store_.installations().size(); i++) {
+ int priority = installation_store_.installations(i).priority();
+ if (installation_store_.installations(i).is_successful() &&
+ priority > highest_priority_ && priority <= fallback_priority) {
+ fallback_priority = priority;
+ fallback_installation = i;
+ SB_DLOG(INFO) << "fallback_installation= " << fallback_installation;
+ }
+ }
+
+ if (fallback_installation == -1) {
+ SB_LOG(ERROR) << "RevertToSuccessfulInstallation: Unable to find fallback "
+ "installation";
+ return IM_ERROR;
+ }
+
+ // Shift up all the priorities below the fallback installation up.
+ ShiftPrioritiesInRange(fallback_priority, lowest_priority_,
+ -1 /* shift up -1 */);
+
+ // Disable current installation.
+ installation_store_.mutable_installations(current_installation_)
+ ->set_priority(lowest_priority_);
+
+ // Move the current installation at the bottom.
+ installation_store_.mutable_installations(current_installation_)
+ ->set_is_successful(false);
+
+ // Change current installation.
+ installation_store_.mutable_installations(fallback_installation)
+ ->set_priority(highest_priority_);
+ current_installation_ = fallback_installation;
+
+ SB_DLOG(INFO) << "RevertToSuccessfulInstallation: End "
+ << DumpInstallationSlots();
+
+ if (SaveInstallationStore()) {
+ return fallback_installation;
+ }
+ return IM_ERROR;
+}
+
+//
+// Roll forward to a new installation and make it
+// the new highest priority installation.
+//
+// high [ ] [x]
+// [ ] [ ]
+// [x] => [ ]
+// low [ ] [ ]
+//
+int InstallationManager::RollForwardIfNeeded() {
+ if (!initialized_) {
+ SB_LOG(ERROR) << "RollForwardIfNeeded: not initialized";
+ return IM_ERROR;
+ }
+ // Check if we need to roll_forward to new slot.
+ int new_installation = installation_store_.roll_forward_to_installation();
+ if (new_installation == -1) {
+ // No need to roll forward.
+ return IM_SUCCESS;
+ }
+ if (!IsValidIndex(new_installation)) {
+ SB_LOG(ERROR) << "RollForwardIfNeeded: invalid new_installation="
+ << new_installation;
+ return IM_ERROR;
+ }
+ SB_DLOG(INFO) << "RollForwardIfNeeded: new_installation=" << new_installation;
+
+ // Save old priority.
+ int new_installation_old_prority =
+ installation_store_.installations(new_installation).priority();
+
+ SB_DLOG(INFO) << "RollForwardIfNeeded: new_installation_old_priority="
+ << new_installation_old_prority;
+
+ // Lower priorities of all jumped over installations.
+ ShiftPrioritiesInRange(highest_priority_, new_installation_old_prority,
+ 1 /* shift down +1 */);
+
+ // The new installation will be set to the highest priority.
+ installation_store_.mutable_installations(new_installation)
+ ->set_priority(highest_priority_);
+
+ // Reset the roll forward index.
+ installation_store_.set_roll_forward_to_installation(-1);
+ current_installation_ = new_installation;
+
+ SB_DLOG(INFO) << "RollForwardIfNeeded: " << DumpInstallationSlots();
+ return SaveInstallationStore() ? IM_SUCCESS : IM_ERROR;
+}
+
+// Shift the priority in the inclusive range either up or down based
+// on the |direction_up" flag.
+void InstallationManager::ShiftPrioritiesInRange(int high_priority,
+ int low_priority,
+ int shift_amount) {
+ for (int i = 0; i < installation_store_.installations().size(); i++) {
+ int priority = installation_store_.installations(i).priority();
+ if (priority >= high_priority && priority <= low_priority) {
+ installation_store_.mutable_installations(i)->set_priority(priority +
+ shift_amount);
+ SB_DLOG(INFO) << "ShiftPrioritiesInRange i=" << i << " priority_new"
+ << priority;
+ }
+ }
+}
+
+int InstallationManager::GetInstallationPath(int installation_index,
+ char* path,
+ int path_length) {
+ if (!initialized_) {
+ SB_LOG(ERROR) << "GetInstallationPath: not initialized";
+ return IM_ERROR;
+ }
+ return GetInstallationPathInternal(installation_index, path, path_length)
+ ? IM_SUCCESS
+ : IM_ERROR;
+}
+
+int InstallationManager::GetCurrentInstallationIndex() {
+ if (!initialized_) {
+ SB_LOG(ERROR) << "GetCurrentInstallationIndex: not initialized";
+ return IM_ERROR;
+ }
+ return current_installation_;
+}
+
+void InstallationManager::LogLastSystemError(const char* msg) {
+ const int kErrorMessageBufferSize = 256;
+ char msgbuf[kErrorMessageBufferSize];
+ SbSystemError error_code = SbSystemGetLastError();
+ if (SbSystemGetErrorString(error_code, msgbuf, kErrorMessageBufferSize) > 0) {
+ SB_LOG(ERROR) << msg << ": " << msgbuf;
+ }
+}
+
+int InstallationManager::FindCurrentInstallationIndex() {
+ int highest_priority_index = -1;
+ for (int i = 0; i < installation_store_.installations_size(); i++) {
+ if (highest_priority_ == installation_store_.installations(i).priority()) {
+ highest_priority_index = i;
+ break;
+ }
+ }
+
+ return highest_priority_index;
+}
+
+int InstallationManager::MarkInstallationSuccessful(int installation_index) {
+ if (!initialized_) {
+ SB_LOG(ERROR) << "MarkInstallationSuccessful: not initialized";
+ return IM_ERROR;
+ }
+ if (!IsValidIndex(installation_index)) {
+ SB_LOG(ERROR) << "MarkInstallationSuccessful: invalid index"
+ << installation_index;
+ return IM_ERROR;
+ }
+ if (!installation_store_.installations(installation_index).is_successful()) {
+ installation_store_.mutable_installations(installation_index)
+ ->set_is_successful(true);
+ return SaveInstallationStore() ? IM_SUCCESS : IM_ERROR;
+ }
+ return IM_SUCCESS;
+}
+
+int InstallationManager::SelectNewInstallationIndex() {
+ if (!initialized_) {
+ SB_LOG(ERROR) << "SelectNewInstallationIndex: not initialized";
+ return IM_ERROR;
+ }
+
+ int priority = highest_priority_;
+ int new_installation_index = -1;
+
+ // If we have more than 2 slots the 0 index slot is always the system image.
+ // We would ignore the 0 slot in that case.
+ int start = max_num_installations_ > 2 ? 1 : 0;
+
+ // Find the lowest priority installation that we can use.
+ for (int i = start; i < installation_store_.installations().size(); i++) {
+ if (priority < installation_store_.installations(i).priority()) {
+ new_installation_index = i;
+ priority = installation_store_.installations(i).priority();
+ SB_DLOG(INFO) << "SelectNewInstallationIndex: lowest_priority_index= "
+ << new_installation_index;
+ }
+ }
+
+ if (new_installation_index != -1) {
+ installation_store_.mutable_installations(new_installation_index)
+ ->set_is_successful(false);
+ installation_store_.mutable_installations(new_installation_index)
+ ->set_num_tries_left(IM_MAX_NUM_TRIES);
+
+ if (!SaveInstallationStore()) {
+ SB_LOG(ERROR) << "SelectNewInstallationIndex: failed to store";
+ return IM_ERROR;
+ }
+
+ SB_DLOG(INFO) << "SelectNewInstallationIndex: " << DumpInstallationSlots();
+ return new_installation_index;
+ }
+ return IM_ERROR;
+}
+
+int InstallationManager::RequestRollForwardToInstallation(
+ int installation_index) {
+ if (!initialized_) {
+ SB_LOG(ERROR) << "RequestRollForwardToInstallation: not initialized";
+ return IM_ERROR;
+ }
+ if (!IsValidIndex(installation_index)) {
+ SB_LOG(ERROR) << "RequestRollForwardToInstallation: invalid index"
+ << installation_index;
+ return IM_ERROR;
+ }
+ installation_store_.set_roll_forward_to_installation(installation_index);
+ return SaveInstallationStore() ? IM_SUCCESS : IM_ERROR;
+}
+
+bool InstallationManager::SaveInstallationStore() {
+ ValidatePriorities();
+ char buf[IM_MAX_INSTALLATION_STORE_SIZE];
+ if (IM_MAX_INSTALLATION_STORE_SIZE < installation_store_.ByteSize()) {
+ SB_LOG(ERROR) << "SaveInstallationStore: Data too large"
+ << installation_store_.ByteSize();
+ return false;
+ }
+ installation_store_.SerializeToArray(buf, installation_store_.ByteSize());
+
+#if SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION
+ if (!SbFileAtomicReplace(store_path_.c_str(), buf,
+ installation_store_.ByteSize())) {
+ SB_LOG(ERROR)
+ << "SaveInstallationStore: Failed to store installation store: "
+ << store_path_;
+ return false;
+ }
+ SB_DLOG(INFO) << "SaveInstallationStore successful";
+ return true;
+
+#else
+ SB_NOTREACHED()
+ << "SbFileAtomicReplace is not available before starboard version "
+ << SB_FILE_ATOMIC_REPLACE_VERSION;
+ return false;
+#endif
+}
+
+bool InstallationManager::InitInstallationStorePath() {
+ std::vector<char> storage_dir(kSbFileMaxPath);
+#if SB_API_VERSION >= SB_STORAGE_PATH_VERSION
+ if (!SbSystemGetPath(kSbSystemPathStorageDirectory, storage_dir.data(),
+ kSbFileMaxPath)) {
+ SB_LOG(ERROR) << "InitInstallationStorePath: Failed to get "
+ "kSbSystemPathStorageDirectory";
+ return false;
+ }
+#else
+ SB_NOTREACHED() << "InitInstallationStorePath: kSbSystemPathStorageDirectory "
+ "is not available before "
+ "starboard version "
+ << SB_STORAGE_PATH_VERSION;
+ return false;
+
+#endif
+ storage_dir_ = storage_dir.data();
+ store_path_ = storage_dir.data();
+ store_path_ += kSbFileSepString;
+ store_path_ += IM_STORE_FILE_NAME;
+
+ if (max_num_installations_ > 2) {
+ std::vector<char> content_dir(kSbFileMaxPath);
+ if (!SbSystemGetPath(kSbSystemPathContentDirectory, content_dir.data(),
+ kSbFileMaxPath)) {
+ return false;
+ }
+ content_dir_ = content_dir.data();
+ }
+ return true;
+}
+
+bool InstallationManager::IsValidIndex(int index) {
+ return index >= 0 && index < max_num_installations_;
+}
+
+void InstallationManager::ValidatePriorities() {
+ std::set<int> priorities;
+ for (int i = 0; i < max_num_installations_; i++) {
+ priorities.insert(installation_store_.installations(i).priority());
+ }
+ for (int i = 0; i < max_num_installations_; i++) {
+ SB_DCHECK(priorities.find(i) != priorities.end());
+ }
+ SB_DCHECK(priorities.size() == max_num_installations_);
+}
+
+bool InstallationManager::LoadInstallationStore() {
+ SbFile file;
+
+ file = SbFileOpen(store_path_.c_str(), kSbFileOpenOnly | kSbFileRead, NULL,
+ NULL);
+ if (!file) {
+ SB_LOG(WARNING) << "Failed to open file: " << store_path_;
+ return false;
+ }
+
+ char buf[IM_MAX_INSTALLATION_STORE_SIZE];
+ int count = SbFileReadAll(file, buf, IM_MAX_INSTALLATION_STORE_SIZE);
+ SB_DLOG(INFO) << "SbFileReadAll: count=" << count;
+ if (count == -1) {
+ LogLastSystemError("SbFileReadAll failed");
+ return false;
+ }
+ if (!installation_store_.ParseFromArray(buf, count)) {
+ SB_LOG(ERROR) << "LoadInstallationStore: Unable to parse storage";
+ return false;
+ }
+ SbFileClose(file);
+ return true;
+}
+
+bool InstallationManager::GetInstallationPathInternal(int installation_index,
+ char* path,
+ int path_length) {
+ if (!IsValidIndex(installation_index)) {
+ SB_LOG(ERROR) << "GetInstallationPath: invalid index" << installation_index;
+ return false;
+ }
+ if (!path) {
+ SB_LOG(ERROR) << "GetInstallationPath: path is null";
+ return false;
+ }
+ // When more than 2 slots are availabe the installation 0 slot is
+ // located under the content directory.
+ if (installation_index == 0 && max_num_installations_ > 2) {
+ SbStringFormatF(path, path_length, "%s%s%s%s%s", content_dir_.c_str(),
+ kSbFileSepString, "app", kSbFileSepString, "cobalt");
+ } else {
+ SbStringFormatF(path, path_length, "%s%s%s%d", storage_dir_.c_str(),
+ kSbFileSepString, "installation_", installation_index);
+ }
+
+ return true;
+}
+
+bool InstallationManager::CreateInstallationDirs() {
+ std::vector<char> path(kSbFileMaxPath);
+ for (int i = 0; i < max_num_installations_; i++) {
+ // The index 0 slot when more than 2 slots are available is
+ // under the content directory.
+ if (i == 0 && max_num_installations_ > 2) {
+ continue;
+ }
+ if (!GetInstallationPathInternal(i, path.data(), kSbFileMaxPath)) {
+ return false;
+ }
+ if (!SbDirectoryCreate(path.data())) {
+ return false;
+ }
+ }
+ return true;
+}
+
+} // namespace installation_manager
+} // namespace loader_app
+} // namespace starboard
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+starboard::scoped_ptr<
+ starboard::loader_app::installation_manager::InstallationManager>
+ g_istallation_manager_;
+
+// Global Installation Manager Mutex.
+SB_ONCE_INITIALIZE_FUNCTION(starboard::Mutex, GetImMutex);
+
+int ImInitialize(int max_num_installations) {
+ starboard::ScopedLock lock(*GetImMutex());
+ if (g_istallation_manager_.get() == NULL) {
+ g_istallation_manager_.reset(
+ new starboard::loader_app::installation_manager::InstallationManager(
+ max_num_installations));
+ }
+ return g_istallation_manager_->Initialize();
+}
+
+void ImUninitialize() {
+ starboard::ScopedLock lock(*GetImMutex());
+ g_istallation_manager_.reset(NULL);
+}
+
+int ImGetInstallationStatus(int installation_index) {
+ starboard::ScopedLock lock(*GetImMutex());
+ return g_istallation_manager_->GetInstallationStatus(installation_index);
+}
+
+int ImGetInstallationNumTriesLeft(int installation_index) {
+ starboard::ScopedLock lock(*GetImMutex());
+ return g_istallation_manager_->GetInstallationNumTriesLeft(
+ installation_index);
+}
+
+int ImDecrementInstallationNumTries(int installation_index) {
+ starboard::ScopedLock lock(*GetImMutex());
+ return g_istallation_manager_->DecrementInstallationNumTries(
+ installation_index);
+}
+
+int ImGetCurrentInstallationIndex() {
+ starboard::ScopedLock lock(*GetImMutex());
+ return g_istallation_manager_->GetCurrentInstallationIndex();
+}
+
+int ImSelectNewInstallationIndex() {
+ starboard::ScopedLock lock(*GetImMutex());
+ return g_istallation_manager_->SelectNewInstallationIndex();
+}
+
+int ImGetInstallationPath(int installation_index, char* path, int path_length) {
+ starboard::ScopedLock lock(*GetImMutex());
+ return g_istallation_manager_->GetInstallationPath(installation_index, path,
+ path_length);
+}
+
+int ImMarkInstallationSuccessful(int installation_index) {
+ starboard::ScopedLock lock(*GetImMutex());
+ return g_istallation_manager_->MarkInstallationSuccessful(installation_index);
+}
+
+int ImRollForwardIfNeeded() {
+ starboard::ScopedLock lock(*GetImMutex());
+ return g_istallation_manager_->RollForwardIfNeeded();
+}
+
+int ImRevertToSuccessfulInstallation() {
+ starboard::ScopedLock lock(*GetImMutex());
+ return g_istallation_manager_->RevertToSuccessfulInstallation();
+}
+
+int ImRequestRollForwardToInstallation(int installation_index) {
+ starboard::ScopedLock lock(*GetImMutex());
+ return g_istallation_manager_->RequestRollForwardToInstallation(
+ installation_index);
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/src/starboard/loader_app/installation_manager.gyp b/src/starboard/loader_app/installation_manager.gyp
new file mode 100644
index 0000000..bff8131
--- /dev/null
+++ b/src/starboard/loader_app/installation_manager.gyp
@@ -0,0 +1,71 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This files contains all targets that should be created by gyp_cobalt by
+# default.
+{
+ 'targets': [
+ {
+ 'target_name': 'installation_store_proto',
+ 'type': 'static_library',
+ 'sources': [
+ 'installation_store.pb.cc',
+ 'installation_store_store.pb.h',
+ ],
+ 'dependencies': [
+ '<(DEPTH)/third_party/protobuf/protobuf.gyp:protobuf_lite',
+ ],
+ },
+ {
+ 'target_name': 'installation_manager',
+ 'type': 'static_library',
+ 'sources': [
+ 'installation_manager.cc',
+ 'installation_manager.h',
+ ],
+ 'dependencies': [
+ ':installation_store_proto',
+ '<(DEPTH)/starboard/starboard.gyp:starboard',
+ ],
+ 'include_dirs': [
+ # Get protobuf headers from the chromium tree.
+ '<(DEPTH)/third_party/protobuf/src',
+ ],
+ },
+ {
+ 'target_name': 'installation_manager_test',
+ 'type': '<(gtest_target_type)',
+ 'sources': [
+ 'installation_manager_test.cc',
+ '<(DEPTH)/starboard/common/test_main.cc',
+ ],
+ 'dependencies': [
+ ':installation_manager',
+ '<(DEPTH)/testing/gmock.gyp:gmock',
+ '<(DEPTH)/testing/gtest.gyp:gtest',
+ ],
+ },
+ {
+ 'target_name': 'installation_manager_test_deploy',
+ 'type': 'none',
+ 'dependencies': [
+ 'installation_manager_test',
+ ],
+ 'variables': {
+ 'executable_name': 'installation_manager_test',
+ },
+ 'includes': [ '<(DEPTH)/starboard/build/deploy.gypi' ],
+ },
+ ],
+}
diff --git a/src/starboard/loader_app/installation_manager.h b/src/starboard/loader_app/installation_manager.h
new file mode 100644
index 0000000..30a27fb
--- /dev/null
+++ b/src/starboard/loader_app/installation_manager.h
@@ -0,0 +1,111 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_LOADER_APP_INSTALLATION_MANAGER_H_
+#define STARBOARD_LOADER_APP_INSTALLATION_MANAGER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// The installation is not successful.
+#define IM_INSTALLATION_STATUS_NOT_SUCCESS 0
+
+// The installation is successful.
+#define IM_INSTALLATION_STATUS_SUCCESS 1
+
+// An error occurd and the status of the installation is unknown.
+#define IM_INSTALLATION_STATUS_ERROR -1
+
+#define IM_SUCCESS 0
+#define IM_ERROR -1
+
+// The filename for the Installation Manager store file.
+#define IM_STORE_FILE_NAME "installation_store.pb"
+
+// The max size in bytes of the store file.
+#define IM_MAX_INSTALLATION_STORE_SIZE 1024 * 1024
+
+// The max number a tries per installation before it
+// is discarded if not successful.
+#define IM_MAX_NUM_TRIES 5
+
+// The Installation Manager API is thread safe and
+// can be used from any thread. Most calls would
+// trigger I/O operation unless the information is
+// already cached in memory.
+
+// Initializes the Installation Manager with the
+// max number of installations.
+// If the store doesn't exist an initial store would be
+// created. A subsequent call to |ImUninitialize| without
+// corresponding |ImUninitialize| will fail.
+// Returns IM_SUCCESS on success and IM_ERROR on error.
+int ImInitialize(int max_num_installations);
+
+// Uninitialize the Installation Manager.
+void ImUninitialize();
+
+// Gets the status of the |installation_index| installation.
+// Returns |IM_INSTALLATION_STATUS_SUCCESS| if the installation is successful.
+// Returns |IM_INSTALLATION_STATUS_NOT_SUCCESS| if the installation is not
+// successful. Returns |IM_INSTALLATION_STATUS_ERROR| on error.
+int ImGetInstallationStatus(int installation_index);
+
+// Returns the number of tries left for the |installation_index| installation.
+// Returns |IM_ERROR| on error.
+int ImGetInstallationNumTriesLeft(int installation_index);
+
+// Decrements the number of tries left for installation |installation_index|.
+// Returns IM_SUCCESS on success and IM_ERROR on error.
+int ImDecrementInstallationNumTries(int installation_index);
+
+// Retrieves the current installation index.
+// Returns |IM_ERROR| on error.
+int ImGetCurrentInstallationIndex();
+
+// Selects a new installation index and prepares the installation
+// slot for new installation use.
+// Returns |IM_ERROR| on error.
+int ImSelectNewInstallationIndex();
+
+// Retrieves the absolute installation path for the installation
+// |installation_index| in the buffer |path| with length |path_length|.
+// Returns IM_SUCCESS on success and IM_ERROR on error.
+int ImGetInstallationPath(int installation_index, char* path, int path_length);
+
+// Mark the installation |installation_index| as successful.
+// Returns IM_SUCCESS on success and IM_ERROR on error.
+int ImMarkInstallationSuccessful(int installation_index);
+
+// Rolls forward the installation slot requested to be used.
+// The operation makes it current installation.
+// Returns IM_SUCCESS on success and IM_ERROR on error.
+int ImRollForwardIfNeeded();
+
+// Revert to a previous successful installation.
+// Returns the installation to which it was reverted.
+// Returns |IM_ERROR| on error.
+int ImRevertToSuccessfulInstallation();
+
+// Request the installation at |installation_index| to be rolled
+// forward next time the Loader App tries to load the app.
+// Returns IM_SUCCESS on success and IM_ERROR on error.
+int ImRequestRollForwardToInstallation(int installation_index);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // STARBOARD_LOADER_APP_INSTALLATION_MANAGER_H_
diff --git a/src/starboard/loader_app/installation_manager_test.cc b/src/starboard/loader_app/installation_manager_test.cc
new file mode 100644
index 0000000..0d5f358
--- /dev/null
+++ b/src/starboard/loader_app/installation_manager_test.cc
@@ -0,0 +1,555 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/loader_app/installation_manager.h"
+
+#include <string>
+#include <vector>
+
+#include "starboard/configuration_constants.h"
+#include "starboard/loader_app/installation_store.pb.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if SB_API_VERSION >= SB_STORAGE_PATH_VERSION && \
+ SB_API_VERSION >= SB_FILE_ATOMIC_REPLACE_VERSION
+
+#define NUMBER_INSTALLS_PARAMS ::testing::Values(2, 3, 4, 5, 6)
+
+namespace starboard {
+namespace loader_app {
+namespace installation_manager {
+
+namespace {
+
+class InstallationManagerTest : public ::testing::TestWithParam<int> {
+ protected:
+ virtual void SetUp() {
+ std::vector<char> buf(kSbFileMaxPath);
+ storage_path_implemented_ = SbSystemGetPath(kSbSystemPathStorageDirectory,
+ buf.data(), kSbFileMaxPath);
+ // Short-circuit the tests if the kSbSystemPathStorageDirectory is not
+ // implemented.
+ if (!storage_path_implemented_) {
+ return;
+ }
+ storage_path_ = buf.data();
+ ASSERT_TRUE(!storage_path_.empty());
+ SbDirectoryCreate(storage_path_.c_str());
+
+ installation_store_path_ = storage_path_;
+ installation_store_path_ += kSbFileSepString;
+ installation_store_path_ += IM_STORE_FILE_NAME;
+ }
+
+ void SaveStorageState(
+ const cobalt::loader::InstallationStore& installation_store) {
+ char buf[IM_MAX_INSTALLATION_STORE_SIZE];
+ ASSERT_GT(IM_MAX_INSTALLATION_STORE_SIZE, installation_store.ByteSize());
+ installation_store.SerializeToArray(buf, installation_store.ByteSize());
+
+ ASSERT_TRUE(SbFileAtomicReplace(installation_store_path_.c_str(), buf,
+ installation_store.ByteSize()));
+ }
+
+ void ReadStorageState(cobalt::loader::InstallationStore* installation_store) {
+ SbFile file;
+
+ file = SbFileOpen(installation_store_path_.c_str(),
+ kSbFileOpenOnly | kSbFileRead, NULL, NULL);
+ ASSERT_TRUE(file);
+
+ char buf[IM_MAX_INSTALLATION_STORE_SIZE];
+ int count = SbFileReadAll(file, buf, IM_MAX_INSTALLATION_STORE_SIZE);
+ SB_DLOG(INFO) << "SbFileReadAll: count=" << count;
+ ASSERT_NE(-1, count);
+ ASSERT_TRUE(installation_store->ParseFromArray(buf, count));
+ SbFileClose(file);
+ }
+
+ // Roll forward to |index| installation in a |max_num_installations|
+ // configuration. The priorities at each corresponding index are provided in
+ // |setup_priorities|. After the transition the new priorities at each
+ // corresponding index should match |expected_priorities|.
+ void RollForwardHelper(int index,
+ int max_num_installations,
+ int* setup_priorities,
+ int* expected_priorities) {
+ cobalt::loader::InstallationStore installation_store;
+ int priority = 0;
+ for (int i = 0; i < max_num_installations; i++) {
+ installation_store.add_installations();
+ installation_store.mutable_installations(i)->set_is_successful(false);
+ installation_store.mutable_installations(i)->set_num_tries_left(
+ IM_MAX_NUM_TRIES);
+ installation_store.mutable_installations(i)->set_priority(
+ setup_priorities[i]);
+ }
+ installation_store.set_roll_forward_to_installation(-1);
+
+ SaveStorageState(installation_store);
+
+ ASSERT_EQ(IM_SUCCESS, ImInitialize(max_num_installations));
+ ASSERT_EQ(IM_SUCCESS, ImRequestRollForwardToInstallation(index));
+ ASSERT_EQ(IM_SUCCESS, ImRollForwardIfNeeded());
+ ASSERT_EQ(index, ImGetCurrentInstallationIndex());
+ ImUninitialize();
+
+ ReadStorageState(&installation_store);
+ for (int i = 0; i < max_num_installations; i++) {
+ ASSERT_EQ(expected_priorities[i],
+ installation_store.installations(i).priority());
+ }
+ }
+
+ // Revert to a previous successful installation in a |max_num_installations|
+ // configuration. After the installation is reverted the priorities at each
+ // corresponding index should match |expected_priorities|.
+ // The |expected_succeed| indicate whether the revert is expected to succeed.
+ // For example if there is no successful installation it is impossible to
+ // revert. The |priority_success_pairs| have initialization values for
+ // priority and is_success states for each corresponding installation.
+ template <size_t N>
+ void RevertHelper(int max_num_installations,
+ int (*priority_success_pairs)[N],
+ int* expected_priorities,
+ bool expected_succeed) {
+ cobalt::loader::InstallationStore installation_store;
+ int priority = 0;
+ for (int i = 0; i < max_num_installations; i++) {
+ installation_store.add_installations();
+ installation_store.mutable_installations(i)->set_priority(
+ priority_success_pairs[i][0]);
+ installation_store.mutable_installations(i)->set_is_successful(
+ priority_success_pairs[i][1]);
+ installation_store.mutable_installations(i)->set_num_tries_left(
+ IM_MAX_NUM_TRIES);
+ }
+ installation_store.set_roll_forward_to_installation(-1);
+
+ SaveStorageState(installation_store);
+
+ ASSERT_EQ(IM_SUCCESS, ImInitialize(max_num_installations));
+ int result = ImRevertToSuccessfulInstallation();
+ if (!expected_succeed) {
+ ASSERT_EQ(IM_ERROR, result);
+ }
+
+ if (expected_succeed) {
+ int index = ImGetCurrentInstallationIndex();
+ ASSERT_EQ(IM_INSTALLATION_STATUS_SUCCESS, ImGetInstallationStatus(index));
+ }
+
+ ImUninitialize();
+
+ if (expected_succeed) {
+ ReadStorageState(&installation_store);
+ for (int i = 0; i < max_num_installations; i++) {
+ ASSERT_EQ(expected_priorities[i],
+ installation_store.installations(i).priority());
+ }
+ }
+ }
+
+ virtual void TearDown() {
+ if (!storage_path_implemented_) {
+ return;
+ }
+ ImUninitialize();
+ SbDirectory dir = SbDirectoryOpen(storage_path_.c_str(), NULL);
+ std::vector<std::string> dir_;
+#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+ std::vector<char> dir_entry(kSbFileMaxName);
+
+ while (SbDirectoryGetNext(dir, dir_entry.data(), dir_entry.size())) {
+ std::string full_path = storage_path_;
+ full_path += kSbFileSepString;
+ full_path += dir_entry.data();
+ SbFileDelete(full_path.c_str());
+ }
+#else // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+ SbDirectoryEntry dir_entry;
+
+ while (SbDirectoryGetNext(dir, &dir_entry)) {
+ std::string full_path = storage_path_;
+ full_path += kSbFileSepString;
+ full_path += dir_entry.name;
+ SbFileDelete(full_path.c_str());
+ }
+#endif // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
+ SbDirectoryClose(dir);
+ SbFileDelete(storage_path_.c_str());
+ }
+
+ protected:
+ std::string storage_path_;
+ std::string installation_store_path_;
+ bool storage_path_implemented_;
+};
+
+} // namespace
+
+TEST_P(InstallationManagerTest, InitializeMultiple) {
+ if (!storage_path_implemented_) {
+ return;
+ }
+ ASSERT_EQ(IM_SUCCESS, ImInitialize(GetParam()));
+ ImUninitialize();
+ ASSERT_EQ(IM_SUCCESS, ImInitialize(GetParam()));
+}
+
+TEST_P(InstallationManagerTest, DefaultInstallationSuccessful) {
+ if (!storage_path_implemented_) {
+ return;
+ }
+ ASSERT_EQ(IM_SUCCESS, ImInitialize(GetParam()));
+ ASSERT_EQ(IM_INSTALLATION_STATUS_NOT_SUCCESS, ImGetInstallationStatus(0));
+}
+
+TEST_P(InstallationManagerTest, MarkInstallationSuccessful) {
+ if (!storage_path_implemented_) {
+ return;
+ }
+ ASSERT_EQ(IM_SUCCESS, ImInitialize(GetParam()));
+ ASSERT_EQ(IM_INSTALLATION_STATUS_NOT_SUCCESS, ImGetInstallationStatus(0));
+ ASSERT_EQ(IM_SUCCESS, ImMarkInstallationSuccessful(0));
+ ASSERT_EQ(IM_INSTALLATION_STATUS_SUCCESS, ImGetInstallationStatus(0));
+}
+
+TEST_P(InstallationManagerTest, DecrementInstallationNumTries) {
+ if (!storage_path_implemented_) {
+ return;
+ }
+ ASSERT_EQ(IM_SUCCESS, ImInitialize(GetParam()));
+ int max_num_tries = ImGetInstallationNumTriesLeft(0);
+ ASSERT_EQ(IM_SUCCESS, ImDecrementInstallationNumTries(0));
+ ASSERT_EQ(max_num_tries - 1, ImGetInstallationNumTriesLeft(0));
+ int num_tries = max_num_tries - 1;
+ while (num_tries--) {
+ ASSERT_EQ(IM_SUCCESS, ImDecrementInstallationNumTries(0));
+ ASSERT_EQ(num_tries, ImGetInstallationNumTriesLeft(0));
+ }
+ ASSERT_EQ(IM_ERROR, ImDecrementInstallationNumTries(0));
+}
+
+TEST_P(InstallationManagerTest, GetCurrentInstallationIndex) {
+ if (!storage_path_implemented_) {
+ return;
+ }
+ ASSERT_EQ(IM_SUCCESS, ImInitialize(GetParam()));
+ ASSERT_EQ(0, ImGetCurrentInstallationIndex());
+}
+
+TEST_P(InstallationManagerTest, SelectNewInstallationIndex) {
+ if (!storage_path_implemented_) {
+ return;
+ }
+ ASSERT_EQ(IM_SUCCESS, ImInitialize(GetParam()));
+ int index = ImSelectNewInstallationIndex();
+ if (GetParam() > 2) {
+ for (int i = 0; i < 10; i++) {
+ ASSERT_EQ(GetParam() > 2 ? GetParam() - 1 : 1, index);
+ }
+ }
+}
+
+TEST_P(InstallationManagerTest, GetInstallationPath) {
+ if (!storage_path_implemented_) {
+ return;
+ }
+ ASSERT_EQ(IM_SUCCESS, ImInitialize(GetParam()));
+ std::vector<char> buf0(kSbFileMaxPath);
+ ASSERT_EQ(IM_SUCCESS, ImGetInstallationPath(0, buf0.data(), kSbFileMaxPath));
+ // For 3 or more slots the 0 index one is under the content directory,
+ // which will not have the correct file path for a Cobalt binary when running
+ // a test.
+ if (GetParam() < 3) {
+ ASSERT_TRUE(SbFileExists(buf0.data()));
+ }
+ std::vector<char> buf1(kSbFileMaxPath);
+ ASSERT_EQ(IM_SUCCESS, ImGetInstallationPath(1, buf1.data(), kSbFileMaxPath));
+ ASSERT_TRUE(SbFileExists(buf1.data()));
+}
+
+TEST_P(InstallationManagerTest, RollForwardIfNeeded) {
+ if (!storage_path_implemented_) {
+ return;
+ }
+ ASSERT_EQ(IM_SUCCESS, ImInitialize(GetParam()));
+ ASSERT_EQ(IM_SUCCESS, ImRollForwardIfNeeded());
+ ASSERT_EQ(0, ImGetCurrentInstallationIndex());
+ ASSERT_EQ(IM_SUCCESS, ImRequestRollForwardToInstallation(1));
+ ASSERT_EQ(0, ImGetCurrentInstallationIndex());
+ ASSERT_EQ(IM_SUCCESS, ImRollForwardIfNeeded());
+ ASSERT_EQ(1, ImGetCurrentInstallationIndex());
+ if (GetParam() > 2) {
+ for (int i = 2; i < GetParam() - 1; i++) {
+ ASSERT_EQ(IM_SUCCESS, ImRequestRollForwardToInstallation(i));
+ ASSERT_EQ(i - 1, ImGetCurrentInstallationIndex());
+ ASSERT_EQ(IM_SUCCESS, ImRollForwardIfNeeded());
+ ASSERT_EQ(i, ImGetCurrentInstallationIndex());
+ }
+ }
+ for (int i = 0; i < 10; i++) {
+ int new_index = i % GetParam();
+ ASSERT_EQ(IM_SUCCESS, ImRequestRollForwardToInstallation(new_index));
+ ASSERT_EQ(IM_SUCCESS, ImRollForwardIfNeeded());
+ ASSERT_EQ(new_index, ImGetCurrentInstallationIndex());
+ }
+}
+
+TEST_P(InstallationManagerTest, RevertToSuccessfulInstallation) {
+ if (!storage_path_implemented_) {
+ return;
+ }
+ ASSERT_EQ(IM_SUCCESS, ImInitialize(GetParam()));
+ ASSERT_EQ(0, ImGetCurrentInstallationIndex());
+ ASSERT_EQ(IM_SUCCESS, ImMarkInstallationSuccessful(0));
+ ASSERT_EQ(IM_SUCCESS, ImRequestRollForwardToInstallation(1));
+ ASSERT_EQ(0, ImGetCurrentInstallationIndex());
+ ASSERT_EQ(IM_SUCCESS, ImRollForwardIfNeeded());
+ ASSERT_EQ(1, ImGetCurrentInstallationIndex());
+ ASSERT_EQ(IM_SUCCESS, ImMarkInstallationSuccessful(1));
+ ASSERT_EQ(1, ImGetCurrentInstallationIndex());
+ ASSERT_EQ(0, ImRevertToSuccessfulInstallation());
+ ASSERT_EQ(0, ImGetCurrentInstallationIndex());
+}
+
+TEST_F(InstallationManagerTest, InvalidInput) {
+ if (!storage_path_implemented_) {
+ return;
+ }
+ ASSERT_EQ(IM_SUCCESS, ImInitialize(3));
+ ASSERT_EQ(IM_INSTALLATION_STATUS_ERROR, ImGetInstallationStatus(10));
+ ASSERT_EQ(IM_SUCCESS, ImMarkInstallationSuccessful(0));
+ ASSERT_EQ(IM_INSTALLATION_STATUS_ERROR, ImGetInstallationStatus(-2));
+ ASSERT_EQ(IM_ERROR, ImRevertToSuccessfulInstallation());
+ ASSERT_EQ(IM_ERROR, ImMarkInstallationSuccessful(10));
+ ASSERT_EQ(IM_ERROR, ImMarkInstallationSuccessful(-2));
+ ASSERT_EQ(IM_ERROR, ImDecrementInstallationNumTries(10));
+ ASSERT_EQ(IM_ERROR, ImDecrementInstallationNumTries(-2));
+
+ std::vector<char> buf(kSbFileMaxPath);
+ ASSERT_EQ(IM_ERROR, ImGetInstallationPath(10, buf.data(), kSbFileMaxPath));
+ ASSERT_EQ(IM_ERROR, ImGetInstallationPath(-2, buf.data(), kSbFileMaxPath));
+ ASSERT_EQ(IM_ERROR, ImGetInstallationPath(-2, NULL, kSbFileMaxPath));
+}
+
+TEST_F(InstallationManagerTest, RollForwardMatrix20) {
+ if (!storage_path_implemented_) {
+ return;
+ }
+ int max_num_installations = 2;
+ int setup_priorities[2][2] = {
+ {0, 1}, {1, 0},
+ };
+
+ int expected_priorities[2][2] = {
+ {0, 1}, {0, 1},
+ };
+
+ for (int i = 0; i < 2; i++) {
+ SB_LOG(INFO) << "Testing Maxtrix20 expected_priorities at index: " << i;
+ RollForwardHelper(0, 2, setup_priorities[i], expected_priorities[i]);
+ }
+}
+
+TEST_F(InstallationManagerTest, RollForwardMatrix21) {
+ if (!storage_path_implemented_) {
+ return;
+ }
+ int max_num_installations = 2;
+ int setup_priorities[2][2] = {
+ {0, 1}, {1, 0},
+ };
+
+ int expected_priorities[2][2] = {
+ {1, 0}, {1, 0},
+ };
+
+ for (int i = 0; i < 2; i++) {
+ SB_LOG(INFO) << "Testing Maxtrix21 expected_priorities at index: " << i;
+ RollForwardHelper(1, 2, setup_priorities[i], expected_priorities[i]);
+ }
+}
+
+TEST_F(InstallationManagerTest, RollForwardMatrix30) {
+ if (!storage_path_implemented_) {
+ return;
+ }
+ int max_num_installations = 3;
+ int setup_priorities[6][3] = {
+ {0, 1, 2}, {0, 2, 1}, {1, 2, 0}, {1, 0, 2}, {2, 0, 1}, {2, 1, 0},
+ };
+
+ int expected_priorities[6][3] = {
+ {0, 1, 2}, {0, 2, 1}, {0, 2, 1}, {0, 1, 2}, {0, 1, 2}, {0, 2, 1},
+ };
+
+ for (int i = 0; i < 6; i++) {
+ SB_LOG(INFO) << "Testing Maxtrix30 expected_priorities at index: " << i;
+ RollForwardHelper(0, 3, setup_priorities[i], expected_priorities[i]);
+ }
+}
+
+TEST_F(InstallationManagerTest, RollForwardMatrix31) {
+ if (!storage_path_implemented_) {
+ return;
+ }
+ int max_num_installations = 3;
+ int setup_priorities[6][3] = {
+ {0, 1, 2}, {0, 2, 1}, {1, 2, 0}, {1, 0, 2}, {2, 0, 1}, {2, 1, 0},
+ };
+
+ int expected_priorities[6][3] = {
+ {1, 0, 2}, {1, 0, 2}, {2, 0, 1}, {1, 0, 2}, {2, 0, 1}, {2, 0, 1},
+ };
+
+ for (int i = 0; i < 6; i++) {
+ SB_LOG(INFO) << "Testing Maxtrix31 expected_priorities at index: " << i;
+ RollForwardHelper(1, 3, setup_priorities[i], expected_priorities[i]);
+ }
+}
+
+TEST_F(InstallationManagerTest, RollForwardMatrix32) {
+ if (!storage_path_implemented_) {
+ return;
+ }
+ int max_num_installations = 3;
+ int setup_priorities[6][3] = {
+ {0, 1, 2}, {0, 2, 1}, {1, 2, 0}, {1, 0, 2}, {2, 0, 1}, {2, 1, 0},
+ };
+
+ int expected_priorities[6][3] = {
+ {1, 2, 0}, {1, 2, 0}, {1, 2, 0}, {2, 1, 0}, {2, 1, 0}, {2, 1, 0},
+ };
+ for (int i = 0; i < 6; i++) {
+ SB_LOG(INFO) << "Testing Maxtrix32 expected_priorities at index: " << i;
+ RollForwardHelper(2, 3, setup_priorities[i], expected_priorities[i]);
+ }
+}
+
+TEST_F(InstallationManagerTest, RevertMatrix2) {
+ if (!storage_path_implemented_) {
+ return;
+ }
+ int max_num_installations = 2;
+ // List of 2 index pairs of (priority, is_success) for which the revert would
+ // fail.
+ int priority_success_pairs1[4][2][2] = {
+ {{0, 1}, {1, 0}}, {{0, 0}, {1, 0}}, {{1, 0}, {0, 1}}, {{1, 0}, {0, 0}},
+ };
+
+ // List of 2 index pairs of (priority, is_success) for which the revert would
+ // succeed.
+ int priority_success_pairs2[4][2][2] = {
+ {{0, 0}, {1, 1}}, {{1, 1}, {0, 0}}, {{0, 1}, {1, 1}}, {{1, 1}, {0, 1}},
+ };
+
+ int expected_priorities[4][2] = {
+ {1, 0}, {0, 1}, {1, 0}, {0, 1},
+ };
+
+ for (int i = 0; i < 4; i++) {
+ SB_LOG(INFO) << "Testing RevertMaxtrix2 expected_priorities at index: "
+ << i;
+ RevertHelper(2, priority_success_pairs1[i], NULL, false);
+ }
+ for (int i = 0; i < 4; i++) {
+ SB_LOG(INFO) << "Testing RevertMaxtrix2 expected_priorities at index: "
+ << i;
+ RevertHelper(2, priority_success_pairs2[i], expected_priorities[i], true);
+ }
+}
+
+TEST_F(InstallationManagerTest, RevertMatrix3) {
+ if (!storage_path_implemented_) {
+ return;
+ }
+ int max_num_installations = 3;
+
+ // List of 3 index pairs of (priority, is_success) for which the revert would
+ // fail.
+ int priority_success_pairs1[12][3][2] = {
+ {{0, 0}, {1, 0}, {2, 0}}, {{0, 1}, {1, 0}, {2, 0}},
+
+ {{0, 0}, {2, 0}, {1, 0}}, {{0, 1}, {2, 0}, {1, 0}},
+
+ {{1, 0}, {2, 0}, {0, 0}}, {{1, 0}, {2, 0}, {0, 1}},
+
+ {{1, 0}, {0, 0}, {2, 0}}, {{1, 0}, {0, 1}, {2, 0}},
+
+ {{2, 0}, {0, 0}, {1, 0}}, {{2, 0}, {0, 1}, {1, 0}},
+
+ {{2, 0}, {1, 0}, {0, 0}}, {{2, 0}, {1, 0}, {0, 1}},
+ };
+
+ // List of 3 index pairs of (priority, is_success) for which the revert would
+ // succeed.
+ int priority_success_pairs2[36][3][2] = {
+ {{0, 0}, {1, 0}, {2, 1}}, {{0, 0}, {1, 1}, {2, 0}},
+ {{0, 0}, {1, 1}, {2, 1}}, {{0, 1}, {1, 1}, {2, 0}},
+ {{0, 1}, {1, 1}, {2, 1}}, {{0, 1}, {1, 0}, {2, 1}},
+
+ {{0, 0}, {2, 0}, {1, 1}}, {{0, 0}, {2, 1}, {1, 0}},
+ {{0, 0}, {2, 1}, {1, 1}}, {{0, 1}, {2, 1}, {1, 0}},
+ {{0, 1}, {2, 0}, {1, 1}}, {{0, 1}, {2, 1}, {1, 1}},
+
+ {{1, 0}, {2, 1}, {0, 0}}, {{1, 1}, {2, 0}, {0, 0}},
+ {{1, 0}, {2, 1}, {0, 1}}, {{1, 1}, {2, 1}, {0, 0}},
+ {{1, 1}, {2, 0}, {0, 1}}, {{1, 1}, {2, 1}, {0, 1}},
+
+ {{1, 0}, {0, 0}, {2, 1}}, {{1, 1}, {0, 0}, {2, 0}},
+ {{1, 0}, {0, 1}, {2, 1}}, {{1, 1}, {0, 1}, {2, 0}},
+ {{1, 1}, {0, 0}, {2, 1}}, {{1, 1}, {0, 1}, {2, 1}},
+
+ {{2, 0}, {0, 0}, {1, 1}}, {{2, 1}, {0, 0}, {1, 0}},
+ {{2, 0}, {0, 1}, {1, 1}}, {{2, 1}, {0, 1}, {1, 0}},
+ {{2, 1}, {0, 0}, {1, 1}}, {{2, 1}, {0, 1}, {1, 1}},
+
+ {{2, 0}, {1, 1}, {0, 0}}, {{2, 1}, {1, 0}, {0, 0}},
+ {{2, 0}, {1, 1}, {0, 1}}, {{2, 1}, {1, 1}, {0, 0}},
+ {{2, 1}, {1, 0}, {0, 1}}, {{2, 1}, {1, 1}, {0, 1}},
+ };
+
+ int expected_priorities[36][3] = {
+ {2, 1, 0}, {2, 0, 1}, {2, 0, 1}, {2, 0, 1}, {2, 0, 1}, {2, 1, 0},
+ {2, 1, 0}, {2, 0, 1}, {2, 1, 0}, {2, 0, 1}, {2, 1, 0}, {2, 1, 0},
+ {1, 0, 2}, {0, 1, 2}, {1, 0, 2}, {0, 1, 2}, {0, 1, 2}, {0, 1, 2},
+ {1, 2, 0}, {0, 2, 1}, {1, 2, 0}, {0, 2, 1}, {0, 2, 1}, {0, 2, 1},
+ {1, 2, 0}, {0, 2, 1}, {1, 2, 0}, {0, 2, 1}, {1, 2, 0}, {1, 2, 0},
+ {1, 0, 2}, {0, 1, 2}, {1, 0, 2}, {1, 0, 2}, {0, 1, 2}, {1, 0, 2},
+ };
+
+ for (int i = 0; i < 12; i++) {
+ SB_LOG(INFO) << "Testing RevertMaxtrix3 expected_priorities at index: "
+ << i;
+ RevertHelper(3, priority_success_pairs1[i], NULL, false);
+ }
+
+ for (int i = 0; i < 36; i++) {
+ SB_LOG(INFO) << "Testing RevertMaxtrix3 expected_priorities at index: "
+ << i;
+ RevertHelper(3, priority_success_pairs2[i], expected_priorities[i], true);
+ }
+}
+INSTANTIATE_TEST_CASE_P(NumberOfMaxInstallations,
+ InstallationManagerTest,
+ NUMBER_INSTALLS_PARAMS);
+
+} // namespace installation_manager
+} // namespace loader_app
+} // namespace starboard
+
+#endif // SB_API_VERSION >= SB_STORAGE_PATH_VERSION && SB_API_VERSION >=
+ // SB_FILE_ATOMIC_REPLACE_VERSION
diff --git a/src/starboard/loader_app/installation_store.pb.cc b/src/starboard/loader_app/installation_store.pb.cc
new file mode 100644
index 0000000..7d6e3ae
--- /dev/null
+++ b/src/starboard/loader_app/installation_store.pb.cc
@@ -0,0 +1,660 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: installation_store.proto
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include "installation_store.pb.h"
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/port.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/stubs/starboard_poem.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+// @@protoc_insertion_point(includes)
+
+namespace cobalt {
+namespace loader {
+
+void protobuf_ShutdownFile_installation_5fstore_2eproto() {
+ delete Installation::default_instance_;
+ delete InstallationStore::default_instance_;
+}
+
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+void protobuf_AddDesc_installation_5fstore_2eproto_impl() {
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+#else
+void protobuf_AddDesc_installation_5fstore_2eproto() {
+ static bool already_here = false;
+ if (already_here) return;
+ already_here = true;
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+#endif
+ Installation::default_instance_ = new Installation();
+ InstallationStore::default_instance_ = new InstallationStore();
+ Installation::default_instance_->InitAsDefaultInstance();
+ InstallationStore::default_instance_->InitAsDefaultInstance();
+ ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_installation_5fstore_2eproto);
+}
+
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AddDesc_installation_5fstore_2eproto_once_);
+void protobuf_AddDesc_installation_5fstore_2eproto() {
+ ::google::protobuf::GoogleOnceInit(&protobuf_AddDesc_installation_5fstore_2eproto_once_,
+ &protobuf_AddDesc_installation_5fstore_2eproto_impl);
+}
+#else
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_installation_5fstore_2eproto {
+ StaticDescriptorInitializer_installation_5fstore_2eproto() {
+ protobuf_AddDesc_installation_5fstore_2eproto();
+ }
+} static_descriptor_initializer_installation_5fstore_2eproto_;
+#endif
+
+namespace {
+
+static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;
+GOOGLE_ATTRIBUTE_NOINLINE static void MergeFromFail(int line) {
+ GOOGLE_CHECK(false) << __FILE__ << ":" << line;
+}
+
+} // namespace
+
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Installation::kIsSuccessfulFieldNumber;
+const int Installation::kNumTriesLeftFieldNumber;
+const int Installation::kPriorityFieldNumber;
+#endif // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Installation::Installation()
+ : ::google::protobuf::MessageLite(), _arena_ptr_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:cobalt.loader.Installation)
+}
+
+void Installation::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+}
+
+Installation::Installation(const Installation& from)
+ : ::google::protobuf::MessageLite(),
+ _arena_ptr_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:cobalt.loader.Installation)
+}
+
+void Installation::SharedCtor() {
+ _is_default_instance_ = false;
+ _cached_size_ = 0;
+ is_successful_ = false;
+ num_tries_left_ = 0;
+ priority_ = 0;
+}
+
+Installation::~Installation() {
+ // @@protoc_insertion_point(destructor:cobalt.loader.Installation)
+ SharedDtor();
+}
+
+void Installation::SharedDtor() {
+ #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+ if (this != &default_instance()) {
+ #else
+ if (this != default_instance_) {
+ #endif
+ }
+}
+
+void Installation::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const Installation& Installation::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+ protobuf_AddDesc_installation_5fstore_2eproto();
+#else
+ if (default_instance_ == NULL) protobuf_AddDesc_installation_5fstore_2eproto();
+#endif
+ return *default_instance_;
+}
+
+Installation* Installation::default_instance_ = NULL;
+
+Installation* Installation::New(::google::protobuf::Arena* arena) const {
+ Installation* n = new Installation;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void Installation::Clear() {
+// @@protoc_insertion_point(message_clear_start:cobalt.loader.Installation)
+#if defined(__clang__)
+#define ZR_HELPER_(f) \
+ _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Winvalid-offsetof\"") \
+ __builtin_offsetof(Installation, f) \
+ _Pragma("clang diagnostic pop")
+#else
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+ &reinterpret_cast<Installation*>(16)->f)
+#endif
+
+#define ZR_(first, last) do {\
+ ::memset(&first, 0,\
+ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
+
+ ZR_(is_successful_, priority_);
+
+#undef ZR_HELPER_
+#undef ZR_
+
+}
+
+bool Installation::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:cobalt.loader.Installation)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional bool is_successful = 1;
+ case 1: {
+ if (tag == 8) {
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &is_successful_)));
+
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(16)) goto parse_num_tries_left;
+ break;
+ }
+
+ // optional int32 num_tries_left = 2;
+ case 2: {
+ if (tag == 16) {
+ parse_num_tries_left:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, &num_tries_left_)));
+
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(24)) goto parse_priority;
+ break;
+ }
+
+ // optional int32 priority = 3;
+ case 3: {
+ if (tag == 24) {
+ parse_priority:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, &priority_)));
+
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:cobalt.loader.Installation)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:cobalt.loader.Installation)
+ return false;
+#undef DO_
+}
+
+void Installation::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:cobalt.loader.Installation)
+ // optional bool is_successful = 1;
+ if (this->is_successful() != 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteBool(1, this->is_successful(), output);
+ }
+
+ // optional int32 num_tries_left = 2;
+ if (this->num_tries_left() != 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->num_tries_left(), output);
+ }
+
+ // optional int32 priority = 3;
+ if (this->priority() != 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteInt32(3, this->priority(), output);
+ }
+
+ // @@protoc_insertion_point(serialize_end:cobalt.loader.Installation)
+}
+
+int Installation::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:cobalt.loader.Installation)
+ int total_size = 0;
+
+ // optional bool is_successful = 1;
+ if (this->is_successful() != 0) {
+ total_size += 1 + 1;
+ }
+
+ // optional int32 num_tries_left = 2;
+ if (this->num_tries_left() != 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::Int32Size(
+ this->num_tries_left());
+ }
+
+ // optional int32 priority = 3;
+ if (this->priority() != 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::Int32Size(
+ this->priority());
+ }
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void Installation::CheckTypeAndMergeFrom(
+ const ::google::protobuf::MessageLite& from) {
+ MergeFrom(*::google::protobuf::down_cast<const Installation*>(&from));
+}
+
+void Installation::MergeFrom(const Installation& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:cobalt.loader.Installation)
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (from.is_successful() != 0) {
+ set_is_successful(from.is_successful());
+ }
+ if (from.num_tries_left() != 0) {
+ set_num_tries_left(from.num_tries_left());
+ }
+ if (from.priority() != 0) {
+ set_priority(from.priority());
+ }
+}
+
+void Installation::CopyFrom(const Installation& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:cobalt.loader.Installation)
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool Installation::IsInitialized() const {
+
+ return true;
+}
+
+void Installation::Swap(Installation* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void Installation::InternalSwap(Installation* other) {
+ std::swap(is_successful_, other->is_successful_);
+ std::swap(num_tries_left_, other->num_tries_left_);
+ std::swap(priority_, other->priority_);
+ _unknown_fields_.Swap(&other->_unknown_fields_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::std::string Installation::GetTypeName() const {
+ return "cobalt.loader.Installation";
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// Installation
+
+// optional bool is_successful = 1;
+void Installation::clear_is_successful() {
+ is_successful_ = false;
+}
+ bool Installation::is_successful() const {
+ // @@protoc_insertion_point(field_get:cobalt.loader.Installation.is_successful)
+ return is_successful_;
+}
+ void Installation::set_is_successful(bool value) {
+
+ is_successful_ = value;
+ // @@protoc_insertion_point(field_set:cobalt.loader.Installation.is_successful)
+}
+
+// optional int32 num_tries_left = 2;
+void Installation::clear_num_tries_left() {
+ num_tries_left_ = 0;
+}
+ ::google::protobuf::int32 Installation::num_tries_left() const {
+ // @@protoc_insertion_point(field_get:cobalt.loader.Installation.num_tries_left)
+ return num_tries_left_;
+}
+ void Installation::set_num_tries_left(::google::protobuf::int32 value) {
+
+ num_tries_left_ = value;
+ // @@protoc_insertion_point(field_set:cobalt.loader.Installation.num_tries_left)
+}
+
+// optional int32 priority = 3;
+void Installation::clear_priority() {
+ priority_ = 0;
+}
+ ::google::protobuf::int32 Installation::priority() const {
+ // @@protoc_insertion_point(field_get:cobalt.loader.Installation.priority)
+ return priority_;
+}
+ void Installation::set_priority(::google::protobuf::int32 value) {
+
+ priority_ = value;
+ // @@protoc_insertion_point(field_set:cobalt.loader.Installation.priority)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int InstallationStore::kInstallationsFieldNumber;
+const int InstallationStore::kRollForwardToInstallationFieldNumber;
+#endif // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+InstallationStore::InstallationStore()
+ : ::google::protobuf::MessageLite(), _arena_ptr_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:cobalt.loader.InstallationStore)
+}
+
+void InstallationStore::InitAsDefaultInstance() {
+ _is_default_instance_ = true;
+}
+
+InstallationStore::InstallationStore(const InstallationStore& from)
+ : ::google::protobuf::MessageLite(),
+ _arena_ptr_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:cobalt.loader.InstallationStore)
+}
+
+void InstallationStore::SharedCtor() {
+ _is_default_instance_ = false;
+ _cached_size_ = 0;
+ roll_forward_to_installation_ = 0;
+}
+
+InstallationStore::~InstallationStore() {
+ // @@protoc_insertion_point(destructor:cobalt.loader.InstallationStore)
+ SharedDtor();
+}
+
+void InstallationStore::SharedDtor() {
+ #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+ if (this != &default_instance()) {
+ #else
+ if (this != default_instance_) {
+ #endif
+ }
+}
+
+void InstallationStore::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const InstallationStore& InstallationStore::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+ protobuf_AddDesc_installation_5fstore_2eproto();
+#else
+ if (default_instance_ == NULL) protobuf_AddDesc_installation_5fstore_2eproto();
+#endif
+ return *default_instance_;
+}
+
+InstallationStore* InstallationStore::default_instance_ = NULL;
+
+InstallationStore* InstallationStore::New(::google::protobuf::Arena* arena) const {
+ InstallationStore* n = new InstallationStore;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void InstallationStore::Clear() {
+// @@protoc_insertion_point(message_clear_start:cobalt.loader.InstallationStore)
+ roll_forward_to_installation_ = 0;
+ installations_.Clear();
+}
+
+bool InstallationStore::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:cobalt.loader.InstallationStore)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // repeated .cobalt.loader.Installation installations = 1;
+ case 1: {
+ if (tag == 10) {
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_installations:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+ input, add_installations()));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(10)) goto parse_loop_installations;
+ input->UnsafeDecrementRecursionDepth();
+ if (input->ExpectTag(16)) goto parse_roll_forward_to_installation;
+ break;
+ }
+
+ // optional int32 roll_forward_to_installation = 2;
+ case 2: {
+ if (tag == 16) {
+ parse_roll_forward_to_installation:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, &roll_forward_to_installation_)));
+
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:cobalt.loader.InstallationStore)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:cobalt.loader.InstallationStore)
+ return false;
+#undef DO_
+}
+
+void InstallationStore::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:cobalt.loader.InstallationStore)
+ // repeated .cobalt.loader.Installation installations = 1;
+ for (unsigned int i = 0, n = this->installations_size(); i < n; i++) {
+ ::google::protobuf::internal::WireFormatLite::WriteMessage(
+ 1, this->installations(i), output);
+ }
+
+ // optional int32 roll_forward_to_installation = 2;
+ if (this->roll_forward_to_installation() != 0) {
+ ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->roll_forward_to_installation(), output);
+ }
+
+ // @@protoc_insertion_point(serialize_end:cobalt.loader.InstallationStore)
+}
+
+int InstallationStore::ByteSize() const {
+// @@protoc_insertion_point(message_byte_size_start:cobalt.loader.InstallationStore)
+ int total_size = 0;
+
+ // optional int32 roll_forward_to_installation = 2;
+ if (this->roll_forward_to_installation() != 0) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::Int32Size(
+ this->roll_forward_to_installation());
+ }
+
+ // repeated .cobalt.loader.Installation installations = 1;
+ total_size += 1 * this->installations_size();
+ for (int i = 0; i < this->installations_size(); i++) {
+ total_size +=
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ this->installations(i));
+ }
+
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void InstallationStore::CheckTypeAndMergeFrom(
+ const ::google::protobuf::MessageLite& from) {
+ MergeFrom(*::google::protobuf::down_cast<const InstallationStore*>(&from));
+}
+
+void InstallationStore::MergeFrom(const InstallationStore& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:cobalt.loader.InstallationStore)
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ installations_.MergeFrom(from.installations_);
+ if (from.roll_forward_to_installation() != 0) {
+ set_roll_forward_to_installation(from.roll_forward_to_installation());
+ }
+}
+
+void InstallationStore::CopyFrom(const InstallationStore& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:cobalt.loader.InstallationStore)
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool InstallationStore::IsInitialized() const {
+
+ return true;
+}
+
+void InstallationStore::Swap(InstallationStore* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void InstallationStore::InternalSwap(InstallationStore* other) {
+ installations_.UnsafeArenaSwap(&other->installations_);
+ std::swap(roll_forward_to_installation_, other->roll_forward_to_installation_);
+ _unknown_fields_.Swap(&other->_unknown_fields_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
+
+::std::string InstallationStore::GetTypeName() const {
+ return "cobalt.loader.InstallationStore";
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// InstallationStore
+
+// repeated .cobalt.loader.Installation installations = 1;
+int InstallationStore::installations_size() const {
+ return installations_.size();
+}
+void InstallationStore::clear_installations() {
+ installations_.Clear();
+}
+const ::cobalt::loader::Installation& InstallationStore::installations(int index) const {
+ // @@protoc_insertion_point(field_get:cobalt.loader.InstallationStore.installations)
+ return installations_.Get(index);
+}
+::cobalt::loader::Installation* InstallationStore::mutable_installations(int index) {
+ // @@protoc_insertion_point(field_mutable:cobalt.loader.InstallationStore.installations)
+ return installations_.Mutable(index);
+}
+::cobalt::loader::Installation* InstallationStore::add_installations() {
+ // @@protoc_insertion_point(field_add:cobalt.loader.InstallationStore.installations)
+ return installations_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::cobalt::loader::Installation >*
+InstallationStore::mutable_installations() {
+ // @@protoc_insertion_point(field_mutable_list:cobalt.loader.InstallationStore.installations)
+ return &installations_;
+}
+const ::google::protobuf::RepeatedPtrField< ::cobalt::loader::Installation >&
+InstallationStore::installations() const {
+ // @@protoc_insertion_point(field_list:cobalt.loader.InstallationStore.installations)
+ return installations_;
+}
+
+// optional int32 roll_forward_to_installation = 2;
+void InstallationStore::clear_roll_forward_to_installation() {
+ roll_forward_to_installation_ = 0;
+}
+ ::google::protobuf::int32 InstallationStore::roll_forward_to_installation() const {
+ // @@protoc_insertion_point(field_get:cobalt.loader.InstallationStore.roll_forward_to_installation)
+ return roll_forward_to_installation_;
+}
+ void InstallationStore::set_roll_forward_to_installation(::google::protobuf::int32 value) {
+
+ roll_forward_to_installation_ = value;
+ // @@protoc_insertion_point(field_set:cobalt.loader.InstallationStore.roll_forward_to_installation)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// @@protoc_insertion_point(namespace_scope)
+
+} // namespace loader
+} // namespace cobalt
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/starboard/loader_app/installation_store.pb.h b/src/starboard/loader_app/installation_store.pb.h
new file mode 100644
index 0000000..a3ad5c9
--- /dev/null
+++ b/src/starboard/loader_app/installation_store.pb.h
@@ -0,0 +1,361 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: installation_store.proto
+
+#ifndef PROTOBUF_installation_5fstore_2eproto__INCLUDED
+#define PROTOBUF_installation_5fstore_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 3000000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please update
+#error your headers.
+#endif
+#if 3000000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/message_lite.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+// @@protoc_insertion_point(includes)
+
+namespace cobalt {
+namespace loader {
+
+// Internal implementation detail -- do not call these.
+void protobuf_AddDesc_installation_5fstore_2eproto();
+void protobuf_AssignDesc_installation_5fstore_2eproto();
+void protobuf_ShutdownFile_installation_5fstore_2eproto();
+
+class Installation;
+class InstallationStore;
+
+// ===================================================================
+
+class Installation : public ::google::protobuf::MessageLite {
+ public:
+ Installation();
+ virtual ~Installation();
+
+ Installation(const Installation& from);
+
+ inline Installation& operator=(const Installation& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const Installation& default_instance();
+
+ #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+ // Returns the internal default instance pointer. This function can
+ // return NULL thus should not be used by the user. This is intended
+ // for Protobuf internal code. Please use default_instance() declared
+ // above instead.
+ static inline const Installation* internal_default_instance() {
+ return default_instance_;
+ }
+ #endif
+
+ GOOGLE_ATTRIBUTE_NOINLINE void Swap(Installation* other);
+
+ // implements Message ----------------------------------------------
+
+ inline Installation* New() const { return New(NULL); }
+
+ Installation* New(::google::protobuf::Arena* arena) const;
+ void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+ void CopyFrom(const Installation& from);
+ void MergeFrom(const Installation& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ void DiscardUnknownFields();
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(Installation* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _arena_ptr_;
+ }
+ inline ::google::protobuf::Arena* MaybeArenaPtr() const {
+ return _arena_ptr_;
+ }
+ public:
+
+ ::std::string GetTypeName() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // optional bool is_successful = 1;
+ void clear_is_successful();
+ static const int kIsSuccessfulFieldNumber = 1;
+ bool is_successful() const;
+ void set_is_successful(bool value);
+
+ // optional int32 num_tries_left = 2;
+ void clear_num_tries_left();
+ static const int kNumTriesLeftFieldNumber = 2;
+ ::google::protobuf::int32 num_tries_left() const;
+ void set_num_tries_left(::google::protobuf::int32 value);
+
+ // optional int32 priority = 3;
+ void clear_priority();
+ static const int kPriorityFieldNumber = 3;
+ ::google::protobuf::int32 priority() const;
+ void set_priority(::google::protobuf::int32 value);
+
+ // @@protoc_insertion_point(class_scope:cobalt.loader.Installation)
+ private:
+
+ ::google::protobuf::internal::ArenaStringPtr _unknown_fields_;
+ ::google::protobuf::Arena* _arena_ptr_;
+
+ bool _is_default_instance_;
+ bool is_successful_;
+ ::google::protobuf::int32 num_tries_left_;
+ ::google::protobuf::int32 priority_;
+ mutable int _cached_size_;
+ #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+ friend void protobuf_AddDesc_installation_5fstore_2eproto_impl();
+ #else
+ friend void protobuf_AddDesc_installation_5fstore_2eproto();
+ #endif
+ friend void protobuf_AssignDesc_installation_5fstore_2eproto();
+ friend void protobuf_ShutdownFile_installation_5fstore_2eproto();
+
+ void InitAsDefaultInstance();
+ static Installation* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class InstallationStore : public ::google::protobuf::MessageLite {
+ public:
+ InstallationStore();
+ virtual ~InstallationStore();
+
+ InstallationStore(const InstallationStore& from);
+
+ inline InstallationStore& operator=(const InstallationStore& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ static const InstallationStore& default_instance();
+
+ #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+ // Returns the internal default instance pointer. This function can
+ // return NULL thus should not be used by the user. This is intended
+ // for Protobuf internal code. Please use default_instance() declared
+ // above instead.
+ static inline const InstallationStore* internal_default_instance() {
+ return default_instance_;
+ }
+ #endif
+
+ GOOGLE_ATTRIBUTE_NOINLINE void Swap(InstallationStore* other);
+
+ // implements Message ----------------------------------------------
+
+ inline InstallationStore* New() const { return New(NULL); }
+
+ InstallationStore* New(::google::protobuf::Arena* arena) const;
+ void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+ void CopyFrom(const InstallationStore& from);
+ void MergeFrom(const InstallationStore& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ void DiscardUnknownFields();
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(InstallationStore* other);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _arena_ptr_;
+ }
+ inline ::google::protobuf::Arena* MaybeArenaPtr() const {
+ return _arena_ptr_;
+ }
+ public:
+
+ ::std::string GetTypeName() const;
+
+ // nested types ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // repeated .cobalt.loader.Installation installations = 1;
+ int installations_size() const;
+ void clear_installations();
+ static const int kInstallationsFieldNumber = 1;
+ const ::cobalt::loader::Installation& installations(int index) const;
+ ::cobalt::loader::Installation* mutable_installations(int index);
+ ::cobalt::loader::Installation* add_installations();
+ ::google::protobuf::RepeatedPtrField< ::cobalt::loader::Installation >*
+ mutable_installations();
+ const ::google::protobuf::RepeatedPtrField< ::cobalt::loader::Installation >&
+ installations() const;
+
+ // optional int32 roll_forward_to_installation = 2;
+ void clear_roll_forward_to_installation();
+ static const int kRollForwardToInstallationFieldNumber = 2;
+ ::google::protobuf::int32 roll_forward_to_installation() const;
+ void set_roll_forward_to_installation(::google::protobuf::int32 value);
+
+ // @@protoc_insertion_point(class_scope:cobalt.loader.InstallationStore)
+ private:
+
+ ::google::protobuf::internal::ArenaStringPtr _unknown_fields_;
+ ::google::protobuf::Arena* _arena_ptr_;
+
+ bool _is_default_instance_;
+ ::google::protobuf::RepeatedPtrField< ::cobalt::loader::Installation > installations_;
+ ::google::protobuf::int32 roll_forward_to_installation_;
+ mutable int _cached_size_;
+ #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+ friend void protobuf_AddDesc_installation_5fstore_2eproto_impl();
+ #else
+ friend void protobuf_AddDesc_installation_5fstore_2eproto();
+ #endif
+ friend void protobuf_AssignDesc_installation_5fstore_2eproto();
+ friend void protobuf_ShutdownFile_installation_5fstore_2eproto();
+
+ void InitAsDefaultInstance();
+ static InstallationStore* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
+// Installation
+
+// optional bool is_successful = 1;
+inline void Installation::clear_is_successful() {
+ is_successful_ = false;
+}
+inline bool Installation::is_successful() const {
+ // @@protoc_insertion_point(field_get:cobalt.loader.Installation.is_successful)
+ return is_successful_;
+}
+inline void Installation::set_is_successful(bool value) {
+
+ is_successful_ = value;
+ // @@protoc_insertion_point(field_set:cobalt.loader.Installation.is_successful)
+}
+
+// optional int32 num_tries_left = 2;
+inline void Installation::clear_num_tries_left() {
+ num_tries_left_ = 0;
+}
+inline ::google::protobuf::int32 Installation::num_tries_left() const {
+ // @@protoc_insertion_point(field_get:cobalt.loader.Installation.num_tries_left)
+ return num_tries_left_;
+}
+inline void Installation::set_num_tries_left(::google::protobuf::int32 value) {
+
+ num_tries_left_ = value;
+ // @@protoc_insertion_point(field_set:cobalt.loader.Installation.num_tries_left)
+}
+
+// optional int32 priority = 3;
+inline void Installation::clear_priority() {
+ priority_ = 0;
+}
+inline ::google::protobuf::int32 Installation::priority() const {
+ // @@protoc_insertion_point(field_get:cobalt.loader.Installation.priority)
+ return priority_;
+}
+inline void Installation::set_priority(::google::protobuf::int32 value) {
+
+ priority_ = value;
+ // @@protoc_insertion_point(field_set:cobalt.loader.Installation.priority)
+}
+
+// -------------------------------------------------------------------
+
+// InstallationStore
+
+// repeated .cobalt.loader.Installation installations = 1;
+inline int InstallationStore::installations_size() const {
+ return installations_.size();
+}
+inline void InstallationStore::clear_installations() {
+ installations_.Clear();
+}
+inline const ::cobalt::loader::Installation& InstallationStore::installations(int index) const {
+ // @@protoc_insertion_point(field_get:cobalt.loader.InstallationStore.installations)
+ return installations_.Get(index);
+}
+inline ::cobalt::loader::Installation* InstallationStore::mutable_installations(int index) {
+ // @@protoc_insertion_point(field_mutable:cobalt.loader.InstallationStore.installations)
+ return installations_.Mutable(index);
+}
+inline ::cobalt::loader::Installation* InstallationStore::add_installations() {
+ // @@protoc_insertion_point(field_add:cobalt.loader.InstallationStore.installations)
+ return installations_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::cobalt::loader::Installation >*
+InstallationStore::mutable_installations() {
+ // @@protoc_insertion_point(field_mutable_list:cobalt.loader.InstallationStore.installations)
+ return &installations_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::cobalt::loader::Installation >&
+InstallationStore::installations() const {
+ // @@protoc_insertion_point(field_list:cobalt.loader.InstallationStore.installations)
+ return installations_;
+}
+
+// optional int32 roll_forward_to_installation = 2;
+inline void InstallationStore::clear_roll_forward_to_installation() {
+ roll_forward_to_installation_ = 0;
+}
+inline ::google::protobuf::int32 InstallationStore::roll_forward_to_installation() const {
+ // @@protoc_insertion_point(field_get:cobalt.loader.InstallationStore.roll_forward_to_installation)
+ return roll_forward_to_installation_;
+}
+inline void InstallationStore::set_roll_forward_to_installation(::google::protobuf::int32 value) {
+
+ roll_forward_to_installation_ = value;
+ // @@protoc_insertion_point(field_set:cobalt.loader.InstallationStore.roll_forward_to_installation)
+}
+
+#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
+// -------------------------------------------------------------------
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+} // namespace loader
+} // namespace cobalt
+
+// @@protoc_insertion_point(global_scope)
+
+#endif // PROTOBUF_installation_5fstore_2eproto__INCLUDED
diff --git a/src/starboard/loader_app/installation_store.proto b/src/starboard/loader_app/installation_store.proto
new file mode 100644
index 0000000..905ecac
--- /dev/null
+++ b/src/starboard/loader_app/installation_store.proto
@@ -0,0 +1,44 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto3";
+
+option optimize_for = LITE_RUNTIME;
+
+package cobalt.loader;
+
+// Single installation slot.
+message Installation {
+ // Is the installation successful.
+ bool is_successful = 1;
+
+ // Number of tries left for this installation.
+ int32 num_tries_left = 2;
+
+ // Priority of the installation.
+ // Valid values are '0' to 'num_installations - 1',
+ // with '0' being the highest priority.
+ int32 priority = 3;
+}
+
+// Installation store for all installations.
+message InstallationStore {
+ // All the installation slots.
+ repeated Installation installations = 1;
+
+ // To which installation to roll forward to.
+ // The value of -1 means no change is needed.
+ // The updater sets the value and the loader performs the action.
+ int32 roll_forward_to_installation = 2;
+}
diff --git a/src/starboard/loader_app/loader_app.cc b/src/starboard/loader_app/loader_app.cc
new file mode 100644
index 0000000..7091fb9
--- /dev/null
+++ b/src/starboard/loader_app/loader_app.cc
@@ -0,0 +1,167 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <vector>
+
+#include "starboard/common/log.h"
+#include "starboard/configuration.h"
+#include "starboard/configuration_constants.h"
+#include "starboard/elf_loader/elf_loader.h"
+#include "starboard/event.h"
+#include "starboard/loader_app/installation_manager.h"
+#include "starboard/loader_app/system_get_extension_shim.h"
+#include "starboard/mutex.h"
+#include "starboard/string.h"
+#include "starboard/thread_types.h"
+
+// TODO: Try to merge with the implementation in starboard/elf_loader/sandbox.cc
+
+namespace {
+// The max number of installations slots.
+const int kMaxNumInstallations = 3;
+
+// Relative path for the Cobalt so file.
+const char kCobaltLibraryPath[] = "lib";
+
+// Filename for the Cobalt binary.
+const char kCobaltLibraryName[] = "libcobalt.so";
+
+// Relative path for the content directory of
+// the Cobalt installation.
+const char kCobaltContentPath[] = "content";
+
+// Portable ELF loader.
+starboard::elf_loader::ElfLoader g_elf_loader;
+
+// Pointer to the |SbEventHandle| function in the
+// Cobalt binary.
+void (*g_sb_event_func)(const SbEvent*) = NULL;
+
+void LoadLibraryAndInitialize() {
+ // Initialize the Installation Manager.
+ SB_CHECK(ImInitialize(kMaxNumInstallations) == IM_SUCCESS)
+ << "Abort. Failed to initialize Installation Manager";
+
+ // Roll forward if needed.
+ if (ImRollForwardIfNeeded() == IM_ERROR) {
+ SB_LOG(WARNING) << "Failed to roll forward";
+ }
+
+ // Loop by priority.
+ int current_installation = ImGetCurrentInstallationIndex();
+ while (current_installation != IM_ERROR) {
+ // if not successful and num_tries_left > 0 decrement and try to
+ // load the library.
+ if (ImGetInstallationStatus(current_installation) !=
+ IM_INSTALLATION_STATUS_SUCCESS) {
+ int num_tries_left = ImGetInstallationNumTriesLeft(current_installation);
+ if (num_tries_left == IM_ERROR || num_tries_left <= 0 ||
+ ImDecrementInstallationNumTries(current_installation) == IM_ERROR) {
+ // If no more tries are left or if we have hard failure,
+ // discard the image and auto rollback, but only if
+ // the current image is not the system image.
+ if (current_installation != 0) {
+ current_installation = ImRevertToSuccessfulInstallation();
+ }
+ }
+ }
+
+ SB_LOG(INFO) << "Try to load the Cobalt binary";
+ SB_LOG(INFO) << "current_installation=" << current_installation;
+
+ // Try to load the image. Failures here discard the image.
+ std::vector<char> installation_path(kSbFileMaxPath);
+ if (ImGetInstallationPath(current_installation, installation_path.data(),
+ kSbFileMaxPath) == IM_ERROR) {
+ SB_LOG(ERROR) << "Failed to find library file";
+
+ // Hard failure. Discard the image and auto rollback, but only if
+ // the current image is not the system image.
+ if (current_installation != 0) {
+ current_installation = ImRevertToSuccessfulInstallation();
+ continue;
+ } else {
+ // The system image at index 0 failed.
+ break;
+ }
+ }
+
+ SB_DLOG(INFO) << "installation_path=" << installation_path.data();
+
+ // installation_n/lib/libcobalt.so
+ std::vector<char> lib_path(kSbFileMaxPath);
+ SbStringFormatF(lib_path.data(), kSbFileMaxPath, "%s%s%s%s%s",
+ installation_path.data(), kSbFileSepString,
+ kCobaltLibraryPath, kSbFileSepString, kCobaltLibraryName);
+ SB_LOG(INFO) << "lib_path=" << lib_path.data();
+
+ // installation_n/content
+ std::vector<char> content_path(kSbFileMaxPath);
+ SbStringFormatF(content_path.data(), kSbFileMaxPath, "%s%s%s",
+ installation_path.data(), kSbFileSepString,
+ kCobaltContentPath);
+ SB_LOG(INFO) << "content_path=" << content_path.data();
+
+ if (!g_elf_loader.Load(lib_path.data(), content_path.data(), false,
+ &starboard::loader_app::SbSystemGetExtensionShim)) {
+ SB_LOG(WARNING) << "Failed to load Cobalt!";
+
+ // Hard failure. Discard the image and auto rollback, but only if
+ // the current image is not the system image.
+ if (current_installation != 0) {
+ current_installation = ImRevertToSuccessfulInstallation();
+ continue;
+ } else {
+ // The system image at index 0 failed.
+ break;
+ }
+ }
+
+ SB_DLOG(INFO) << "Successfully loaded Cobalt!\n";
+ void* p = g_elf_loader.LookupSymbol("SbEventHandle");
+ if (p != NULL) {
+ SB_DLOG(INFO) << "Symbol Lookup succeeded address: " << p;
+ g_sb_event_func = (void (*)(const SbEvent*))p;
+ break;
+ } else {
+ SB_LOG(ERROR) << "Symbol Lookup failed\n";
+
+ // Hard failure. Discard the image and auto rollback, but only if
+ // the current image is not the system image.
+ if (current_installation != 0) {
+ current_installation = ImRevertToSuccessfulInstallation();
+ continue;
+ } else {
+ // The system image at index 0 failed.
+ break;
+ }
+ }
+ }
+}
+} // namespace
+
+void SbEventHandle(const SbEvent* event) {
+ static SbMutex mutex = SB_MUTEX_INITIALIZER;
+
+ SB_CHECK(SbMutexAcquire(&mutex) == kSbMutexAcquired);
+
+ if (!g_sb_event_func) {
+ LoadLibraryAndInitialize();
+ SB_CHECK(g_sb_event_func);
+ }
+
+ g_sb_event_func(event);
+
+ SB_CHECK(SbMutexRelease(&mutex) == true);
+}
diff --git a/src/starboard/loader_app/loader_app.gyp b/src/starboard/loader_app/loader_app.gyp
new file mode 100644
index 0000000..097b5fa
--- /dev/null
+++ b/src/starboard/loader_app/loader_app.gyp
@@ -0,0 +1,91 @@
+# Copyright 2019 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This files contains all targets that should be created by gyp_cobalt by
+# default.
+{
+ 'variables': {
+ 'common_loader_app_sources': [
+ 'loader_app.cc',
+ 'system_get_extension_shim.h',
+ 'system_get_extension_shim.cc',
+ ],
+ 'common_loader_app_dependencies': [
+ '<(DEPTH)/starboard/loader_app/installation_manager.gyp:installation_manager',
+ '<(DEPTH)/starboard/starboard.gyp:starboard',
+ ],
+ },
+ 'targets': [
+ {
+ 'target_name': 'loader_app',
+ 'type': '<(final_executable_type)',
+ 'conditions': [
+ ['target_arch in ["x86", "x64", "arm", "arm64"] ', {
+ 'sources': [
+ '<@(common_loader_app_sources)',
+ ],
+ 'dependencies': [
+ '<(DEPTH)/starboard/elf_loader/elf_loader.gyp:elf_loader',
+ '<@(common_loader_app_dependencies)',
+ # TODO: Remove this dependency once MediaSession is migrated to use CobaltExtensions.
+ '<@(cobalt_platform_dependencies)',
+ ],
+ }],
+ ],
+ },
+ {
+ 'target_name': 'loader_app_deploy',
+ 'type': 'none',
+ 'dependencies': [
+ 'loader_app',
+ ],
+ 'variables': {
+ 'executable_name': 'loader_app',
+ },
+ 'includes': [ '<(DEPTH)/starboard/build/deploy.gypi' ],
+ },
+ {
+ 'target_name': 'loader_app_sys',
+ 'type': '<(final_executable_type)',
+ 'conditions': [
+ ['target_arch in ["x86", "x64", "arm", "arm64"] ', {
+ 'sources': [
+ '<@(common_loader_app_sources)',
+ ],
+ 'dependencies': [
+ '<(DEPTH)/starboard/elf_loader/elf_loader.gyp:elf_loader_sys',
+ '<@(common_loader_app_dependencies)',
+ # TODO: Remove this dependency once MediaSession is migrated to use CobaltExtensions.
+ '<@(cobalt_platform_dependencies)',
+ ],
+ 'ldflags': [
+ '-Wl,--dynamic-list=<(DEPTH)/starboard/starboard.syms',
+ '-ldl' ,
+ ],
+ }],
+ ],
+ },
+ {
+ 'target_name': 'loader_app_sys_deploy',
+ 'type': 'none',
+ 'dependencies': [
+ 'loader_app',
+ ],
+ 'variables': {
+ 'executable_name': 'loader_app_sys',
+ },
+ 'includes': [ '<(DEPTH)/starboard/build/deploy.gypi' ],
+ },
+ ],
+}
diff --git a/src/starboard/loader_app/system_get_extension_shim.cc b/src/starboard/loader_app/system_get_extension_shim.cc
new file mode 100644
index 0000000..8017159
--- /dev/null
+++ b/src/starboard/loader_app/system_get_extension_shim.cc
@@ -0,0 +1,46 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/loader_app/system_get_extension_shim.h"
+
+#include <string>
+
+#include "cobalt/extension/installation_manager.h"
+#include "starboard/common/log.h"
+#include "starboard/loader_app/installation_manager.h"
+#include "starboard/string.h"
+#include "starboard/system.h"
+
+namespace {
+const CobaltExtensionInstallationManagerApi kInstallationManagerApi = {
+ kCobaltExtensionInstallationManagerName,
+ 1, // API version that's implemented.
+ &ImGetCurrentInstallationIndex,
+ &ImMarkInstallationSuccessful,
+ &ImRequestRollForwardToInstallation,
+ &ImGetInstallationPath,
+ &ImSelectNewInstallationIndex,
+};
+} // namespace
+namespace starboard {
+namespace loader_app {
+
+const void* SbSystemGetExtensionShim(const char* name) {
+ if (SbStringCompareAll(name, kCobaltExtensionInstallationManagerName) == 0) {
+ return &kInstallationManagerApi;
+ }
+ return NULL;
+}
+} // namespace loader_app
+} // namespace starboard
diff --git a/src/starboard/loader_app/system_get_extension_shim.h b/src/starboard/loader_app/system_get_extension_shim.h
new file mode 100644
index 0000000..befaf9c
--- /dev/null
+++ b/src/starboard/loader_app/system_get_extension_shim.h
@@ -0,0 +1,39 @@
+// Copyright 2019 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// ELF Loader shim functions are intended to be patched into the Cobalt shared
+// library when the library is loaded. Cobalt will then invoke the shim function
+// where it would otherwise invoke the original function, allowing us to
+// partially or entirely change the behavior within that function call.
+
+#ifndef STARBOARD_LOADER_APP_SYSTEM_GET_EXTENSION_SHIM_H_
+#define STARBOARD_LOADER_APP_SYSTEM_GET_EXTENSION_SHIM_H_
+
+#include "starboard/system.h"
+
+namespace starboard {
+namespace loader_app {
+
+// Adds the |kCobaltExtensionInstallationManagerName| to the list of extensions
+// supported by SbSystemGetExtension() by wrapping the call to
+// SbSystemGetExtension.
+//
+// Please reference //starboard/system.h for documentation on
+// SbSystemGetExtension().
+const void* SbSystemGetExtensionShim(const char* name);
+
+} // namespace loader_app
+} // namespace starboard
+
+#endif // STARBOARD_LOADER_APP_SYSTEM_GET_EXTENSION_SHIM_H_
diff --git a/src/starboard/media.h b/src/starboard/media.h
index c554c58..bfc5864 100644
--- a/src/starboard/media.h
+++ b/src/starboard/media.h
@@ -31,20 +31,6 @@
// --- Types -----------------------------------------------------------------
-#if SB_API_VERSION < 10
-// Time represented in 90KHz ticks.
-typedef int64_t SbMediaTime;
-
-#define SB_MEDIA_TIME_TO_SB_TIME(media) \
- (((media == SB_PLAYER_NO_DURATION) \
- ? SB_PLAYER_NO_DURATION \
- : ((media == kSbInt64Max) ? kSbInt64Max : (media * 100 / 9))))
-#define SB_TIME_TO_SB_MEDIA_TIME(time) \
- (((time == SB_PLAYER_NO_DURATION) \
- ? SB_PLAYER_NO_DURATION \
- : ((time == kSbInt64Max) ? kSbInt64Max : (time * 9 / 100))))
-#endif // SB_API_VERSION < 10
-
// Types of media component streams.
typedef enum SbMediaType {
// Value used for audio streams.
@@ -531,14 +517,6 @@
typedef SbMediaAudioSampleInfo SbMediaAudioHeader;
#endif // SB_API_VERSION < 11
-#if SB_API_VERSION < 10
-// --- Constants -------------------------------------------------------------
-
-// TODO: remove entirely.
-// One second in SbMediaTime (90KHz ticks).
-#define kSbMediaTimeSecond ((SbMediaTime)(90000))
-#endif // SB_API_VERSION < 10
-
// --- Functions -------------------------------------------------------------
// Indicates whether this platform supports decoding |video_codec| and
@@ -609,7 +587,6 @@
// disabled.
SB_EXPORT bool SbMediaSetOutputProtection(bool enabled);
-#if SB_API_VERSION >= 10
// Value used when a video's resolution is not known.
#define kSbMediaVideoResolutionDimensionInvalid 0
// Value used when a video's bits per pixel is not known.
@@ -732,7 +709,6 @@
int resolution_width,
int resolution_height,
int bits_per_pixel);
-#endif // SB_API_VERSION >= 10
#if SB_API_VERSION >= 11
// Communicate to the platform how far past |current_playback_position| the app
diff --git a/src/starboard/memory.h b/src/starboard/memory.h
index c844b8d..24d2b61 100644
--- a/src/starboard/memory.h
+++ b/src/starboard/memory.h
@@ -56,9 +56,7 @@
typedef enum SbMemoryMapFlags {
// No flags set: Reserves virtual address space. SbMemoryProtect() can later
// make it accessible.
-#if SB_API_VERSION >= 10
kSbMemoryMapProtectReserved = 0,
-#endif
kSbMemoryMapProtectRead = 1 << 0, // Mapped memory can be read.
kSbMemoryMapProtectWrite = 1 << 1, // Mapped memory can be written to.
#if SB_CAN(MAP_EXECUTABLE_MEMORY)
@@ -221,13 +219,11 @@
// |SbMemoryUnmap(0xA000, 0x2000)| should free both regions.
SB_EXPORT bool SbMemoryUnmap(void* virtual_address, int64_t size_bytes);
-#if SB_API_VERSION >= 10
// Change the protection of |size_bytes| of memory regions, starting from
// |virtual_address|, to |flags|, returning |true| on success.
SB_EXPORT bool SbMemoryProtect(void* virtual_address,
int64_t size_bytes,
int flags);
-#endif
#if SB_CAN(MAP_EXECUTABLE_MEMORY)
// Flushes any data in the given virtual address range that is cached locally in
diff --git a/src/starboard/mutex.h b/src/starboard/mutex.h
index 4192c42..790087f 100644
--- a/src/starboard/mutex.h
+++ b/src/starboard/mutex.h
@@ -32,7 +32,7 @@
#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
// Max size of the SbMutex type.
-#define SB_MUTEX_MAX_SIZE 64
+#define SB_MUTEX_MAX_SIZE 80
// An opaque handle to a mutex type with reserved memory
// buffer of size SB_MUTEX_MAX_SIZE and aligned at void
diff --git a/src/starboard/nplb/atomic_test.cc b/src/starboard/nplb/atomic_test.cc
index 9adf0e7..16fd789 100644
--- a/src/starboard/nplb/atomic_test.cc
+++ b/src/starboard/nplb/atomic_test.cc
@@ -46,9 +46,7 @@
};
typedef testing::Types<
-#if SB_API_VERSION >= 10
SbAtomic8,
-#endif
SbAtomic32,
#if SB_HAS(64_BIT_ATOMICS)
SbAtomic64,
@@ -61,11 +59,7 @@
#endif
SbAtomicPtr> AdvancedSbAtomicTestTypes;
-#if SB_API_VERSION >= 10
TYPED_TEST_CASE(BasicSbAtomicTest, BasicSbAtomicTestTypes);
-#else
-TYPED_TEST_CASE(BasicSbAtomicTest, AdvancedSbAtomicTestTypes);
-#endif
TYPED_TEST_CASE(AdvancedSbAtomicTest, AdvancedSbAtomicTestTypes);
diff --git a/src/starboard/nplb/audio_sink_create_test.cc b/src/starboard/nplb/audio_sink_create_test.cc
index eba658d..194b27f 100644
--- a/src/starboard/nplb/audio_sink_create_test.cc
+++ b/src/starboard/nplb/audio_sink_create_test.cc
@@ -62,7 +62,6 @@
SbAudioSinkDestroy(audio_sink);
}
-#if SB_API_VERSION >= 10
TEST(SbAudioSinkCreateTest, MultiSink) {
ASSERT_GE(SbAudioSinkGetMaxChannels(), 1);
@@ -88,7 +87,6 @@
SbAudioSinkDestroy(sink);
}
}
-#endif // SB_API_VERSION >= 10
TEST(SbAudioSinkCreateTest, SunnyDayAllCombinations) {
std::vector<SbMediaAudioSampleType> sample_types;
diff --git a/src/starboard/nplb/audio_sink_get_max_channels_test.cc b/src/starboard/nplb/audio_sink_get_max_channels_test.cc
index ba94c54..e50cf18 100644
--- a/src/starboard/nplb/audio_sink_get_max_channels_test.cc
+++ b/src/starboard/nplb/audio_sink_get_max_channels_test.cc
@@ -19,10 +19,13 @@
namespace nplb {
TEST(SbAudioSinkGetMaxChannelsTest, SunnyDay) {
- int max_channels = SbAudioSinkGetMaxChannels();
- EXPECT_GT(max_channels, 0);
- // See if it reports anything ridiculous.
- EXPECT_LT(max_channels, 99);
+ // Call the function a few times to ensure that it works consistently
+ for (int i = 0; i < 4; ++i) {
+ int max_channels = SbAudioSinkGetMaxChannels();
+ EXPECT_GT(max_channels, 0);
+ // See if it reports anything ridiculous.
+ EXPECT_LT(max_channels, 99);
+ }
}
} // namespace nplb
diff --git a/src/starboard/nplb/audio_sink_get_min_buffer_size_in_frames_test.cc b/src/starboard/nplb/audio_sink_get_min_buffer_size_in_frames_test.cc
index a07a8c8..cac5917 100644
--- a/src/starboard/nplb/audio_sink_get_min_buffer_size_in_frames_test.cc
+++ b/src/starboard/nplb/audio_sink_get_min_buffer_size_in_frames_test.cc
@@ -19,6 +19,9 @@
namespace nplb {
#if SB_API_VERSION >= 11
+
+const int kMaxAllowedMinRequiredFrames = 16 * 1024;
+
TEST(SbAudioSinkGetMinBufferSizeInFramesTest, SunnyDay) {
SbMediaAudioSampleType sample_type = kSbMediaAudioSampleTypeFloat32;
if (!SbAudioSinkIsAudioSampleTypeSupported(sample_type)) {
@@ -31,7 +34,7 @@
SbAudioSinkGetNearestSupportedSampleFrequency(kDefaultSampleFrequency));
EXPECT_GT(min_required_frames, 0);
- EXPECT_LE(min_required_frames, 10 * 1024);
+ EXPECT_LE(min_required_frames, kMaxAllowedMinRequiredFrames);
if (max_channels > 1) {
min_required_frames = SbAudioSinkGetMinBufferSizeInFrames(
@@ -39,7 +42,7 @@
SbAudioSinkGetNearestSupportedSampleFrequency(kDefaultSampleFrequency));
EXPECT_GT(min_required_frames, 0);
- EXPECT_LE(min_required_frames, 10 * 1024);
+ EXPECT_LE(min_required_frames, kMaxAllowedMinRequiredFrames);
}
if (max_channels > 2) {
min_required_frames = SbAudioSinkGetMinBufferSizeInFrames(
@@ -47,7 +50,7 @@
SbAudioSinkGetNearestSupportedSampleFrequency(kDefaultSampleFrequency));
EXPECT_GT(min_required_frames, 0);
- EXPECT_LE(min_required_frames, 10 * 1024);
+ EXPECT_LE(min_required_frames, kMaxAllowedMinRequiredFrames);
}
}
#endif // SB_API_VERSION >= 11
diff --git a/src/starboard/nplb/blitter_pixel_tests/tests.cc b/src/starboard/nplb/blitter_pixel_tests/tests.cc
index a936d6f..b349476 100644
--- a/src/starboard/nplb/blitter_pixel_tests/tests.cc
+++ b/src/starboard/nplb/blitter_pixel_tests/tests.cc
@@ -32,6 +32,7 @@
// including image diffs between the actual results and expected results.
#include "starboard/blitter.h"
+#include "starboard/configuration_constants.h"
#include "starboard/nplb/blitter_pixel_tests/fixture.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -262,15 +263,16 @@
int height) {
SbBlitterPixelDataFormat pixel_data_format;
-#if SB_PREFERRED_RGBA_BYTE_ORDER == SB_PREFERRED_RGBA_BYTE_ORDER_RGBA
- pixel_data_format = kSbBlitterPixelDataFormatRGBA8;
-#elif SB_PREFERRED_RGBA_BYTE_ORDER == SB_PREFERRED_RGBA_BYTE_ORDER_BGRA
- pixel_data_format = kSbBlitterPixelDataFormatBGRA8;
-#elif SB_PREFERRED_RGBA_BYTE_ORDER == SB_PREFERRED_RGBA_BYTE_ORDER_ARGB
- pixel_data_format = kSbBlitterPixelDataFormatARGB8;
-#else
-#error "Platform's preferred RGBA byte order is not yet supported."
-#endif
+ if (kSbPreferredRgbaByteOrder == SB_PREFERRED_RGBA_BYTE_ORDER_RGBA) {
+ pixel_data_format = kSbBlitterPixelDataFormatRGBA8;
+ } else if (kSbPreferredRgbaByteOrder == SB_PREFERRED_RGBA_BYTE_ORDER_BGRA) {
+ pixel_data_format = kSbBlitterPixelDataFormatBGRA8;
+ } else if (kSbPreferredRgbaByteOrder == SB_PREFERRED_RGBA_BYTE_ORDER_ARGB) {
+ pixel_data_format = kSbBlitterPixelDataFormatARGB8;
+ } else {
+ SB_CHECK(false)
+ << "Platform's preferred RGBA byte order is not yet supported.";
+ }
// RGBA byte-offsets into each pixel.
int r, g, b, a;
diff --git a/src/starboard/nplb/cpu_features_get_test.cc b/src/starboard/nplb/cpu_features_get_test.cc
index 53469cc..c72a84e 100644
--- a/src/starboard/nplb/cpu_features_get_test.cc
+++ b/src/starboard/nplb/cpu_features_get_test.cc
@@ -67,6 +67,9 @@
EXPECT_EQ(false, features.x86.has_sse2);
EXPECT_EQ(false, features.x86.has_tsc);
EXPECT_EQ(false, features.x86.has_sse3);
+#if defined(SB_CPU_FEATURE_PCLMULQDQ)
+ EXPECT_EQ(false, features.x86.has_pclmulqdq);
+#endif // defined(SB_CPU_FEATURE_PCLMULQDQ)
EXPECT_EQ(false, features.x86.has_ssse3);
EXPECT_EQ(false, features.x86.has_sse41);
EXPECT_EQ(false, features.x86.has_sse42);
@@ -121,24 +124,14 @@
ExpectArmInvalid(features);
#endif // SB_IS(ARCH_ARM) || SB_IS(ARCH_ARM64)
-#if SB_IS(ARCH_MIPS)
- EXPECT_TRUE(features.architecture == kSbCPUFeaturesArchitectureMips ||
- features.architecture == kSbCPUFeaturesArchitectureMips64);
-#else // !SB_IS(ARCH_MIPS)
- ExpectMipsInvalid(features);
-#endif // SB_IS(ARCH_MIPS)
-
-#if SB_IS(ARCH_PPC)
- EXPECT_TRUE(features.architecture == kSbCPUFeaturesArchitecturePpc ||
- features.architecture == kSbCPUFeaturesArchitecturePpc64);
-#endif // SB_IS(ARCH_PPC)
-
#if SB_IS(ARCH_X86) || SB_IS(ARCH_X64)
EXPECT_TRUE(features.architecture == kSbCPUFeaturesArchitectureX86 ||
features.architecture == kSbCPUFeaturesArchitectureX86_64);
#else // !SB_IS(ARCH_X86) && !SB_IS(ARCH_X64)
ExpectX86Invalid(features);
#endif // SB_IS(ARCH_X86) || SB_IS(ARCH_X64)
+
+ ExpectMipsInvalid(features);
}
}
diff --git a/src/starboard/nplb/cryptography_create_transformer_test.cc b/src/starboard/nplb/cryptography_create_transformer_test.cc
index 7a1c1c6..1dcf280 100644
--- a/src/starboard/nplb/cryptography_create_transformer_test.cc
+++ b/src/starboard/nplb/cryptography_create_transformer_test.cc
@@ -12,6 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "starboard/configuration.h"
+
+#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+
#include "starboard/cryptography.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -46,3 +50,5 @@
} // namespace
} // namespace nplb
} // namespace starboard
+
+#endif // SB_CRYPTOAPI_DEPRECATED_VERSION
diff --git a/src/starboard/nplb/cryptography_helpers.cc b/src/starboard/nplb/cryptography_helpers.cc
index 6b189d8..c92f422 100644
--- a/src/starboard/nplb/cryptography_helpers.cc
+++ b/src/starboard/nplb/cryptography_helpers.cc
@@ -60,6 +60,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "starboard/configuration.h"
+
+#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+
#include "starboard/nplb/cryptography_helpers.h"
#include <string>
@@ -143,3 +147,5 @@
} // namespace nplb
} // namespace starboard
+
+#endif // SB_CRYPTOAPI_DEPRECATED_VERSION
diff --git a/src/starboard/nplb/cryptography_transform_gcm_test.cc b/src/starboard/nplb/cryptography_transform_gcm_test.cc
index 69a59e1..081067f 100644
--- a/src/starboard/nplb/cryptography_transform_gcm_test.cc
+++ b/src/starboard/nplb/cryptography_transform_gcm_test.cc
@@ -62,6 +62,10 @@
// This test is adapted from BoringSSL's crypto/fipsmodule/modes/gcm_test.cc
+#include "starboard/configuration.h"
+
+#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+
#include "starboard/cryptography.h"
#include "starboard/common/log.h"
@@ -443,3 +447,5 @@
} // namespace
} // namespace nplb
} // namespace starboard
+
+#endif // SB_CRYPTOAPI_DEPRECATED_VERSION
diff --git a/src/starboard/nplb/cryptography_transform_test.cc b/src/starboard/nplb/cryptography_transform_test.cc
index 0ffc4c9..98feac6 100644
--- a/src/starboard/nplb/cryptography_transform_test.cc
+++ b/src/starboard/nplb/cryptography_transform_test.cc
@@ -12,6 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "starboard/configuration.h"
+
+#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+
#include "starboard/cryptography.h"
#include "starboard/common/log.h"
@@ -223,3 +227,5 @@
} // namespace
} // namespace nplb
} // namespace starboard
+
+#endif // SB_CRYPTOAPI_DEPRECATED_VERSION
diff --git a/src/starboard/nplb/drm_create_system_test.cc b/src/starboard/nplb/drm_create_system_test.cc
index 9cd4b7a..4082580 100644
--- a/src/starboard/nplb/drm_create_system_test.cc
+++ b/src/starboard/nplb/drm_create_system_test.cc
@@ -40,7 +40,6 @@
EXPECT_TRUE(any_supported_key_systems) << " no DRM key systems supported";
}
-#if SB_API_VERSION >= 10
TEST(SbDrmTest, NullCallbacks) {
for (int i = 0; i < SB_ARRAY_SIZE_INT(kKeySystems); ++i) {
const char* key_system = kKeySystems[i];
@@ -111,7 +110,6 @@
SbDrmDestroySystem(drm_system);
}
}
-#endif // SB_API_VERSION >= 10
} // namespace
} // namespace nplb
diff --git a/src/starboard/nplb/drm_helpers.cc b/src/starboard/nplb/drm_helpers.cc
index 930fb82..cac39fa 100644
--- a/src/starboard/nplb/drm_helpers.cc
+++ b/src/starboard/nplb/drm_helpers.cc
@@ -19,8 +19,6 @@
namespace starboard {
namespace nplb {
-#if SB_API_VERSION >= 10
-
void DummySessionUpdateRequestFunc(SbDrmSystem drm_system,
void* context,
int ticket,
@@ -47,26 +45,6 @@
SbDrmStatus status,
const char* error_message) {}
-#else // SB_API_VERSION >= 10
-
-void DummySessionUpdateRequestFunc(SbDrmSystem drm_system,
- void* context,
- int ticket,
- const void* session_id,
- int session_id_size,
- const void* content,
- int content_size,
- const char* url) {}
-
-void DummySessionUpdatedFunc(SbDrmSystem drm_system,
- void* context,
- int ticket,
- const void* session_id,
- int session_id_size,
- bool succeeded) {}
-
-#endif // SB_API_VERSION >= 10
-
void DummySessionKeyStatusesChangedFunc(SbDrmSystem drm_system,
void* context,
const void* session_id,
@@ -81,21 +59,10 @@
int session_id_size) {}
SbDrmSystem CreateDummyDrmSystem(const char* key_system) {
-#if SB_API_VERSION >= 10
return SbDrmCreateSystem(
key_system, NULL /* context */, DummySessionUpdateRequestFunc,
DummySessionUpdatedFunc, DummySessionKeyStatusesChangedFunc,
DummyServerCertificateUpdatedFunc, DummySessionClosedFunc);
-#elif SB_HAS(DRM_SESSION_CLOSED)
- return SbDrmCreateSystem(
- key_system, NULL /* context */, DummySessionUpdateRequestFunc,
- DummySessionUpdatedFunc, DummySessionKeyStatusesChangedFunc,
- DummySessionClosedFunc);
-#else // SB_HAS(DRM_SESSION_CLOSED)
- return SbDrmCreateSystem(
- key_system, NULL /* context */, DummySessionUpdateRequestFunc,
- DummySessionUpdatedFunc, DummySessionKeyStatusesChangedFunc);
-#endif // SB_HAS(DRM_SESSION_CLOSED)
}
} // namespace nplb
diff --git a/src/starboard/nplb/drm_helpers.h b/src/starboard/nplb/drm_helpers.h
index f6d012d..c24b696 100644
--- a/src/starboard/nplb/drm_helpers.h
+++ b/src/starboard/nplb/drm_helpers.h
@@ -20,8 +20,6 @@
namespace starboard {
namespace nplb {
-#if SB_API_VERSION >= 10
-
void DummySessionUpdateRequestFunc(SbDrmSystem drm_system,
void* context,
int ticket,
@@ -48,26 +46,6 @@
SbDrmStatus status,
const char* error_message);
-#else // SB_API_VERSION >= 10
-
-void DummySessionUpdateRequestFunc(SbDrmSystem drm_system,
- void* context,
- int ticket,
- const void* session_id,
- int session_id_size,
- const void* content,
- int content_size,
- const char* url);
-
-void DummySessionUpdatedFunc(SbDrmSystem drm_system,
- void* context,
- int ticket,
- const void* session_id,
- int session_id_size,
- bool succeeded);
-
-#endif // SB_API_VERSION >= 10
-
void DummySessionKeyStatusesChangedFunc(SbDrmSystem drm_system,
void* context,
const void* session_id,
diff --git a/src/starboard/nplb/drm_is_server_certificate_updatable_test.cc b/src/starboard/nplb/drm_is_server_certificate_updatable_test.cc
index dff3ea2..94ea7dd 100644
--- a/src/starboard/nplb/drm_is_server_certificate_updatable_test.cc
+++ b/src/starboard/nplb/drm_is_server_certificate_updatable_test.cc
@@ -21,8 +21,6 @@
namespace nplb {
namespace {
-#if SB_API_VERSION >= 10
-
TEST(SbDrmIsServerCertificateUpdatableTest, SunnyDay) {
// Ensure that |SbDrmIsServerCertificateUpdatable| can be called over all key
// systems.
@@ -50,8 +48,6 @@
}
}
-#endif // SB_API_VERSION >= 10
-
} // namespace
} // namespace nplb
} // namespace starboard
diff --git a/src/starboard/nplb/drm_update_server_certificate_test.cc b/src/starboard/nplb/drm_update_server_certificate_test.cc
index 2646312..9d9e9c7 100644
--- a/src/starboard/nplb/drm_update_server_certificate_test.cc
+++ b/src/starboard/nplb/drm_update_server_certificate_test.cc
@@ -22,8 +22,6 @@
namespace nplb {
namespace {
-#if SB_API_VERSION >= 10
-
TEST(SbDrmUpdateServerCertificateTest, SunnyDay) {
// Ensure that |SbDrmUpdateServerCertificate| can be called over all key
// systems.
@@ -42,8 +40,6 @@
}
}
-#endif // SB_API_VERSION >= 10
-
} // namespace
} // namespace nplb
} // namespace starboard
diff --git a/src/starboard/nplb/extern_c_test.cc b/src/starboard/nplb/extern_c_test.cc
index d209d1e..63a56b1 100644
--- a/src/starboard/nplb/extern_c_test.cc
+++ b/src/starboard/nplb/extern_c_test.cc
@@ -24,7 +24,9 @@
#include "starboard/condition_variable.h"
#include "starboard/configuration.h"
#include "starboard/cpu_features.h"
+#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
#include "starboard/cryptography.h"
+#endif
#include "starboard/decode_target.h"
#include "starboard/directory.h"
#include "starboard/double.h"
diff --git a/src/starboard/nplb/include_all.c b/src/starboard/nplb/include_all.c
index b4c6892..39216fb 100644
--- a/src/starboard/nplb/include_all.c
+++ b/src/starboard/nplb/include_all.c
@@ -23,7 +23,9 @@
#include "starboard/condition_variable.h"
#include "starboard/configuration.h"
#include "starboard/cpu_features.h"
+#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
#include "starboard/cryptography.h"
+#endif
#include "starboard/decode_target.h"
#include "starboard/directory.h"
#include "starboard/double.h"
diff --git a/src/starboard/nplb/media_buffer_test.cc b/src/starboard/nplb/media_buffer_test.cc
index baa7811..6b0116b 100644
--- a/src/starboard/nplb/media_buffer_test.cc
+++ b/src/starboard/nplb/media_buffer_test.cc
@@ -16,7 +16,6 @@
#include "testing/gtest/include/gtest/gtest.h"
-#if SB_API_VERSION >= 10
namespace starboard {
namespace nplb {
namespace {
@@ -198,4 +197,3 @@
}
} // namespace nplb
} // namespace starboard
-#endif // SB_API_VERSION >= 10
diff --git a/src/starboard/nplb/media_can_play_mime_and_key_system_test.cc b/src/starboard/nplb/media_can_play_mime_and_key_system_test.cc
new file mode 100644
index 0000000..2e38c86
--- /dev/null
+++ b/src/starboard/nplb/media_can_play_mime_and_key_system_test.cc
@@ -0,0 +1,102 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/media.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace starboard {
+namespace shared {
+namespace starboard {
+namespace media {
+namespace {
+
+TEST(SbMediaCanPlayMimeAndKeySystem, SunnyDay) {
+ // Vp9
+ SbMediaCanPlayMimeAndKeySystem(
+ "video/webm; codecs=\"vp9\"; width=3840; height=2160; framerate=30; "
+ "bitrate=21823784; eotf=bt709",
+ "");
+ // Avc
+ SbMediaSupportType result = SbMediaCanPlayMimeAndKeySystem(
+ "video/mp4; codecs=\"avc1.4d4015\"; width=640; "
+ "height=360; framerate=30;",
+ "");
+ ASSERT_EQ(result, kSbMediaSupportTypeProbably);
+ // Hdr bt709
+ SbMediaCanPlayMimeAndKeySystem(
+ "video/webm; codecs=\"vp09.02.10.10\";eotf=bt709;width=640;height=360",
+ "");
+ // Aac
+ result = SbMediaCanPlayMimeAndKeySystem(
+ "audio/mp4; codecs=\"mp4a.40.2\"; channels=2", "");
+ ASSERT_EQ(result, kSbMediaSupportTypeProbably);
+ // Opus
+ SbMediaCanPlayMimeAndKeySystem("audio/webm; codecs=\"opus\"; channels=2", "");
+}
+
+TEST(SbMediaCanPlayMimeAndKeySystem, Invalid) {
+ // Invalid codec
+ SbMediaSupportType result =
+ SbMediaCanPlayMimeAndKeySystem("video/webm; codecs=\"abc\";", "");
+ ASSERT_EQ(result, kSbMediaSupportTypeNotSupported);
+
+ result = SbMediaCanPlayMimeAndKeySystem(
+ "video/webm; codecs=\"vp09.00.01.00.22\";", "");
+ ASSERT_EQ(result, kSbMediaSupportTypeNotSupported);
+
+ // Invalid container
+ result =
+ SbMediaCanPlayMimeAndKeySystem("video/abc; codecs=\"avc1.4d4015\";", "");
+ ASSERT_EQ(result, kSbMediaSupportTypeNotSupported);
+
+ // Invalid size
+ result = SbMediaCanPlayMimeAndKeySystem(
+ "video/mp4; codecs=\"avc1.4d4015\"; width=99999; height=1080;", "");
+ ASSERT_EQ(result, kSbMediaSupportTypeNotSupported);
+
+ result = SbMediaCanPlayMimeAndKeySystem(
+ "video/mp4; codecs=\"avc1.4d4015\"; width=1920; height=99999;", "");
+ ASSERT_EQ(result, kSbMediaSupportTypeNotSupported);
+
+ // Invalid bitrate
+ result = SbMediaCanPlayMimeAndKeySystem(
+ "video/mp4; codecs=\"avc1.4d4015\"; width=1920; height=1080; "
+ "bitrate=999999999;",
+ "");
+ ASSERT_EQ(result, kSbMediaSupportTypeNotSupported);
+
+ // Invalid eotf
+ result = SbMediaCanPlayMimeAndKeySystem(
+ "video/webm; codecs=\"vp09.02.10.10\"; width=1920; height=1080; "
+ "eotf=abc",
+ "");
+ ASSERT_EQ(result, kSbMediaSupportTypeNotSupported);
+
+ // Invalid channels
+ result = SbMediaCanPlayMimeAndKeySystem(
+ "audio/mp4; codecs=\"mp4a.40.2\"; channels=99", "");
+ ASSERT_EQ(result, kSbMediaSupportTypeNotSupported);
+
+ // Invalid keysystem
+ result = SbMediaCanPlayMimeAndKeySystem(
+ "video/mp4; codecs=\"avc1.4d4015\"; width=1920; height=1080;", "abc");
+ ASSERT_EQ(result, kSbMediaSupportTypeNotSupported);
+}
+
+} // namespace
+} // namespace media
+} // namespace starboard
+} // namespace shared
+} // namespace starboard
diff --git a/src/starboard/nplb/media_set_audio_write_duration_test.cc b/src/starboard/nplb/media_set_audio_write_duration_test.cc
index 73fc90d..77563b1 100644
--- a/src/starboard/nplb/media_set_audio_write_duration_test.cc
+++ b/src/starboard/nplb/media_set_audio_write_duration_test.cc
@@ -93,7 +93,7 @@
}
SbPlayerSampleInfo player_sample_info =
- dmp_reader_.GetPlayerSampleInfo(kSbMediaTypeAudio, ++index_);
+ dmp_reader_.GetPlayerSampleInfo(kSbMediaTypeAudio, index_++);
SbPlayerSampleInfo sample_info = {};
sample_info.buffer = player_sample_info.buffer;
@@ -249,10 +249,18 @@
WaitForPlayerState(kSbPlayerStatePresenting);
- // Check that the playback time is > 0.
- SbPlayerInfo2 info;
- SbPlayerGetInfo2(player, &info);
- ASSERT_GT(info.current_media_timestamp, 0);
+ // Wait until the playback time is > 0.
+ const SbTime kMaxWaitTime = 5 * kSbTimeSecond;
+ SbTime start_of_wait = SbTimeGetMonotonicNow();
+ SbPlayerInfo2 info = {};
+
+ while (SbTimeGetMonotonicNow() - start_of_wait < kMaxWaitTime &&
+ info.current_media_timestamp == 0) {
+ SbThreadSleep(kSbTimeMillisecond * 500);
+ SbPlayerGetInfo2(player, &info);
+ }
+
+ EXPECT_GT(info.current_media_timestamp, 0);
SbPlayerDestroy(player);
}
@@ -305,6 +313,9 @@
VideoDmpReader dmp_reader(ResolveTestFileName(filename).c_str());
SB_DCHECK(dmp_reader.number_of_audio_buffers() > 0);
if (SbMediaIsAudioSupported(dmp_reader.audio_codec(),
+#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+ "", // content_type
+#endif // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
dmp_reader.audio_bitrate())) {
test_params.push_back(filename);
}
diff --git a/src/starboard/nplb/memory_map_test.cc b/src/starboard/nplb/memory_map_test.cc
index c1e2137..c24bb36 100644
--- a/src/starboard/nplb/memory_map_test.cc
+++ b/src/starboard/nplb/memory_map_test.cc
@@ -201,7 +201,6 @@
original_function);
}
-#if SB_API_VERSION >= 10
// Cobalt can not map executable memory. If executable memory is needed, map
// non-executable memory first and use SbMemoryProtect to change memory accesss
// to executable.
@@ -219,10 +218,8 @@
EXPECT_FALSE(SbMemoryUnmap(memory, 0));
}
}
-#endif // 10
#endif // SB_CAN(MAP_EXECUTABLE_MEMORY)
-#if SB_API_VERSION >= 10
TEST(SbMemoryMapTest, CanChangeMemoryProtection) {
SbMemoryMapFlags all_from_flags[] = {
SbMemoryMapFlags(kSbMemoryMapProtectReserved),
@@ -292,7 +289,6 @@
}
}
}
-#endif // SB_API_VERSION >= 10
#endif // SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)
diff --git a/src/starboard/nplb/mutex_create_test.cc b/src/starboard/nplb/mutex_create_test.cc
index 62f0c74..1d072c9 100644
--- a/src/starboard/nplb/mutex_create_test.cc
+++ b/src/starboard/nplb/mutex_create_test.cc
@@ -32,13 +32,6 @@
SbMutex mutex;
EXPECT_TRUE(SbMutexCreate(&mutex));
EXPECT_TRUE(SbMutexDestroy(&mutex));
- // TODO: Remove those logs once we get the measurements.
- SB_LOG(INFO) << "SB_THREAD_TYPES: sizeof(SbMutex): " << sizeof(SbMutex);
- SB_LOG(INFO) << "SB_THREAD_TYPES: sizeof(SbThread): " << sizeof(SbThread);
- SB_LOG(INFO) << "SB_THREAD_TYPES: sizeof(SbOnceControl): "
- << sizeof(SbOnceControl);
- SB_LOG(INFO) << "SB_THREAD_TYPES: sizeof(SbConditionVariable): "
- << sizeof(SbConditionVariable);
}
TEST(SbMutexCreateTest, SunnyDayAutoInit) {
diff --git a/src/starboard/nplb/nplb.gyp b/src/starboard/nplb/nplb.gyp
index 37f0c7c..0f100ce 100644
--- a/src/starboard/nplb/nplb.gyp
+++ b/src/starboard/nplb/nplb.gyp
@@ -152,6 +152,7 @@
# TODO: Separate functions tested by media buffer test into multiple
# files.
'media_buffer_test.cc',
+ 'media_can_play_mime_and_key_system_test.cc',
'memory_align_to_page_size_test.cc',
'memory_allocate_aligned_test.cc',
'memory_allocate_test.cc',
diff --git a/src/starboard/nplb/nplb_evergreen_compat_tests/checks.h b/src/starboard/nplb/nplb_evergreen_compat_tests/checks.h
new file mode 100644
index 0000000..0dbff4e
--- /dev/null
+++ b/src/starboard/nplb/nplb_evergreen_compat_tests/checks.h
@@ -0,0 +1,41 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_NPLB_NPLB_EVERGREEN_COMPAT_TESTS_CHECKS_H_
+#define STARBOARD_NPLB_NPLB_EVERGREEN_COMPAT_TESTS_CHECKS_H_
+
+#include "starboard/configuration.h"
+
+#if SB_IS(EVERGREEN_COMPATIBLE)
+
+#if SB_API_VERSION < 12
+#error "Evergreen requires starboard version 12 or higher!"
+#endif
+
+#if SB_API_VERSION < SB_STORAGE_PATH_VERSION
+#error \
+ "Evergreen requires support for the kSbSystemPathStorageDirectory" \
+ " system property!"
+#endif
+
+#if SB_API_VERSION < SB_MMAP_REQUIRED_VERSION
+#error "Evergreen requires memory mapping!"
+#endif
+
+#if !SB_CAN(MAP_EXECUTABLE_MEMORY)
+#error "Evergreen requires executable memory support!"
+#endif
+
+#endif // SB_IS(EVERGREEN_COMPATIBLE)
+#endif // STARBOARD_NPLB_NPLB_EVERGREEN_COMPAT_TESTS_CHECKS_H_
diff --git a/src/starboard/nplb/nplb_evergreen_compat_tests/executable_memory_test.cc b/src/starboard/nplb/nplb_evergreen_compat_tests/executable_memory_test.cc
new file mode 100644
index 0000000..ece5aa3
--- /dev/null
+++ b/src/starboard/nplb/nplb_evergreen_compat_tests/executable_memory_test.cc
@@ -0,0 +1,52 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/memory.h"
+#include "starboard/nplb/nplb_evergreen_compat_tests/checks.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if SB_IS(EVERGREEN_COMPATIBLE)
+
+namespace starboard {
+namespace nplb {
+namespace nplb_evergreen_compat_tests {
+
+namespace {
+
+const size_t kSize = 30 * 1024 * 1024;
+const size_t kSmallerSize = 15 * 1024 * 1024;
+
+class ExecutableMemoryTest : public ::testing::Test {
+ protected:
+ ExecutableMemoryTest() {}
+ ~ExecutableMemoryTest() {}
+};
+
+TEST_F(ExecutableMemoryTest, VerifyMemoryProtection) {
+ void* memory =
+ SbMemoryMap(kSize, kSbMemoryMapProtectWrite, "evergreen_buffer");
+ ASSERT_NE(SB_MEMORY_MAP_FAILED, memory);
+ SbMemorySet(memory, 0, kSize);
+ ASSERT_TRUE(SbMemoryProtect(
+ memory, kSmallerSize, kSbMemoryMapProtectRead | kSbMemoryMapProtectExec));
+ SbMemoryUnmap(memory, kSize);
+ EXPECT_TRUE(true);
+}
+
+} // namespace
+} // namespace nplb_evergreen_compat_tests
+} // namespace nplb
+} // namespace starboard
+
+#endif // SB_IS(EVERGREEN_COMPATIBLE)
diff --git a/src/starboard/nplb/nplb_evergreen_compat_tests/nplb_evergreen_compat_tests.gyp b/src/starboard/nplb/nplb_evergreen_compat_tests/nplb_evergreen_compat_tests.gyp
new file mode 100644
index 0000000..bcca8be
--- /dev/null
+++ b/src/starboard/nplb/nplb_evergreen_compat_tests/nplb_evergreen_compat_tests.gyp
@@ -0,0 +1,45 @@
+# Copyright 2020 The Cobalt Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'nplb_evergreen_compat_tests',
+ 'type': '<(gtest_target_type)',
+ 'sources': [
+ 'checks.h',
+ 'executable_memory_test.cc',
+ 'sabi_test.cc',
+ 'storage_test.cc',
+ '<(DEPTH)/starboard/common/test_main.cc',
+ ],
+ 'dependencies': [
+ '<(DEPTH)/starboard/starboard.gyp:starboard',
+ '<(DEPTH)/testing/gmock.gyp:gmock',
+ '<(DEPTH)/testing/gtest.gyp:gtest',
+ ],
+ },
+ {
+ 'target_name': 'nplb_evergreen_compat_tests_deploy',
+ 'type': 'none',
+ 'dependencies': [
+ 'nplb_evergreen_compat_tests',
+ ],
+ 'variables': {
+ 'executable_name': 'nplb_evergreen_compat_tests',
+ },
+ 'includes': [ '<(DEPTH)/starboard/build/deploy.gypi' ],
+ },
+ ],
+}
diff --git a/src/starboard/nplb/nplb_evergreen_compat_tests/sabi_test.cc b/src/starboard/nplb/nplb_evergreen_compat_tests/sabi_test.cc
new file mode 100644
index 0000000..08560cb
--- /dev/null
+++ b/src/starboard/nplb/nplb_evergreen_compat_tests/sabi_test.cc
@@ -0,0 +1,120 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <iostream>
+#include <set>
+#include <string>
+
+#include "starboard/configuration.h"
+#include "starboard/nplb/nplb_evergreen_compat_tests/checks.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if SB_IS(EVERGREEN_COMPATIBLE)
+
+namespace starboard {
+namespace nplb {
+namespace nplb_evergreen_compat_tests {
+
+namespace {
+
+const char* kSabiJsonIdArmHardfp =
+ "{\"alignment_char\":1,\"alignment_double\":8,\"alignment_float\":4,"
+ "\"alignment_int\":4,\"alignment_llong\":8,\"alignment_long\":4,"
+ "\"alignment_pointer\":4,\"alignment_short\":2,\"calling_convention\":"
+ "\"eabi\",\"endianness\":\"little\",\"floating_point_abi\":\"hard\","
+ "\"floating_point_fpu\":\"vfpv3\",\"sb_api_version\":12,\"signedness_of_"
+ "char\":\"signed\",\"signedness_of_enum\":\"signed\",\"size_of_char\":1,"
+ "\"size_of_double\":8,\"size_of_enum\":4,\"size_of_float\":4,\"size_of_"
+ "int\":4,\"size_of_llong\":8,\"size_of_long\":4,\"size_of_pointer\":4,"
+ "\"size_of_short\":2,\"target_arch\":\"arm\",\"target_arch_sub\":\"v7a\","
+ "\"word_size\":32}";
+
+const char* kSabiJsonIdArmSoftfp =
+ "{\"alignment_char\":1,\"alignment_double\":8,\"alignment_float\":4,"
+ "\"alignment_int\":4,\"alignment_llong\":8,\"alignment_long\":4,"
+ "\"alignment_pointer\":4,\"alignment_short\":2,\"calling_convention\":"
+ "\"eabi\",\"endianness\":\"little\",\"floating_point_abi\":\"softfp\","
+ "\"floating_point_fpu\":\"vfpv3\",\"sb_api_version\":12,\"signedness_of_"
+ "char\":\"signed\",\"signedness_of_enum\":\"signed\",\"size_of_char\":1,"
+ "\"size_of_double\":8,\"size_of_enum\":4,\"size_of_float\":4,\"size_of_"
+ "int\":4,\"size_of_llong\":8,\"size_of_long\":4,\"size_of_pointer\":4,"
+ "\"size_of_short\":2,\"target_arch\":\"arm\",\"target_arch_sub\":\"v7a\","
+ "\"word_size\":32}";
+
+const char* kSabiJsonIdArm64 =
+ "{\"alignment_char\":1,\"alignment_double\":8,\"alignment_float\":4,"
+ "\"alignment_int\":4,\"alignment_llong\":8,\"alignment_long\":8,"
+ "\"alignment_pointer\":8,\"alignment_short\":2,\"calling_convention\":"
+ "\"aarch64\",\"endianness\":\"little\",\"floating_point_abi\":\"\","
+ "\"floating_point_fpu\":\"\",\"sb_api_version\":12,\"signedness_of_char\":"
+ "\"signed\",\"signedness_of_enum\":\"signed\",\"size_of_char\":1,\"size_of_"
+ "double\":8,\"size_of_enum\":4,\"size_of_float\":4,\"size_of_int\":4,"
+ "\"size_of_llong\":8,\"size_of_long\":8,\"size_of_pointer\":8,\"size_of_"
+ "short\":2,\"target_arch\":\"arm64\",\"target_arch_sub\":\"v8a\",\"word_"
+ "size\":64}";
+
+const char* kSabiJsonIdX86 =
+ "{\"alignment_char\":1,\"alignment_double\":8,\"alignment_float\":4,"
+ "\"alignment_int\":4,\"alignment_llong\":8,\"alignment_long\":4,"
+ "\"alignment_pointer\":4,\"alignment_short\":2,\"calling_convention\":"
+ "\"sysv\",\"endianness\":\"little\",\"floating_point_abi\":\"\",\"floating_"
+ "point_fpu\":\"\",\"sb_api_version\":12,\"signedness_of_char\":\"signed\","
+ "\"signedness_of_enum\":\"signed\",\"size_of_char\":1,\"size_of_double\":8,"
+ "\"size_of_enum\":4,\"size_of_float\":4,\"size_of_int\":4,\"size_of_"
+ "llong\":8,\"size_of_long\":4,\"size_of_pointer\":4,\"size_of_short\":2,"
+ "\"target_arch\":\"x86\",\"target_arch_sub\":\"\",\"word_size\":32}";
+
+const char* kSabiJsonIdX64Sysv =
+ "{\"alignment_char\":1,\"alignment_double\":8,\"alignment_float\":4,"
+ "\"alignment_int\":4,\"alignment_llong\":8,\"alignment_long\":8,"
+ "\"alignment_pointer\":8,\"alignment_short\":2,\"calling_convention\":"
+ "\"sysv\",\"endianness\":\"little\",\"floating_point_abi\":\"\",\"floating_"
+ "point_fpu\":\"\",\"sb_api_version\":12,\"signedness_of_char\":\"signed\","
+ "\"signedness_of_enum\":\"signed\",\"size_of_char\":1,\"size_of_double\":8,"
+ "\"size_of_enum\":4,\"size_of_float\":4,\"size_of_int\":4,\"size_of_"
+ "llong\":8,\"size_of_long\":8,\"size_of_pointer\":8,\"size_of_short\":2,"
+ "\"target_arch\":\"x64\",\"target_arch_sub\":\"\",\"word_size\":64}";
+
+class SabiTest : public ::testing::Test {
+ protected:
+ SabiTest() {}
+ ~SabiTest() {}
+};
+
+TEST_F(SabiTest, VerifySABI) {
+ std::set<std::string> sabi_set;
+ sabi_set.insert(kSabiJsonIdArmHardfp);
+ sabi_set.insert(kSabiJsonIdArmSoftfp);
+ sabi_set.insert(kSabiJsonIdArm64);
+ sabi_set.insert(kSabiJsonIdX86);
+ sabi_set.insert(kSabiJsonIdX64Sysv);
+
+ ASSERT_NE(sabi_set.find(SB_SABI_JSON_ID), sabi_set.end())
+ << "Unsupported SABI configuration. " << std::endl
+ << "The platform should use one of the predefined SABI json files!"
+ << std::endl
+ << "Currently supported are: " << std::endl
+ << " starboard/sabi/arm/hardfp/sabi.json" << std::endl
+ << " starboard/sabi/arm/softfp/sabi.json" << std::endl
+ << " starboard/sabi/arm64/sabi.json" << std::endl
+ << " starboard/sabi/x86/sabi.json" << std::endl
+ << " starboard/sabi/x64/sysv/sabi.json" << std::endl;
+}
+
+} // namespace
+} // namespace nplb_evergreen_compat_tests
+} // namespace nplb
+} // namespace starboard
+
+#endif // SB_IS(EVERGREEN_COMPATIBLE)
diff --git a/src/starboard/nplb/nplb_evergreen_compat_tests/storage_test.cc b/src/starboard/nplb/nplb_evergreen_compat_tests/storage_test.cc
new file mode 100644
index 0000000..8ac05ac
--- /dev/null
+++ b/src/starboard/nplb/nplb_evergreen_compat_tests/storage_test.cc
@@ -0,0 +1,93 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <string>
+#include <vector>
+
+#include "starboard/common/log.h"
+#include "starboard/configuration.h"
+#include "starboard/file.h"
+#include "starboard/memory.h"
+#include "starboard/nplb/nplb_evergreen_compat_tests/checks.h"
+#include "starboard/system.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if SB_IS(EVERGREEN_COMPATIBLE)
+
+namespace starboard {
+namespace nplb {
+namespace nplb_evergreen_compat_tests {
+
+namespace {
+
+const char kFileName[] = "test_file.data";
+const size_t kBufSize = 128 * 1024 * 1024; // 128 MB
+
+class StorageTest : public ::testing::Test {
+ protected:
+ StorageTest() {}
+ ~StorageTest() {}
+};
+
+void WriteBuffer(const char* file_path,
+ const char* buffer,
+ size_t buffer_size) {
+ SbFileError error;
+ ScopedFile file(file_path, kSbFileOpenAlways | kSbFileWrite, nullptr, &error);
+ ASSERT_EQ(kSbFileOk, error) << "Failed to open file for writing";
+ int bytes_written = file.WriteAll(buffer, buffer_size);
+ ASSERT_EQ(kBufSize, bytes_written);
+}
+
+void ReadBuffer(const char* file_path, char* buffer, size_t buffer_size) {
+ SbFileError error;
+ ScopedFile file(file_path, kSbFileOpenOnly | kSbFileRead, nullptr, &error);
+ ASSERT_EQ(kSbFileOk, error) << "Failed to open file for reading";
+ int count = file.ReadAll(buffer, buffer_size);
+ ASSERT_EQ(kBufSize, count);
+}
+
+TEST_F(StorageTest, VerifyStorageDirectory) {
+ std::vector<char> storage_dir(kSbFileMaxPath);
+ ASSERT_TRUE(SbSystemGetPath(kSbSystemPathStorageDirectory, storage_dir.data(),
+ kSbFileMaxPath));
+
+ std::string file_path = storage_dir.data();
+ file_path += kSbFileSepString;
+ file_path += kFileName;
+ SB_LOG(INFO) << "file: " << file_path;
+
+ std::vector<char> buf(kBufSize);
+ SbMemorySet(buf.data(), 'A', kBufSize);
+
+ WriteBuffer(file_path.c_str(), buf.data(), kBufSize);
+
+ SbMemorySet(buf.data(), 0, kBufSize);
+
+ ReadBuffer(file_path.c_str(), buf.data(), kBufSize);
+
+ for (int i = 0; i < kBufSize; i++) {
+ ASSERT_EQ('A', buf[i]);
+ }
+
+ ASSERT_TRUE(SbFileDelete(file_path.data()));
+ ASSERT_FALSE(SbFileExists(file_path.data()));
+}
+
+} // namespace
+} // namespace nplb_evergreen_compat_tests
+} // namespace nplb
+} // namespace starboard
+
+#endif // SB_IS(EVERGREEN_COMPATIBLE)
diff --git a/src/starboard/nplb/player_create_test.cc b/src/starboard/nplb/player_create_test.cc
index 5c4e6a2..294db6a 100644
--- a/src/starboard/nplb/player_create_test.cc
+++ b/src/starboard/nplb/player_create_test.cc
@@ -48,12 +48,10 @@
SbPlayerState state,
int ticket) {}
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
void DummyErrorFunc(SbPlayer player,
void* context,
SbPlayerError error,
const char* message) {}
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
SbPlayer CallSbPlayerCreate(
SbWindow window,
@@ -93,18 +91,13 @@
#else // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
return SbPlayerCreate(window, video_codec, audio_codec,
-#if SB_API_VERSION < 10
- SB_PLAYER_NO_DURATION,
-#endif // SB_API_VERSION < 10
kSbDrmSystemInvalid, audio_sample_info,
#if SB_API_VERSION >= 11
max_video_capabilities,
#endif // SB_API_VERSION >= 11
sample_deallocate_func, decoder_status_func,
player_status_func,
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
DummyErrorFunc,
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
context, output_mode, context_provider);
#endif // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
@@ -152,7 +145,6 @@
}
}
-#if SB_API_VERSION >= 10
TEST_F(SbPlayerTest, NullCallbacks) {
SbMediaAudioSampleInfo audio_sample_info =
CreateAudioSampleInfo(kSbMediaAudioCodecAac);
@@ -206,8 +198,6 @@
SbPlayerDestroy(player);
}
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
-
#if SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
{
@@ -243,19 +233,10 @@
}
#endif // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
-
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
}
}
-#endif // SB_API_VERSION >= 10
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || \
- defined(SB_HAS_AUDIOLESS_VIDEO)
TEST_F(SbPlayerTest, Audioless) {
- if (!kSbHasAudiolessVideo) {
- return;
- }
-
SbMediaVideoCodec kVideoCodec = kSbMediaVideoCodecH264;
SbPlayerOutputMode output_modes[] = {kSbPlayerOutputModeDecodeToTexture,
@@ -283,10 +264,7 @@
SbPlayerDestroy(player);
}
}
-#endif // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
- // defined(SB_HAS_AUDIOLESS_VIDEO)
-#if SB_API_VERSION >= 10
TEST_F(SbPlayerTest, AudioOnly) {
SbMediaAudioSampleInfo audio_sample_info =
CreateAudioSampleInfo(kSbMediaAudioCodecAac);
@@ -419,7 +397,6 @@
SbPlayerDestroy(player);
}
}
-#endif // SB_API_VERSION >= 10
} // namespace
} // namespace nplb
diff --git a/src/starboard/nplb/system_get_property_test.cc b/src/starboard/nplb/system_get_property_test.cc
index 46716ee..1fe8f97 100644
--- a/src/starboard/nplb/system_get_property_test.cc
+++ b/src/starboard/nplb/system_get_property_test.cc
@@ -133,9 +133,6 @@
UnmodifiedOnFailureTest(kSbSystemPropertyNetworkOperatorName, __LINE__);
#endif
UnmodifiedOnFailureTest(kSbSystemPropertyPlatformName, __LINE__);
-#if SB_API_VERSION < 10
- UnmodifiedOnFailureTest(kSbSystemPropertyPlatformUuid, __LINE__);
-#endif // SB_API_VERSION < 10
UnmodifiedOnFailureTest(kSbSystemPropertySpeechApiKey, __LINE__);
#if SB_API_VERSION >= 5
UnmodifiedOnFailureTest(kSbSystemPropertyUserAgentAuxField, __LINE__);
diff --git a/src/starboard/once.h b/src/starboard/once.h
index 076e3c7..98e8763 100644
--- a/src/starboard/once.h
+++ b/src/starboard/once.h
@@ -31,7 +31,7 @@
#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
// Max size of the SbOnceControl type.
-#define SB_ONCE_MAX_SIZE 16
+#define SB_ONCE_MAX_SIZE 64
// An opaque handle to a once control type with
// reserved memory buffer of size SB_ONCE_MAX_SIZE and
diff --git a/src/starboard/player.h b/src/starboard/player.h
index 2ea9de1..c830893 100644
--- a/src/starboard/player.h
+++ b/src/starboard/player.h
@@ -70,31 +70,21 @@
// The player has been destroyed, and will send no more callbacks.
kSbPlayerStateDestroyed,
-#if !SB_HAS(PLAYER_ERROR_MESSAGE)
- // The player encountered an error. It expects an SbPlayerDestroy() call
- // to tear down the player. Calls to other functions may be ignored and
- // callbacks may not be triggered.
- kSbPlayerStateError,
-#endif // !SB_HAS(PLAYER_ERROR_MESSAGE)
} SbPlayerState;
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
typedef enum SbPlayerError {
kSbPlayerErrorDecode,
-#if SB_API_VERSION >= 10
// The playback capability of the player has changed, likely because of a
// change of the system environment. For example, the system may support vp9
// decoding with an external GPU. When the external GPU is detached, this
// error code can signal the app to retry the playback, possibly with h264.
kSbPlayerErrorCapabilityChanged,
-#endif // SB_API_VERSION >= 10
#if SB_API_VERSION >= 11
// The max value of SbPlayer error type. It should always at the bottom
// of SbPlayerError and never be used.
kSbPlayerErrorMax,
#endif // SB_API_VERSION >= 11
} SbPlayerError;
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
typedef enum SbPlayerOutputMode {
// Requests for SbPlayer to produce an OpenGL texture that the client must
@@ -209,56 +199,6 @@
const SbDrmSampleInfo* drm_info;
} SbPlayerSampleInfo;
-#if SB_API_VERSION < 10
-// Information about the current media playback state.
-typedef struct SbPlayerInfo {
- // The position of the playback head, as precisely as possible, in 90KHz ticks
- // (PTS).
- SbMediaTime current_media_pts;
-
- // The known duration of the currently playing media stream, in 90KHz ticks
- // (PTS).
- SbMediaTime duration_pts;
-
- // The result of getStartDate for the currently playing media stream, in
- // microseconds since the epoch of January 1, 1601 UTC.
- SbTime start_date;
-
- // The width of the currently displayed frame, in pixels, or 0 if not provided
- // by this player.
- int frame_width;
-
- // The height of the currently displayed frame, in pixels, or 0 if not
- // provided by this player.
- int frame_height;
-
- // Whether playback is currently paused.
- bool is_paused;
-
- // The current player volume in [0, 1].
- double volume;
-
- // The number of video frames sent to the player since the creation of the
- // player.
- int total_video_frames;
-
- // The number of video frames decoded but not displayed since the creation of
- // the player.
- int dropped_video_frames;
-
- // The number of video frames that failed to be decoded since the creation of
- // the player.
- int corrupted_video_frames;
-
- // The rate of playback. The video is played back in a speed that is
- // proportional to this. By default it is 1.0 which indicates that the
- // playback is at normal speed. When it is greater than one, the video is
- // played in a faster than normal speed. When it is less than one, the video
- // is played in a slower than normal speed. Negative speeds are not
- // supported.
- double playback_rate;
-} SbPlayerInfo;
-#else // SB_API_VERSION < 10
// Information about the current media playback state.
typedef struct SbPlayerInfo2 {
// The position of the playback head, as precisely as possible, in
@@ -306,7 +246,6 @@
// supported.
double playback_rate;
} SbPlayerInfo2;
-#endif // SB_API_VERSION < 10
// An opaque handle to an implementation-private structure representing a
// player.
@@ -338,7 +277,6 @@
SbPlayerState state,
int ticket);
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
// Callback for player errors, that may set a |message|.
// |error|: indicates the error code.
// |message|: provides specific informative diagnostic message about the error
@@ -348,7 +286,6 @@
void* context,
SbPlayerError error,
const char* message);
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
// Callback to free the given sample buffer data. When more than one buffer
// are sent in SbPlayerWriteSample(), the implementation only has to call this
@@ -402,27 +339,13 @@
// |video_codec|: The video codec used for the player. If |video_codec| is
// |kSbMediaVideoCodecNone|, the player is an audio-only player. If
// |video_codec| is any other value, the player is an audio/video decoder.
-#if SB_API_VERSION >= 10
// This can be set to |kSbMediaVideoCodecNone| to play a video with only an
// audio track.
-#endif // SB_API_VERSION >= 10
//
-// |audio_codec|: The audio codec used for the player. The value should never
-// be |kSbMediaAudioCodecNone|. In addition, the caller must provide a
-// populated |audio_sample_info| if the audio codec is
-// |kSbMediaAudioCodecAac|.
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || \
- SB_HAS(AUDIOLESS_VIDEO)
-// If |kSbHasAudiolessVideo| is |true| or SB_HAS(AUDIOLESS_VIDEO), this can
-// be set to |kSbMediaAudioCodecNone| to play a video without any audio
+// |audio_codec|: The audio codec used for the player. The caller must provide a
+// populated |audio_sample_info| if audio codec is |kSbMediaAudioCodecAac|.
+// Can be set to |kSbMediaAudioCodecNone| to play a video without any audio
// track. In such case |audio_sample_info| must be NULL.
-#endif // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
- // SB_HAS(AUDIOLESS_VIDEO)
-//
-#if SB_API_VERSION < 10
-// |duration_pts|: The expected media duration in 90KHz ticks (PTS). It may be
-// set to |SB_PLAYER_NO_DURATION| for live streams.
-#endif // SB_API_VERSION < 10
//
// |drm_system|: If the media stream has encrypted portions, then this
// parameter provides an appropriate DRM system, created with
@@ -430,18 +353,26 @@
// then |drm_system| may be |kSbDrmSystemInvalid|.
//
#if SB_API_VERSION < 11
+//
// |audio_header|: |audio_header| is same as |audio_sample_info| in old
-// starboard version.
+// starboard version. When |audio_codec| is |kSbMediaAudioCodecNone|, this
+// must be set to NULL.
+//
#else // SB_API_VERSION < 11
+//
// |audio_sample_info|: Note that the caller must provide a populated
// |audio_sample_info| if the audio codec is |kSbMediaAudioCodecAac|.
// Otherwise, |audio_sample_info| can be NULL. See media.h for the format of
// the |SbMediaAudioSampleInfo| struct.
+//
#endif // SB_API_VERSION < 11
+//
// Note that |audio_specific_config| is a pointer and the content it points to
// is no longer valid after this function returns. The implementation has to
// make a copy of the content if it is needed after the function returns.
+//
#if SB_API_VERSION >= 11
+//
// |max_video_capabilities|: This string communicates the max video capabilities
// required to the platform. The web app will not provide a video stream
// exceeding the maximums described by this parameter. Allows the platform to
@@ -453,12 +384,7 @@
// second higher than 15 fps. When the maximums are unknown, this will be set
// to NULL.
#endif // SB_API_VERSION >= 11
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || \
- SB_HAS(AUDIOLESS_VIDEO)
-// If |kSbHasAudiolessVideo| is |true| or SB_HAS(AUDIOLESS_VIDEO), when
-// |audio_codec| is |kSbMediaAudioCodecNone|, this must be set to NULL.
-#endif // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
- // SB_HAS(AUDIOLESS_VIDEO)
+
//
// |sample_deallocator_func|: If not |NULL|, the player calls this function
// on an internal thread to free the sample buffers passed into
@@ -474,11 +400,9 @@
// should be done on this thread. Rather, it should just signal the client
// thread interacting with the decoder.
//
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
// |player_error_func|: If not |NULL|, the player calls this function on an
// internal thread to provide an update on the error status. This callback is
// responsible for setting the media error message.
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
//
// |context|: This is passed to all callbacks and is generally used to point
// at a class or struct that contains state associated with the player.
@@ -497,11 +421,9 @@
// the provider is not given, the player will fail by returning
// |kSbPlayerInvalid|.
//
-#if SB_API_VERSION >= 10
// If |NULL| is passed to any of the callbacks (|sample_deallocator_func|,
// |decoder_status_func|, |player_status_func|, or |player_error_func| if it
// applies), then |kSbPlayerInvalid| must be returned.
-#endif // SB_API_VERSION >= 10
#if SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
@@ -521,9 +443,6 @@
SbPlayerCreate(SbWindow window,
SbMediaVideoCodec video_codec,
SbMediaAudioCodec audio_codec,
-#if SB_API_VERSION < 10
- SbMediaTime duration_pts,
-#endif // SB_API_VERSION < 10
SbDrmSystem drm_system,
#if SB_API_VERSION < 11
const SbMediaAudioHeader* audio_header,
@@ -536,9 +455,7 @@
SbPlayerDeallocateSampleFunc sample_deallocate_func,
SbPlayerDecoderStatusFunc decoder_status_func,
SbPlayerStatusFunc player_status_func,
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
SbPlayerErrorFunc player_error_func,
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
void* context,
SbPlayerOutputMode output_mode,
SbDecodeTargetGraphicsContextProvider* context_provider);
@@ -586,39 +503,6 @@
// |player|: The player to be destroyed.
SB_EXPORT void SbPlayerDestroy(SbPlayer player);
-#if SB_API_VERSION < 10
-// Tells the player to freeze playback (if playback has already started),
-// reset or flush the decoder pipeline, and go back to the Prerolling state.
-// The player should restart playback once it can display the frame at
-// |seek_to_pts|, or the closest it can get. (Some players can only seek to
-// I-Frames, for example.)
-//
-// - Seek must be called before samples are sent when starting playback for
-// the first time, or the client never receives the
-// |kSbPlayerDecoderStateNeedsData| signal.
-// - A call to seek may interrupt another seek.
-// - After this function is called, the client should not send any more audio
-// or video samples until |SbPlayerDecoderStatusFunc| is called back with
-// |kSbPlayerDecoderStateNeedsData| for each required media type.
-// |SbPlayerDecoderStatusFunc| is the |decoder_status_func| callback function
-// that was specified when the player was created (SbPlayerCreate).
-//
-// |player|: The SbPlayer in which the seek operation is being performed.
-// |seek_to_pts|: The frame at which playback should begin.
-// |ticket|: A user-supplied unique ID that is be passed to all subsequent
-// |SbPlayerDecoderStatusFunc| calls. (That is the |decoder_status_func|
-// callback function specified when calling SbPlayerCreate.)
-//
-// The |ticket| value is used to filter calls that may have been in flight
-// when SbPlayerSeek was called. To be very specific, once SbPlayerSeek has
-// been called with ticket X, a client should ignore all
-// |SbPlayerDecoderStatusFunc| calls that do not pass in ticket X.
-
-// presubmit: allow sb_export mismatch
-SB_EXPORT void SbPlayerSeek(SbPlayer player,
- SbMediaTime seek_to_pts,
- int ticket);
-#else // SB_API_VERSION < 10
// SbPlayerSeek2 is like the deprecated SbPlayerSeek, but accepts SbTime
// |seek_to_timestamp| instead of SbMediaTime |seek_to_pts|.
@@ -652,7 +536,6 @@
SB_EXPORT void SbPlayerSeek2(SbPlayer player,
SbTime seek_to_timestamp,
int ticket);
-#endif // SB_API_VERSION < 10
// Writes a single sample of the given media type to |player|'s input stream.
// Its data may be passed in via more than one buffers. The lifetime of
@@ -688,18 +571,7 @@
// |NULL|.
// |sample_drm_info|: The DRM system related info for the media sample. This
// value is required for encrypted samples. Otherwise, it must be |NULL|.
-#if SB_API_VERSION < 10
-// presubmit: allow sb_export mismatch
-SB_EXPORT void SbPlayerWriteSample(
- SbPlayer player,
- SbMediaType sample_type,
- const void* const* sample_buffers,
- const int* sample_buffer_sizes,
- int number_of_sample_buffers,
- SbMediaTime sample_pts,
- const SbMediaVideoSampleInfo* video_sample_info,
- const SbDrmSampleInfo* sample_drm_info);
-#else // SB_API_VERSION < 10
+
// SbPlayerWriteSample2 is like the deprecated SbPlayerWriteSample, but accepts
// SbTime |sample_timestamp| instead of SbMediaTime |sample_pts|, and also
// allows writing of multiple samples in one SbPlayerWriteSample2() call.
@@ -744,8 +616,6 @@
SbPlayer player,
SbMediaType sample_type);
-#endif // SB_API_VERSION < 10
-
// Writes a marker to |player|'s input stream of |stream_type| indicating that
// there are no more samples for that media type for the remainder of this
// media stream. This marker is invalidated, along with the rest of the stream's
@@ -803,17 +673,6 @@
// value of |1.0| means that it should be played at full volume.
SB_EXPORT void SbPlayerSetVolume(SbPlayer player, double volume);
-#if SB_API_VERSION < 10
-// Gets a snapshot of the current player state and writes it to
-// |out_player_info|. This function may be called very frequently and is
-// expected to be inexpensive.
-//
-// |player|: The player about which information is being retrieved.
-// |out_player_info|: The information retrieved for the player.
-
-// presubmit: allow sb_export mismatch
-SB_EXPORT void SbPlayerGetInfo(SbPlayer player, SbPlayerInfo* out_player_info);
-#else // SB_API_VERSION < 10
// SbPlayerGetInfo2 is like the deprecated SbPlayerGetInfo, but accepts
// SbPlayerInfo2* |out_player_info2| instead of SbPlayerInfo |out_player_info|.
@@ -825,7 +684,6 @@
// |out_player_info|: The information retrieved for the player.
SB_EXPORT void SbPlayerGetInfo2(SbPlayer player,
SbPlayerInfo2* out_player_info2);
-#endif // SB_API_VERSION < 10
// Given a player created with the kSbPlayerOutputModeDecodeToTexture
// output mode, it will return a SbDecodeTarget representing the current frame
diff --git a/src/starboard/raspi/2/gyp_configuration.gypi b/src/starboard/raspi/2/gyp_configuration.gypi
index a5617d4..86a20c1 100644
--- a/src/starboard/raspi/2/gyp_configuration.gypi
+++ b/src/starboard/raspi/2/gyp_configuration.gypi
@@ -13,6 +13,12 @@
# limitations under the License.
{
+ 'variables': {
+ 'variables': {
+ 'sb_evergreen_compatible': 1,
+ },
+ },
+
'target_defaults': {
'default_configuration': 'raspi-2_debug',
'configurations': {
diff --git a/src/starboard/raspi/2/mozjs/atomic_public.h b/src/starboard/raspi/2/mozjs/atomic_public.h
deleted file mode 100644
index 5ad1ce6..0000000
--- a/src/starboard/raspi/2/mozjs/atomic_public.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2018 The Cobalt Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef STARBOARD_RASPI_2_MOZJS_ATOMIC_PUBLIC_H_
-#define STARBOARD_RASPI_2_MOZJS_ATOMIC_PUBLIC_H_
-
-#include "starboard/raspi/2/atomic_public.h"
-
-#endif // STARBOARD_RASPI_2_MOZJS_ATOMIC_PUBLIC_H_
diff --git a/src/starboard/raspi/2/mozjs/configuration_public.h b/src/starboard/raspi/2/mozjs/configuration_public.h
deleted file mode 100644
index 3b4427e..0000000
--- a/src/starboard/raspi/2/mozjs/configuration_public.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2018 The Cobalt Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// The Starboard configuration for Raspberry PI 2 Raspbian.
-
-// Other source files should never include this header directly, but should
-// include the generic "starboard/configuration.h" instead.
-
-#ifndef STARBOARD_RASPI_2_MOZJS_CONFIGURATION_PUBLIC_H_
-#define STARBOARD_RASPI_2_MOZJS_CONFIGURATION_PUBLIC_H_
-
-#include "starboard/raspi/2/configuration_public.h"
-
-#endif // STARBOARD_RASPI_2_MOZJS_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/raspi/2/mozjs/gyp_configuration.gypi b/src/starboard/raspi/2/mozjs/gyp_configuration.gypi
deleted file mode 100644
index 4cc3212..0000000
--- a/src/starboard/raspi/2/mozjs/gyp_configuration.gypi
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright 2017 The Cobalt Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-{
- 'target_defaults': {
- 'default_configuration': 'raspi-2-mozjs_debug',
- 'configurations': {
- 'raspi-2-mozjs_debug': {
- 'inherit_from': ['debug_base'],
- },
- 'raspi-2-mozjs_devel': {
- 'inherit_from': ['devel_base'],
- },
- 'raspi-2-mozjs_qa': {
- 'inherit_from': ['qa_base'],
- },
- 'raspi-2-mozjs_gold': {
- 'inherit_from': ['gold_base'],
- },
- }, # end of configurations
- },
-
- 'includes': [
- '../architecture.gypi',
- '../../shared/gyp_configuration.gypi',
- '<(DEPTH)/starboard/sabi/sabi.gypi',
- ],
-}
diff --git a/src/starboard/raspi/2/mozjs/gyp_configuration.py b/src/starboard/raspi/2/mozjs/gyp_configuration.py
deleted file mode 100644
index decc64f..0000000
--- a/src/starboard/raspi/2/mozjs/gyp_configuration.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright 2018 The Cobalt Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Starboard Raspberry Pi 2 platform configuration for gyp_cobalt."""
-
-import importlib
-
-# pylint: disable=invalid-name
-Raspi2PlatformConfig = importlib.import_module(
- 'starboard.raspi.2.gyp_configuration').Raspi2PlatformConfig
-
-
-class Raspi2MozjsPlatformConfig(Raspi2PlatformConfig):
-
- def __init__(self, platform, sabi_json_path=None):
- super(Raspi2MozjsPlatformConfig, self).__init__(
- platform, sabi_json_path=sabi_json_path)
-
- def GetVariables(self, config_name):
- variables = super(Raspi2MozjsPlatformConfig, self).GetVariables(config_name)
- variables.update({
- 'javascript_engine': 'mozjs-45',
- 'cobalt_enable_jit': 0,
- })
- return variables
-
-
-def CreatePlatformConfig():
- return Raspi2MozjsPlatformConfig(
- 'raspi-2-mozjs', sabi_json_path='starboard/sabi/arm/hardfp/sabi.json')
diff --git a/src/starboard/raspi/2/skia/configuration.cc b/src/starboard/raspi/2/skia/configuration.cc
new file mode 100644
index 0000000..0ffdf45
--- /dev/null
+++ b/src/starboard/raspi/2/skia/configuration.cc
@@ -0,0 +1,73 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/raspi/2/skia/configuration.h"
+
+#include "cobalt/extension/configuration.h"
+#include "starboard/common/configuration_defaults.h"
+
+namespace starboard {
+namespace raspi {
+namespace skia {
+
+namespace {
+
+int CobaltSkiaGlyphAtlasWidth() {
+ return 2048;
+}
+
+int CobaltSkiaGlyphAtlasHeight() {
+ return 2048;
+}
+
+const char* CobaltRasterizerType() {
+ return "hardware";
+}
+
+const CobaltExtensionConfigurationApi kConfigurationApi = {
+ kCobaltExtensionConfigurationName,
+ 1,
+ &common::CobaltUserOnExitStrategyDefault,
+ &common::CobaltRenderDirtyRegionOnlyDefault,
+ &common::CobaltEglSwapIntervalDefault,
+ &common::CobaltFallbackSplashScreenUrlDefault,
+ &common::CobaltEnableQuicDefault,
+ &common::CobaltSkiaCacheSizeInBytesDefault,
+ &common::CobaltOffscreenTargetCacheSizeInBytesDefault,
+ &common::CobaltEncodedImageCacheSizeInBytesDefault,
+ &common::CobaltImageCacheSizeInBytesDefault,
+ &common::CobaltLocalTypefaceCacheSizeInBytesDefault,
+ &common::CobaltRemoteTypefaceCacheSizeInBytesDefault,
+ &common::CobaltMeshCacheSizeInBytesDefault,
+ &common::CobaltSoftwareSurfaceCacheSizeInBytesDefault,
+ &common::CobaltImageCacheCapacityMultiplierWhenPlayingVideoDefault,
+ &CobaltSkiaGlyphAtlasWidth,
+ &CobaltSkiaGlyphAtlasHeight,
+ &common::CobaltJsGarbageCollectionThresholdInBytesDefault,
+ &common::CobaltReduceCpuMemoryByDefault,
+ &common::CobaltReduceGpuMemoryByDefault,
+ &common::CobaltGcZealDefault,
+ &CobaltRasterizerType,
+ &common::CobaltEnableJitDefault,
+};
+
+} // namespace
+
+const void* GetConfigurationApi() {
+ return &kConfigurationApi;
+}
+
+} // namespace skia
+} // namespace raspi
+} // namespace starboard
diff --git a/src/starboard/raspi/2/skia/configuration.h b/src/starboard/raspi/2/skia/configuration.h
new file mode 100644
index 0000000..4ce8394
--- /dev/null
+++ b/src/starboard/raspi/2/skia/configuration.h
@@ -0,0 +1,28 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_RASPI_2_SKIA_CONFIGURATION_H_
+#define STARBOARD_RASPI_2_SKIA_CONFIGURATION_H_
+
+namespace starboard {
+namespace raspi {
+namespace skia {
+
+const void* GetConfigurationApi();
+
+} // namespace skia
+} // namespace raspi
+} // namespace starboard
+
+#endif // STARBOARD_RASPI_2_SKIA_CONFIGURATION_H_
diff --git a/src/starboard/raspi/2/skia/starboard_platform.gyp b/src/starboard/raspi/2/skia/starboard_platform.gyp
index 1a1111d..8057cd1 100644
--- a/src/starboard/raspi/2/skia/starboard_platform.gyp
+++ b/src/starboard/raspi/2/skia/starboard_platform.gyp
@@ -15,4 +15,16 @@
'includes': [
'../../shared/starboard_platform.gypi',
],
+ 'target_defaults': {
+ 'sources': [
+ '<(DEPTH)/starboard/raspi/2/skia/configuration.cc',
+ '<(DEPTH)/starboard/raspi/2/skia/configuration.h',
+ '<(DEPTH)/starboard/raspi/2/skia/system_get_extensions.cc',
+ ],
+ 'sources!': [
+ '<(DEPTH)/starboard/raspi/shared/configuration.cc',
+ '<(DEPTH)/starboard/raspi/shared/configuration.h',
+ '<(DEPTH)/starboard/raspi/shared/system_get_extensions.cc',
+ ],
+ },
}
diff --git a/src/starboard/raspi/2/skia/system_get_extensions.cc b/src/starboard/raspi/2/skia/system_get_extensions.cc
new file mode 100644
index 0000000..01e50ba
--- /dev/null
+++ b/src/starboard/raspi/2/skia/system_get_extensions.cc
@@ -0,0 +1,26 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/system.h"
+
+#include "cobalt/extension/configuration.h"
+#include "starboard/common/string.h"
+#include "starboard/raspi/2/skia/configuration.h"
+
+const void* SbSystemGetExtension(const char* name) {
+ if (SbStringCompareAll(name, kCobaltExtensionConfigurationName) == 0) {
+ return starboard::raspi::skia::GetConfigurationApi();
+ }
+ return NULL;
+}
diff --git a/src/starboard/raspi/shared/cobalt/configuration.py b/src/starboard/raspi/shared/cobalt/configuration.py
index 49d9ade..7c7d912 100644
--- a/src/starboard/raspi/shared/cobalt/configuration.py
+++ b/src/starboard/raspi/shared/cobalt/configuration.py
@@ -61,6 +61,7 @@
filters += [
('csp/WebPlatformTest.Run/'
'content_security_policy_media_src_media_src_allowed_html'),
+ ('websockets/WebPlatformTest.Run/websockets_*'),
]
return filters
diff --git a/src/starboard/raspi/shared/configuration.cc b/src/starboard/raspi/shared/configuration.cc
new file mode 100644
index 0000000..5dc4c10
--- /dev/null
+++ b/src/starboard/raspi/shared/configuration.cc
@@ -0,0 +1,73 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/raspi/shared/configuration.h"
+
+#include "cobalt/extension/configuration.h"
+#include "starboard/common/configuration_defaults.h"
+
+namespace starboard {
+namespace raspi {
+namespace shared {
+
+namespace {
+
+int CobaltSkiaGlyphAtlasWidth() {
+ return 2048;
+}
+
+int CobaltSkiaGlyphAtlasHeight() {
+ return 2048;
+}
+
+bool CobaltEnableJit() {
+ return true;
+}
+
+const CobaltExtensionConfigurationApi kConfigurationApi = {
+ kCobaltExtensionConfigurationName,
+ 1,
+ &common::CobaltUserOnExitStrategyDefault,
+ &common::CobaltRenderDirtyRegionOnlyDefault,
+ &common::CobaltEglSwapIntervalDefault,
+ &common::CobaltFallbackSplashScreenUrlDefault,
+ &common::CobaltEnableQuicDefault,
+ &common::CobaltSkiaCacheSizeInBytesDefault,
+ &common::CobaltOffscreenTargetCacheSizeInBytesDefault,
+ &common::CobaltEncodedImageCacheSizeInBytesDefault,
+ &common::CobaltImageCacheSizeInBytesDefault,
+ &common::CobaltLocalTypefaceCacheSizeInBytesDefault,
+ &common::CobaltRemoteTypefaceCacheSizeInBytesDefault,
+ &common::CobaltMeshCacheSizeInBytesDefault,
+ &common::CobaltSoftwareSurfaceCacheSizeInBytesDefault,
+ &common::CobaltImageCacheCapacityMultiplierWhenPlayingVideoDefault,
+ &CobaltSkiaGlyphAtlasWidth,
+ &CobaltSkiaGlyphAtlasHeight,
+ &common::CobaltJsGarbageCollectionThresholdInBytesDefault,
+ &common::CobaltReduceCpuMemoryByDefault,
+ &common::CobaltReduceGpuMemoryByDefault,
+ &common::CobaltGcZealDefault,
+ &common::CobaltRasterizerTypeDefault,
+ &CobaltEnableJit,
+};
+
+} // namespace
+
+const void* GetConfigurationApi() {
+ return &kConfigurationApi;
+}
+
+} // namespace shared
+} // namespace raspi
+} // namespace starboard
diff --git a/src/starboard/raspi/shared/configuration.h b/src/starboard/raspi/shared/configuration.h
new file mode 100644
index 0000000..cee3db6
--- /dev/null
+++ b/src/starboard/raspi/shared/configuration.h
@@ -0,0 +1,28 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_RASPI_SHARED_CONFIGURATION_H_
+#define STARBOARD_RASPI_SHARED_CONFIGURATION_H_
+
+namespace starboard {
+namespace raspi {
+namespace shared {
+
+const void* GetConfigurationApi();
+
+} // namespace shared
+} // namespace raspi
+} // namespace starboard
+
+#endif // STARBOARD_RASPI_SHARED_CONFIGURATION_H_
diff --git a/src/starboard/raspi/shared/configuration_constants.cc b/src/starboard/raspi/shared/configuration_constants.cc
index 459b15e..b81883f 100644
--- a/src/starboard/raspi/shared/configuration_constants.cc
+++ b/src/starboard/raspi/shared/configuration_constants.cc
@@ -55,9 +55,6 @@
// Specifies whether this platform updates audio frames asynchronously.
const bool kSbHasAsyncAudioFramesReporting = false;
-// Allow playing audioless video.
-const bool kSbHasAudiolessVideo = true;
-
// Specifies whether this platform has webm/vp9 support. This should be set to
// non-zero on platforms with webm/vp9 support.
const bool kSbHasMediaWebmVp9Support = false;
@@ -142,5 +139,10 @@
// The string form of SB_PATH_SEP_CHAR.
const char* kSbPathSepString = ":";
+// Specifies the preferred byte order of color channels in a pixel. Refer to
+// starboard/configuration.h for the possible values. EGL/GLES platforms should
+// generally prefer a byte order of RGBA, regardless of endianness.
+const int kSbPreferredRgbaByteOrder = SB_PREFERRED_RGBA_BYTE_ORDER_RGBA;
+
// The maximum number of users that can be signed in at the same time.
const uint32_t kSbUserMaxSignedIn = 1;
diff --git a/src/starboard/raspi/shared/configuration_public.h b/src/starboard/raspi/shared/configuration_public.h
index 374a37f..8623dcd 100644
--- a/src/starboard/raspi/shared/configuration_public.h
+++ b/src/starboard/raspi/shared/configuration_public.h
@@ -143,11 +143,6 @@
// API. The basic requirement is a scaled, clipped, alpha-blended blit.
#define SB_HAS_BLITTER 0
-// Specifies the preferred byte order of color channels in a pixel. Refer to
-// starboard/configuration.h for the possible values. EGL/GLES platforms should
-// generally prefer a byte order of RGBA, regardless of endianness.
-#define SB_PREFERRED_RGBA_BYTE_ORDER SB_PREFERRED_RGBA_BYTE_ORDER_RGBA
-
// Indicates whether or not the given platform supports bilinear filtering.
// This can be checked to enable/disable renderer tests that verify that this is
// working properly.
diff --git a/src/starboard/raspi/shared/gyp_configuration.gypi b/src/starboard/raspi/shared/gyp_configuration.gypi
index da08556..a404e2b 100644
--- a/src/starboard/raspi/shared/gyp_configuration.gypi
+++ b/src/starboard/raspi/shared/gyp_configuration.gypi
@@ -14,15 +14,10 @@
{
'variables': {
- 'variables': {
- 'sb_evergreen_compatible': '<!(python <(DEPTH)/build/file_exists.py <(DEPTH)/starboard/elf_loader/evergreen_info.gyp)',
- },
-
# Override that omits the "data" subdirectory.
# TODO: Remove when omitted for all platforms in base_configuration.gypi.
'sb_static_contents_output_data_dir': '<(PRODUCT_DIR)/content',
- 'target_arch': 'arm',
'target_os': 'linux',
'sysroot%': '/',
diff --git a/src/starboard/raspi/shared/gyp_configuration.py b/src/starboard/raspi/shared/gyp_configuration.py
index 7b6a213..5abd0c8 100644
--- a/src/starboard/raspi/shared/gyp_configuration.py
+++ b/src/starboard/raspi/shared/gyp_configuration.py
@@ -15,10 +15,16 @@
import os
-from starboard.build import clang
+from starboard.build import clang as clang_specification
from starboard.build import platform_configuration
from starboard.tools import build
from starboard.tools.testing import test_filter
+from starboard.tools.toolchain import ar
+from starboard.tools.toolchain import bash
+from starboard.tools.toolchain import clang
+from starboard.tools.toolchain import clangxx
+from starboard.tools.toolchain import cp
+from starboard.tools.toolchain import touch
# Use a bogus path instead of None so that anything based on $RASPI_HOME won't
# inadvertently end up pointing to something in the root directory, and this
@@ -60,7 +66,7 @@
def GetEnvironmentVariables(self):
env_variables = build.GetHostCompilerEnvironment(
- clang.GetClangSpecification(), False)
+ clang_specification.GetClangSpecification(), False)
toolchain = os.path.realpath(
os.path.join(
self.raspi_home,
@@ -82,6 +88,42 @@
raise RuntimeError('RasPi builds require $RASPI_HOME/sysroot '
'to be a valid directory.')
+ def GetTargetToolchain(self):
+ environment_variables = self.GetEnvironmentVariables()
+ cc_path = environment_variables['CC']
+ cxx_path = environment_variables['CXX']
+
+ return [
+ clang.CCompiler(path=cc_path),
+ clang.CxxCompiler(path=cxx_path),
+ clang.AssemblerWithCPreprocessor(path=cc_path),
+ ar.StaticThinLinker(),
+ ar.StaticLinker(),
+ clangxx.ExecutableLinker(path=cxx_path, write_group=True),
+ clangxx.SharedLibraryLinker(path=cxx_path),
+ cp.Copy(),
+ touch.Stamp(),
+ bash.Shell(),
+ ]
+
+ def GetHostToolchain(self):
+ environment_variables = self.GetEnvironmentVariables()
+ cc_path = environment_variables['CC_host']
+ cxx_path = environment_variables['CXX_host']
+
+ return [
+ clang.CCompiler(path=cc_path),
+ clang.CxxCompiler(path=cxx_path),
+ clang.AssemblerWithCPreprocessor(path=cc_path),
+ ar.StaticThinLinker(),
+ ar.StaticLinker(),
+ clangxx.ExecutableLinker(path=cxx_path, write_group=True),
+ clangxx.SharedLibraryLinker(path=cxx_path),
+ cp.Copy(),
+ touch.Stamp(),
+ bash.Shell(),
+ ]
+
def GetLauncherPath(self):
"""Gets the path to the launcher module for this platform."""
return os.path.dirname(__file__)
diff --git a/src/starboard/raspi/shared/media_is_video_supported.cc b/src/starboard/raspi/shared/media_is_video_supported.cc
index e7e7d2e..04ef357 100644
--- a/src/starboard/raspi/shared/media_is_video_supported.cc
+++ b/src/starboard/raspi/shared/media_is_video_supported.cc
@@ -20,6 +20,7 @@
#include "starboard/shared/starboard/media/media_util.h"
bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec,
+ const char* content_type,
int profile,
int level,
int bit_depth,
@@ -31,6 +32,7 @@
int64_t bitrate,
int fps,
bool decode_to_texture_required) {
+ SB_UNREFERENCED_PARAMETER(content_type);
SB_UNREFERENCED_PARAMETER(profile);
SB_UNREFERENCED_PARAMETER(level);
diff --git a/src/starboard/raspi/shared/open_max/open_max_component_base.cc b/src/starboard/raspi/shared/open_max/open_max_component_base.cc
index 1ed246a..3af019a 100644
--- a/src/starboard/raspi/shared/open_max/open_max_component_base.cc
+++ b/src/starboard/raspi/shared/open_max/open_max_component_base.cc
@@ -36,7 +36,8 @@
void DoInitializeOpenMax() {
OMX_ERRORTYPE error = OMX_Init();
- SB_DCHECK(error == OMX_ErrorNone);
+ SB_DCHECK(error == OMX_ErrorNone)
+ << "OMX_Init() failed with error code: 0x" << std::hex << error << ".";
}
void InitializeOpenMax() {
diff --git a/src/starboard/raspi/shared/starboard_platform.gypi b/src/starboard/raspi/shared/starboard_platform.gypi
index c596afd..63f2be3 100644
--- a/src/starboard/raspi/shared/starboard_platform.gypi
+++ b/src/starboard/raspi/shared/starboard_platform.gypi
@@ -47,6 +47,8 @@
'<(DEPTH)/starboard/linux/shared/system_has_capability.cc',
'<(DEPTH)/starboard/raspi/shared/application_dispmanx.cc',
'<(DEPTH)/starboard/raspi/shared/audio_sink_type_dispatcher.cc',
+ '<(DEPTH)/starboard/raspi/shared/configuration.cc',
+ '<(DEPTH)/starboard/raspi/shared/configuration.h',
'<(DEPTH)/starboard/raspi/shared/dispmanx_util.cc',
'<(DEPTH)/starboard/raspi/shared/dispmanx_util.h',
'<(DEPTH)/starboard/raspi/shared/main.cc',
@@ -74,6 +76,7 @@
'<(DEPTH)/starboard/raspi/shared/open_max/video_decoder.h',
'<(DEPTH)/starboard/raspi/shared/player_components_factory.cc',
'<(DEPTH)/starboard/raspi/shared/system_get_device_type.cc',
+ '<(DEPTH)/starboard/raspi/shared/system_get_extensions.cc',
'<(DEPTH)/starboard/raspi/shared/system_get_property.cc',
'<(DEPTH)/starboard/raspi/shared/system_gles2.cc',
'<(DEPTH)/starboard/raspi/shared/thread_create_priority.cc',
@@ -326,13 +329,11 @@
'<(DEPTH)/starboard/shared/starboard/player/player_create.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_destroy.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_get_current_frame.cc',
- '<(DEPTH)/starboard/shared/starboard/player/player_get_info.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_get_info2.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_get_maximum_number_of_samples_per_write.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_get_preferred_output_mode_prefer_punchout.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_internal.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_internal.h',
- '<(DEPTH)/starboard/shared/starboard/player/player_seek.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_seek2.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_set_bounds.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_set_playback_rate.cc',
@@ -340,7 +341,6 @@
'<(DEPTH)/starboard/shared/starboard/player/player_worker.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_worker.h',
'<(DEPTH)/starboard/shared/starboard/player/player_write_end_of_stream.cc',
- '<(DEPTH)/starboard/shared/starboard/player/player_write_sample.cc',
'<(DEPTH)/starboard/shared/starboard/player/player_write_sample2.cc',
'<(DEPTH)/starboard/shared/starboard/queue_application.cc',
'<(DEPTH)/starboard/shared/starboard/string_concat.cc',
@@ -390,7 +390,6 @@
'<(DEPTH)/starboard/shared/stub/speech_synthesis_cancel.cc',
'<(DEPTH)/starboard/shared/stub/speech_synthesis_is_supported.cc',
'<(DEPTH)/starboard/shared/stub/speech_synthesis_speak.cc',
- '<(DEPTH)/starboard/shared/stub/system_get_extensions.cc',
'<(DEPTH)/starboard/shared/stub/system_get_total_gpu_memory.cc',
'<(DEPTH)/starboard/shared/stub/system_get_used_gpu_memory.cc',
'<(DEPTH)/starboard/shared/stub/system_hide_splash_screen.cc',
@@ -425,6 +424,7 @@
'conditions': [
['sb_evergreen_compatible == 1', {
'dependencies': [
+ '<(DEPTH)/starboard/elf_loader/evergreen_config.gyp:evergreen_config',
'<(DEPTH)/third_party/llvm-project/libunwind/libunwind.gyp:unwind_starboard',
],},
],
diff --git a/src/starboard/raspi/shared/system_get_extensions.cc b/src/starboard/raspi/shared/system_get_extensions.cc
new file mode 100644
index 0000000..8ac669a
--- /dev/null
+++ b/src/starboard/raspi/shared/system_get_extensions.cc
@@ -0,0 +1,42 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/system.h"
+
+#include "cobalt/extension/configuration.h"
+#include "starboard/common/string.h"
+#if SB_IS(EVERGREEN_COMPATIBLE)
+#include "starboard/elf_loader/evergreen_config.h"
+#endif
+
+#include "starboard/raspi/shared/configuration.h"
+
+const void* SbSystemGetExtension(const char* name) {
+#if SB_IS(EVERGREEN_COMPATIBLE)
+ const starboard::elf_loader::EvergreenConfig* evergreen_config =
+ starboard::elf_loader::EvergreenConfig::GetInstance();
+ if (evergreen_config != NULL &&
+ evergreen_config->custom_get_extension_ != NULL) {
+ const void* ext = evergreen_config->custom_get_extension_(name);
+ if (ext != NULL) {
+ return ext;
+ }
+ }
+#endif
+
+ if (SbStringCompareAll(name, kCobaltExtensionConfigurationName) == 0) {
+ return starboard::raspi::shared::GetConfigurationApi();
+ }
+ return NULL;
+}
diff --git a/src/starboard/shared/alsa/alsa_util.cc b/src/starboard/shared/alsa/alsa_util.cc
index 3d43c7e..8413a6d 100644
--- a/src/starboard/shared/alsa/alsa_util.cc
+++ b/src/starboard/shared/alsa/alsa_util.cc
@@ -29,6 +29,19 @@
} \
} while (false)
+#if defined(ADDRESS_SANITIZER)
+// By default, Leak Sanitizer and Address Sanitizer is expected to exist
+// together. However, this is not true for all platforms.
+// HAS_LEAK_SANTIZER=0 explicitly removes the Leak Sanitizer from code.
+#ifndef HAS_LEAK_SANITIZER
+#define HAS_LEAK_SANITIZER 1
+#endif // HAS_LEAK_SANITIZER
+#endif // defined(ADDRESS_SANITIZER)
+
+#if HAS_LEAK_SANITIZER
+#include <sanitizer/lsan_interface.h>
+#endif // HAS_LEAK_SANITIZER
+
namespace starboard {
namespace shared {
namespace alsa {
@@ -105,8 +118,14 @@
sample_type == SND_PCM_FORMAT_S16);
PcmHandle playback_handle;
+#if HAS_LEAK_SANITIZER
+ __lsan_disable();
+#endif // HAS_LEAK_SANITIZER
int error =
snd_pcm_open(&playback_handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
+#if HAS_LEAK_SANITIZER
+ __lsan_enable();
+#endif // HAS_LEAK_SANITIZER
ALSA_CHECK(error, snd_pcm_open, NULL);
playback_handle.set_valid();
diff --git a/src/starboard/shared/directfb/application_directfb.cc b/src/starboard/shared/directfb/application_directfb.cc
index 0a89a08..c8c7a83 100644
--- a/src/starboard/shared/directfb/application_directfb.cc
+++ b/src/starboard/shared/directfb/application_directfb.cc
@@ -524,9 +524,7 @@
SbInputData* data = new SbInputData();
SbMemorySet(data, 0, sizeof(*data));
-#if SB_API_VERSION >= 10
data->timestamp = SbTimeGetMonotonicNow();
-#endif // SB_API_VERSION >= 10
data->window = window_;
SB_DCHECK(SbWindowIsValid(data->window));
data->type = (event.type == DIET_KEYPRESS ? kSbInputEventTypePress
diff --git a/src/starboard/shared/dlmalloc/memory_protect.cc b/src/starboard/shared/dlmalloc/memory_protect.cc
index 8ab3a22..91a4c59 100644
--- a/src/starboard/shared/dlmalloc/memory_protect.cc
+++ b/src/starboard/shared/dlmalloc/memory_protect.cc
@@ -16,8 +16,6 @@
#include "starboard/memory.h"
#include "starboard/shared/dlmalloc/page_internal.h"
-#if SB_API_VERSION >= 10
bool SbMemoryProtect(void* virtual_address, int64_t size_bytes, int flags) {
return SbPageProtect(virtual_address, size_bytes, flags);
}
-#endif
diff --git a/src/starboard/shared/dlmalloc/page_internal.h b/src/starboard/shared/dlmalloc/page_internal.h
index 040e362..6b1d5ca 100644
--- a/src/starboard/shared/dlmalloc/page_internal.h
+++ b/src/starboard/shared/dlmalloc/page_internal.h
@@ -129,11 +129,9 @@
// allocated via MapUntracked().
bool SbPageUnmapUntracked(void* virtual_address, size_t size_bytes);
-#if SB_API_VERSION >= 10
// Change the protection of |size_bytes| of physical pages, starting from
// |virtual_address|, to |flags|, returning |true| on success.
bool SbPageProtect(void* virtual_address, int64_t size_bytes, int flags);
-#endif
#endif // SB_API_VERSION >= SB_MMAP_REQUIRED_VERSION || SB_HAS(MMAP)
// Returns the total amount, in bytes, of physical memory available. Should
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder_impl.cc b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder_impl.cc
index fec161c..ae422cb 100644
--- a/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder_impl.cc
+++ b/src/starboard/shared/ffmpeg/ffmpeg_audio_decoder_impl.cc
@@ -137,13 +137,9 @@
SB_DLOG(WARNING) << "avcodec_decode_audio4() failed with result: " << result
<< " with input buffer size: " << input_buffer->size()
<< " and frame decoded: " << frame_decoded;
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
error_cb_(
kSbPlayerErrorDecode,
FormatString("avcodec_decode_audio4() failed with result %d.", result));
-#else // SB_HAS(PLAYER_ERROR_MESSAGE)
- error_cb_();
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
return;
}
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_video_decoder_impl.cc b/src/starboard/shared/ffmpeg/ffmpeg_video_decoder_impl.cc
index fac3b9b..0509caa 100644
--- a/src/starboard/shared/ffmpeg/ffmpeg_video_decoder_impl.cc
+++ b/src/starboard/shared/ffmpeg/ffmpeg_video_decoder_impl.cc
@@ -257,13 +257,9 @@
if (decode_result < 0) {
SB_DLOG(ERROR) << "avcodec_decode_video2() failed with result "
<< decode_result;
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
error_cb_(kSbPlayerErrorDecode,
FormatString("avcodec_decode_video2() failed with result %d.",
decode_result));
-#else // SB_HAS(PLAYER_ERROR_MESSAGE)
- error_cb_();
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
error_occured_ = true;
return false;
}
@@ -273,12 +269,8 @@
if (av_frame_->opaque == NULL) {
SB_DLOG(ERROR) << "Video frame was produced yet has invalid frame data.";
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
error_cb_(kSbPlayerErrorDecode,
"Video frame was produced yet has invalid frame data.");
-#else // SB_HAS(PLAYER_ERROR_MESSAGE)
- error_cb_();
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
error_occured_ = true;
return false;
}
diff --git a/src/starboard/shared/gcc/atomic_gcc_public.h b/src/starboard/shared/gcc/atomic_gcc_public.h
index 6e6e645..bf1eded 100644
--- a/src/starboard/shared/gcc/atomic_gcc_public.h
+++ b/src/starboard/shared/gcc/atomic_gcc_public.h
@@ -101,7 +101,6 @@
}
// 8-bit atomic operations.
-#if SB_API_VERSION >= 10
static SB_C_FORCE_INLINE SbAtomic8
SbAtomicRelease_CompareAndSwap8(volatile SbAtomic8* ptr,
SbAtomic8 old_value,
@@ -121,7 +120,6 @@
SbAtomicNoBarrier_Load8(volatile const SbAtomic8* ptr) {
return __atomic_load_n(ptr, __ATOMIC_RELAXED);
}
-#endif // SB_API_VERSION >= 10
// 64-bit atomic operations (only available on 64-bit processors).
#if SB_HAS(64_BIT_ATOMICS)
diff --git a/src/starboard/shared/libaom/aom_video_decoder.cc b/src/starboard/shared/libaom/aom_video_decoder.cc
index f2caac4..711ea24 100644
--- a/src/starboard/shared/libaom/aom_video_decoder.cc
+++ b/src/starboard/shared/libaom/aom_video_decoder.cc
@@ -141,11 +141,7 @@
SB_DCHECK(decoder_thread_->job_queue()->BelongsToCurrentThread());
error_occured_ = true;
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
Schedule(std::bind(error_cb_, kSbPlayerErrorDecode, error_message));
-#else // SB_HAS(PLAYER_ERROR_MESSAGE)
- Schedule(error_cb_);
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
}
void VideoDecoder::InitializeCodec() {
diff --git a/src/starboard/shared/libdav1d/dav1d_video_decoder.cc b/src/starboard/shared/libdav1d/dav1d_video_decoder.cc
index 143df5c..d063310 100644
--- a/src/starboard/shared/libdav1d/dav1d_video_decoder.cc
+++ b/src/starboard/shared/libdav1d/dav1d_video_decoder.cc
@@ -199,11 +199,7 @@
void VideoDecoder::ReportError(const std::string& error_message) {
SB_LOG(ERROR) << error_message;
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
Schedule(std::bind(error_cb_, kSbPlayerErrorDecode, error_message));
-#else // SB_HAS(PLAYER_ERROR_MESSAGE)
- Schedule(error_cb_);
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
}
void VideoDecoder::InitializeCodec() {
diff --git a/src/starboard/shared/libde265/de265_video_decoder.cc b/src/starboard/shared/libde265/de265_video_decoder.cc
index 619f962..931e5ab 100644
--- a/src/starboard/shared/libde265/de265_video_decoder.cc
+++ b/src/starboard/shared/libde265/de265_video_decoder.cc
@@ -132,11 +132,7 @@
SB_DCHECK(decoder_thread_->job_queue()->BelongsToCurrentThread());
error_occured_ = true;
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
Schedule(std::bind(error_cb_, kSbPlayerErrorDecode, error_message));
-#else // SB_HAS(PLAYER_ERROR_MESSAGE)
- Schedule(error_cb_);
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
}
void VideoDecoder::InitializeCodec() {
diff --git a/src/starboard/shared/libjpeg/jpeg_image_decoder.cc b/src/starboard/shared/libjpeg/jpeg_image_decoder.cc
index 30e3991..c0be8f8 100644
--- a/src/starboard/shared/libjpeg/jpeg_image_decoder.cc
+++ b/src/starboard/shared/libjpeg/jpeg_image_decoder.cc
@@ -165,9 +165,7 @@
break;
case kSbDecodeTargetFormat2PlaneYUVNV12:
case kSbDecodeTargetFormat3PlaneYUVI420:
-#if SB_API_VERSION >= 10
case kSbDecodeTargetFormat3Plane10BitYUVI420:
-#endif // SB_API_VERSION >= 10
case kSbDecodeTargetFormat1PlaneUYVY:
case kSbDecodeTargetFormatInvalid:
SB_NOTREACHED();
diff --git a/src/starboard/shared/libvpx/vpx_video_decoder.cc b/src/starboard/shared/libvpx/vpx_video_decoder.cc
index 9cb5253..6bd1488 100644
--- a/src/starboard/shared/libvpx/vpx_video_decoder.cc
+++ b/src/starboard/shared/libvpx/vpx_video_decoder.cc
@@ -137,11 +137,7 @@
SB_DCHECK(decoder_thread_->job_queue()->BelongsToCurrentThread());
error_occured_ = true;
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
Schedule(std::bind(error_cb_, kSbPlayerErrorDecode, error_message));
-#else // SB_HAS(PLAYER_ERROR_MESSAGE)
- Schedule(error_cb_);
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
}
void VideoDecoder::InitializeCodec() {
diff --git a/src/starboard/shared/linux/cpu_features_get.cc b/src/starboard/shared/linux/cpu_features_get.cc
index 2eead19..8dface2 100644
--- a/src/starboard/shared/linux/cpu_features_get.cc
+++ b/src/starboard/shared/linux/cpu_features_get.cc
@@ -656,6 +656,9 @@
features->x86.has_tsc = (cpuid_info[3] & (1 << 4)) != 0;
features->x86.has_sse3 = (cpuid_info[2] & (1 << 0)) != 0;
+#if defined(SB_CPU_FEATURE_PCLMULQDQ)
+ features->x86.has_pclmulqdq = (cpuid_info[2] & (1 << 1)) != 0;
+#endif // defined(SB_CPU_FEATURE_PCLMULQDQ)
features->x86.has_ssse3 = (cpuid_info[2] & (1 << 9)) != 0;
features->x86.has_sse41 = (cpuid_info[2] & (1 << 19)) != 0;
features->x86.has_sse42 = (cpuid_info[2] & (1 << 20)) != 0;
diff --git a/src/starboard/shared/linux/dev_input/dev_input.cc b/src/starboard/shared/linux/dev_input/dev_input.cc
index bd5a4d3..a834764 100644
--- a/src/starboard/shared/linux/dev_input/dev_input.cc
+++ b/src/starboard/shared/linux/dev_input/dev_input.cc
@@ -1051,9 +1051,7 @@
SbInputData* data = new SbInputData();
SbMemorySet(data, 0, sizeof(*data));
-#if SB_API_VERSION >= 10
data->timestamp = SbTimeGetMonotonicNow();
-#endif // SB_API_VERSION >= 10
data->window = window;
data->type = type;
data->device_type = kSbInputDeviceTypeGamepad;
@@ -1074,9 +1072,7 @@
SbInputData* data = new SbInputData();
SbMemorySet(data, 0, sizeof(*data));
-#if SB_API_VERSION >= 10
data->timestamp = SbTimeGetMonotonicNow();
-#endif // SB_API_VERSION >= 10
data->window = window;
data->type = kSbInputEventTypeMove;
data->device_type = kSbInputDeviceTypeGamepad;
@@ -1103,9 +1099,7 @@
SbInputData* data = new SbInputData();
SbMemorySet(data, 0, sizeof(*data));
-#if SB_API_VERSION >= 10
data->timestamp = SbTimeGetMonotonicNow();
-#endif // SB_API_VERSION >= 10
data->window = window;
data->type = type;
data->device_type = kSbInputDeviceTypeTouchPad;
@@ -1295,9 +1289,7 @@
SbInputData* data = new SbInputData();
SbMemorySet(data, 0, sizeof(*data));
-#if SB_API_VERSION >= 10
data->timestamp = SbTimeGetMonotonicNow();
-#endif // SB_API_VERSION >= 10
data->window = window_;
data->type =
(event.value == 0 ? kSbInputEventTypeUnpress : kSbInputEventTypePress);
diff --git a/src/starboard/shared/linux/page_internal.cc b/src/starboard/shared/linux/page_internal.cc
index 8ee3dd2..b9cdbaf 100644
--- a/src/starboard/shared/linux/page_internal.cc
+++ b/src/starboard/shared/linux/page_internal.cc
@@ -37,11 +37,9 @@
int SbMemoryMapFlagsToMmapProtect(int sb_flags) {
bool flag_set = false;
int mmap_protect = 0;
-#if SB_API_VERSION >= 10
if (sb_flags == kSbMemoryMapProtectReserved) {
return PROT_NONE;
}
-#endif
if (sb_flags & kSbMemoryMapProtectRead) {
mmap_protect |= PROT_READ;
flag_set = true;
@@ -76,7 +74,7 @@
void* SbPageMapUntracked(size_t size_bytes,
int flags,
const char* /*unused_name*/) {
-#if SB_CAN(MAP_EXECUTABLE_MEMORY) && SB_API_VERSION >= 10
+#if SB_CAN(MAP_EXECUTABLE_MEMORY)
if (flags & kSbMemoryMapProtectExec) {
// Cobalt does not allow mapping executable memory directly.
return SB_MEMORY_MAP_FAILED;
@@ -96,12 +94,10 @@
return munmap(ptr, size_bytes) == 0;
}
-#if SB_API_VERSION >= 10
bool SbPageProtect(void* virtual_address, int64_t size_bytes, int flags) {
int mmap_protect = SbMemoryMapFlagsToMmapProtect(flags);
return mprotect(virtual_address, size_bytes, mmap_protect) == 0;
}
-#endif
size_t SbPageGetTotalPhysicalMemoryBytes() {
// Limit ourselves to remain similar to more constrained platforms.
diff --git a/src/starboard/shared/linux/thread_set_name.cc b/src/starboard/shared/linux/thread_set_name.cc
index be97f15..825379a 100644
--- a/src/starboard/shared/linux/thread_set_name.cc
+++ b/src/starboard/shared/linux/thread_set_name.cc
@@ -34,8 +34,6 @@
if (SbStringGetLength(name) >= SB_ARRAY_SIZE_INT(buffer)) {
SbStringCopy(buffer, name, SB_ARRAY_SIZE_INT(buffer));
- SB_DLOG(WARNING) << "Thread name \"" << name << "\" was truncated to \""
- << buffer << "\"";
name = buffer;
}
diff --git a/src/starboard/shared/opus/opus_audio_decoder.cc b/src/starboard/shared/opus/opus_audio_decoder.cc
index 5ca3d94..8555023 100644
--- a/src/starboard/shared/opus/opus_audio_decoder.cc
+++ b/src/starboard/shared/opus/opus_audio_decoder.cc
@@ -137,13 +137,9 @@
// TODO: Consider fill it with silence.
SB_LOG(ERROR) << kDecodeFunctionName
<< "() failed with error code: " << decoded_frames;
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
error_cb_(kSbPlayerErrorDecode,
FormatString("%s() failed with error code: %d",
kDecodeFunctionName, decoded_frames));
-#else // SB_HAS(PLAYER_ERROR_MESSAGE)
- error_cb_();
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
return;
}
diff --git a/src/starboard/shared/posix/memory_flush.cc b/src/starboard/shared/posix/memory_flush.cc
index 81ead5c..61c1b70 100644
--- a/src/starboard/shared/posix/memory_flush.cc
+++ b/src/starboard/shared/posix/memory_flush.cc
@@ -18,10 +18,6 @@
#include <iomanip>
-#if SB_IS(ARCH_MIPS)
-#include <sys/cachectl.h>
-#endif
-
#include "starboard/common/log.h"
#if !SB_CAN(MAP_EXECUTABLE_MEMORY)
@@ -31,17 +27,12 @@
void SbMemoryFlush(void* virtual_address, int64_t size_bytes) {
char* memory = reinterpret_cast<char*>(virtual_address);
-#if !SB_IS(ARCH_ARM) && !SB_IS(ARCH_ARM64) && !SB_IS(ARCH_MIPS)
+#if !SB_IS(ARCH_ARM) && !SB_IS(ARCH_ARM64)
int result = msync(memory, size_bytes, MS_SYNC);
SB_DCHECK(result == 0) << "msync failed: 0x" << std::hex << result << " ("
<< std::dec << result << "d)";
#endif
-#if SB_IS(ARCH_MIPS)
- _flush_cache(reinterpret_cast<char*>(memory), (size_t)size_bytes, BCACHE);
- return;
-#endif
-
#if !defined(__has_builtin)
#define __has_builtin(a) (0)
#endif
diff --git a/src/starboard/shared/pthread/mutex_acquire.cc b/src/starboard/shared/pthread/mutex_acquire.cc
index d247727..796d99f 100644
--- a/src/starboard/shared/pthread/mutex_acquire.cc
+++ b/src/starboard/shared/pthread/mutex_acquire.cc
@@ -19,12 +19,22 @@
#include "starboard/common/experimental/concurrency_debug.h"
#include "starboard/shared/pthread/is_success.h"
#include "starboard/shared/pthread/types_internal.h"
+#include "starboard/shared/starboard/lazy_initialization_internal.h"
+
+using starboard::shared::starboard::EnsureInitialized;
+using starboard::shared::starboard::SetInitialized;
SbMutexResult SbMutexAcquire(SbMutex* mutex) {
if (!mutex) {
return kSbMutexDestroyed;
}
+#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+ if (!EnsureInitialized(&(SB_INTERNAL_MUTEX(mutex)->initialized_state))) {
+ *SB_PTHREAD_INTERNAL_MUTEX(mutex) = PTHREAD_MUTEX_INITIALIZER;
+ SetInitialized(&(SB_INTERNAL_MUTEX(mutex)->initialized_state));
+ }
+#endif
#if SB_ENABLE_CONCURRENTY_DEBUG
starboard::experimental::ScopedMutexWaitTracker tracker(mutex);
if (tracker.acquired()) {
diff --git a/src/starboard/shared/pthread/mutex_acquire_try.cc b/src/starboard/shared/pthread/mutex_acquire_try.cc
index d7a55c5..5ec2db7 100644
--- a/src/starboard/shared/pthread/mutex_acquire_try.cc
+++ b/src/starboard/shared/pthread/mutex_acquire_try.cc
@@ -18,11 +18,23 @@
#include "starboard/shared/pthread/is_success.h"
#include "starboard/shared/pthread/types_internal.h"
+#include "starboard/shared/starboard/lazy_initialization_internal.h"
+
+using starboard::shared::starboard::EnsureInitialized;
+using starboard::shared::starboard::SetInitialized;
SbMutexResult SbMutexAcquireTry(SbMutex* mutex) {
if (!mutex) {
return kSbMutexDestroyed;
}
+
+#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+ if (!EnsureInitialized(&(SB_INTERNAL_MUTEX(mutex)->initialized_state))) {
+ *SB_PTHREAD_INTERNAL_MUTEX(mutex) = PTHREAD_MUTEX_INITIALIZER;
+ SetInitialized(&(SB_INTERNAL_MUTEX(mutex)->initialized_state));
+ }
+#endif
+
int result = pthread_mutex_trylock(SB_PTHREAD_INTERNAL_MUTEX(mutex));
if (IsSuccess(result)) {
return kSbMutexAcquired;
diff --git a/src/starboard/shared/pthread/mutex_create.cc b/src/starboard/shared/pthread/mutex_create.cc
index a37ff65..fb6f65a 100644
--- a/src/starboard/shared/pthread/mutex_create.cc
+++ b/src/starboard/shared/pthread/mutex_create.cc
@@ -19,13 +19,21 @@
#include "starboard/common/log.h"
#include "starboard/shared/pthread/is_success.h"
#include "starboard/shared/pthread/types_internal.h"
+#include "starboard/shared/starboard/lazy_initialization_internal.h"
+
+using starboard::shared::starboard::SetInitialized;
bool SbMutexCreate(SbMutex* mutex) {
- SB_COMPILE_ASSERT(sizeof(SbMutex) >= sizeof(pthread_mutex_t),
- pthread_mutex_t_larger_than_sb_mutex);
+#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+ SB_COMPILE_ASSERT(sizeof(SbMutex) >= sizeof(SbMutexPrivate),
+ sb_mutex_private_larger_than_sb_mutex);
+#endif
if (!mutex) {
return false;
}
+#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+ SetInitialized(&(SB_INTERNAL_MUTEX(mutex)->initialized_state));
+#endif
return IsSuccess(pthread_mutex_init(SB_PTHREAD_INTERNAL_MUTEX(mutex), NULL));
}
diff --git a/src/starboard/shared/pthread/mutex_destroy.cc b/src/starboard/shared/pthread/mutex_destroy.cc
index 7b58e31..df01a41 100644
--- a/src/starboard/shared/pthread/mutex_destroy.cc
+++ b/src/starboard/shared/pthread/mutex_destroy.cc
@@ -20,12 +20,22 @@
#include "starboard/configuration.h"
#include "starboard/shared/pthread/is_success.h"
#include "starboard/shared/pthread/types_internal.h"
+#include "starboard/shared/starboard/lazy_initialization_internal.h"
+
+using starboard::shared::starboard::IsInitialized;
bool SbMutexDestroy(SbMutex* mutex) {
if (!mutex) {
return false;
}
+#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+ if (!IsInitialized(&(SB_INTERNAL_MUTEX(mutex)->initialized_state))) {
+ // If the mutex is not initialized there is nothing to destroy.
+ return true;
+ }
+#endif
+
#if SB_API_VERSION >= SB_MUTEX_ACQUIRE_TRY_API_CHANGE_VERSION
// Both trying to recursively acquire a mutex that is locked by the calling
// thread, as well as deleting a locked mutex, result in undefined behavior.
diff --git a/src/starboard/shared/pthread/mutex_release.cc b/src/starboard/shared/pthread/mutex_release.cc
index e55603c..2e9bc41 100644
--- a/src/starboard/shared/pthread/mutex_release.cc
+++ b/src/starboard/shared/pthread/mutex_release.cc
@@ -18,11 +18,21 @@
#include "starboard/shared/pthread/is_success.h"
#include "starboard/shared/pthread/types_internal.h"
+#include "starboard/shared/starboard/lazy_initialization_internal.h"
+
+using starboard::shared::starboard::IsInitialized;
bool SbMutexRelease(SbMutex* mutex) {
if (!mutex) {
return false;
}
+#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+ if (!IsInitialized(&(SB_INTERNAL_MUTEX(mutex)->initialized_state))) {
+ // If the mutex is not initialized there is nothing to release.
+ return true;
+ }
+#endif
+
return IsSuccess(pthread_mutex_unlock(SB_PTHREAD_INTERNAL_MUTEX(mutex)));
}
diff --git a/src/starboard/shared/pthread/once.cc b/src/starboard/shared/pthread/once.cc
index 56ba9a8..c8c937f 100644
--- a/src/starboard/shared/pthread/once.cc
+++ b/src/starboard/shared/pthread/once.cc
@@ -18,16 +18,29 @@
#include "starboard/common/log.h"
#include "starboard/shared/pthread/types_internal.h"
+#include "starboard/shared/starboard/lazy_initialization_internal.h"
+
+using starboard::shared::starboard::EnsureInitialized;
+using starboard::shared::starboard::SetInitialized;
bool SbOnce(SbOnceControl* once_control, SbOnceInitRoutine init_routine) {
- SB_COMPILE_ASSERT(sizeof(SbOnceControl) >= sizeof(pthread_once_t),
- pthread_once_t_larger_than_sb_once_control);
+#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+ SB_COMPILE_ASSERT(sizeof(SbOnceControl) >= sizeof(SbOnceControlPrivate),
+ sb_once_control_private_larger_than_sb_once_control);
+#endif
if (once_control == NULL) {
return false;
}
if (init_routine == NULL) {
return false;
}
+#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
+ if (!EnsureInitialized(
+ &(SB_INTERNAL_ONCE(once_control)->initialized_state))) {
+ *SB_PTHREAD_INTERNAL_ONCE(once_control) = PTHREAD_ONCE_INIT;
+ SetInitialized(&(SB_INTERNAL_ONCE(once_control)->initialized_state));
+ }
+#endif
return pthread_once(SB_PTHREAD_INTERNAL_ONCE(once_control), init_routine) ==
0;
diff --git a/src/starboard/shared/pthread/types_internal.h b/src/starboard/shared/pthread/types_internal.h
index e55ec05..53100c54 100644
--- a/src/starboard/shared/pthread/types_internal.h
+++ b/src/starboard/shared/pthread/types_internal.h
@@ -18,10 +18,14 @@
#define STARBOARD_SHARED_PTHREAD_TYPES_INTERNAL_H_
#if SB_API_VERSION >= SB_PORTABLE_THREAD_TYPES_VERSION
-#define SB_PTHREAD_INTERNAL_MUTEX(mutex_ptr) \
- reinterpret_cast<pthread_mutex_t*>((mutex_ptr)->mutex_buffer)
-#define SB_PTHREAD_INTERNAL_ONCE(once_ptr) \
- reinterpret_cast<pthread_once_t*>((once_ptr)->once_buffer)
+#define SB_INTERNAL_MUTEX(mutex_var) \
+ reinterpret_cast<SbMutexPrivate*>((mutex_var)->mutex_buffer)
+#define SB_PTHREAD_INTERNAL_MUTEX(mutex_var) \
+ &(reinterpret_cast<SbMutexPrivate*>((mutex_var)->mutex_buffer)->mutex)
+#define SB_INTERNAL_ONCE(once_var) \
+ reinterpret_cast<SbOnceControlPrivate*>((once_var)->once_buffer)
+#define SB_PTHREAD_INTERNAL_ONCE(once_var) \
+ &(reinterpret_cast<SbOnceControlPrivate*>((once_var)->once_buffer)->once)
#define SB_PTHREAD_INTERNAL_THREAD(thread) reinterpret_cast<pthread_t>(thread)
#define SB_PTHREAD_INTERNAL_THREAD_PTR(thread) \
reinterpret_cast<pthread_t*>(&(thread))
@@ -30,8 +34,8 @@
reinterpret_cast<SbConditionVariablePrivate*>( \
(condition_var)->condition_buffer)
#else
-#define SB_PTHREAD_INTERNAL_MUTEX(mutex_ptr) (mutex_ptr)
-#define SB_PTHREAD_INTERNAL_ONCE(once_ptr) (once_ptr)
+#define SB_PTHREAD_INTERNAL_MUTEX(mutex_var) (mutex_var)
+#define SB_PTHREAD_INTERNAL_ONCE(once_var) (once_var)
#define SB_PTHREAD_INTERNAL_THREAD(thread) (thread)
#define SB_PTHREAD_INTERNAL_THREAD_PTR(thread) \
reinterpret_cast<pthread_t*>(&(thread))
@@ -49,4 +53,20 @@
pthread_cond_t condition;
} SbConditionVariablePrivate;
+// Wrapping pthread_mutex_t to add initialization state
+// which allows for lazy initialization to PTHREAD_MUTEX_INITIALIZER.
+// NOTE: The actual value of PTHREAD_MUTEX_INITIALIZER.
+typedef struct SbMutexPrivate {
+ InitializedState initialized_state;
+ pthread_mutex_t mutex;
+} SbMutexPrivate;
+
+// Wrapping pthread_once_t to add initialization state
+// which allows for lazy initialization to PTHREAD_ONCE_INIT.
+// NOTE: The actual value of PTHREAD_ONCE_INIT.
+typedef struct SbOnceControlPrivate {
+ InitializedState initialized_state;
+ pthread_once_t once;
+} SbOnceControlPrivate;
+
#endif // STARBOARD_SHARED_PTHREAD_TYPES_INTERNAL_H_
diff --git a/src/starboard/shared/pulse/pulse_audio_sink_type.cc b/src/starboard/shared/pulse/pulse_audio_sink_type.cc
index 346522c..92e763d 100644
--- a/src/starboard/shared/pulse/pulse_audio_sink_type.cc
+++ b/src/starboard/shared/pulse/pulse_audio_sink_type.cc
@@ -500,9 +500,27 @@
pa_stream_flags_t flags,
pa_stream_request_cb_t stream_request_cb,
void* userdata) {
+ pa_channel_map channel_map = {sample_spec->channels};
+
+ if (sample_spec->channels == 6) {
+ // Assume the incoming layout is always "FL FR FC LFE BL BR".
+ channel_map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
+ channel_map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
+ channel_map.map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
+ // Note that this should really be |PA_CHANNEL_POSITION_LFE|, but there is
+ // usually no lfe device on desktop so set it to rear center to make it
+ // audible.
+ channel_map.map[3] = PA_CHANNEL_POSITION_REAR_CENTER;
+ // Rear left and rear left are the same as back left and back right.
+ channel_map.map[4] = PA_CHANNEL_POSITION_REAR_LEFT;
+ channel_map.map[5] = PA_CHANNEL_POSITION_REAR_RIGHT;
+ }
+
ScopedLock lock(mutex_);
+
pa_stream* stream =
- pa_stream_new(context_, "cobalt_stream", sample_spec, NULL);
+ pa_stream_new(context_, "cobalt_stream", sample_spec,
+ sample_spec->channels == 6 ? &channel_map : NULL);
if (!stream) {
SB_LOG(ERROR) << "Pulse audio error: cannot create stream.";
return NULL;
diff --git a/src/starboard/shared/starboard/audio_sink/audio_sink_create.cc b/src/starboard/shared/starboard/audio_sink/audio_sink_create.cc
index eba72ef..bcddf3b 100644
--- a/src/starboard/shared/starboard/audio_sink/audio_sink_create.cc
+++ b/src/starboard/shared/starboard/audio_sink/audio_sink_create.cc
@@ -72,6 +72,7 @@
auto audio_sink_type = SbAudioSinkPrivate::GetPreferredType();
if (!audio_sink_type) {
+ SB_LOG(WARNING) << "Preferred Sink Type is invalid.";
return kSbAudioSinkInvalid;
}
SbAudioSink audio_sink = audio_sink_type->Create(
@@ -88,6 +89,7 @@
audio_sink_type->Destroy(audio_sink);
auto fallback_audio_sink_type = SbAudioSinkPrivate::GetFallbackType();
if (!fallback_audio_sink_type) {
+ SB_LOG(WARNING) << "Fallback Sink Type is invalid.";
return kSbAudioSinkInvalid;
}
audio_sink = fallback_audio_sink_type->Create(
diff --git a/src/starboard/shared/starboard/configuration_constants_compatibility_defines.h b/src/starboard/shared/starboard/configuration_constants_compatibility_defines.h
index d0a4846..5af45c9 100644
--- a/src/starboard/shared/starboard/configuration_constants_compatibility_defines.h
+++ b/src/starboard/shared/starboard/configuration_constants_compatibility_defines.h
@@ -47,8 +47,6 @@
#define kSbHasAsyncAudioFramesReporting SB_HAS_ASYNC_AUDIO_FRAMES_REPORTING
-#define kSbHasAudiolessVideo SB_HAS_AUDIOLESS_VIDEO
-
#define kSbHasMediaWebmVp9Support SB_HAS_MEDIA_WEBM_VP9_SUPPORT
#define kSbHasThreadPrioritySupport SB_HAS_THREAD_PRIORITY_SUPPORT
@@ -83,6 +81,8 @@
#define kSbPathSepString SB_PATH_SEP_STRING
+#define kSbPreferredRgbaByteOrder SB_PREFERRED_RGBA_BYTE_ORDER
+
#define kSbUserMaxSignedIn SB_USER_MAX_SIGNED_IN
#endif // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
diff --git a/src/starboard/shared/starboard/cryptography/cryptography_create_transformer.cc b/src/starboard/shared/starboard/cryptography/cryptography_create_transformer.cc
index 4d453d3..9845a42 100644
--- a/src/starboard/shared/starboard/cryptography/cryptography_create_transformer.cc
+++ b/src/starboard/shared/starboard/cryptography/cryptography_create_transformer.cc
@@ -12,9 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "starboard/configuration.h"
+
+#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+
#include "starboard/common/log.h"
#include "starboard/common/string.h"
-#include "starboard/configuration.h"
#include "starboard/cryptography.h"
#include "starboard/memory.h"
#include "starboard/shared/starboard/cryptography/cryptography_internal.h"
@@ -119,3 +122,5 @@
return transformer;
}
+
+#endif // SB_CRYPTOAPI_DEPRECATED_VERSION
diff --git a/src/starboard/shared/starboard/cryptography/cryptography_destroy_transformer.cc b/src/starboard/shared/starboard/cryptography/cryptography_destroy_transformer.cc
index c4411ac..c3e68c5 100644
--- a/src/starboard/shared/starboard/cryptography/cryptography_destroy_transformer.cc
+++ b/src/starboard/shared/starboard/cryptography/cryptography_destroy_transformer.cc
@@ -13,6 +13,9 @@
// limitations under the License.
#include "starboard/configuration.h"
+
+#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+
#include "starboard/cryptography.h"
#include "starboard/shared/starboard/cryptography/cryptography_internal.h"
@@ -23,3 +26,5 @@
delete transformer;
}
+
+#endif // SB_CRYPTOAPI_DEPRECATED_VERSION
diff --git a/src/starboard/shared/starboard/cryptography/cryptography_get_tag.cc b/src/starboard/shared/starboard/cryptography/cryptography_get_tag.cc
index e16d8c1..20dacd3 100644
--- a/src/starboard/shared/starboard/cryptography/cryptography_get_tag.cc
+++ b/src/starboard/shared/starboard/cryptography/cryptography_get_tag.cc
@@ -13,6 +13,9 @@
// limitations under the License.
#include "starboard/configuration.h"
+
+#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+
#include "starboard/cryptography.h"
#include "starboard/shared/starboard/cryptography/cryptography_internal.h"
#include "starboard/shared/starboard/cryptography/software_aes.h"
@@ -32,3 +35,5 @@
AES_gcm128_tag(&transformer->gcm_context, out_tag, out_tag_size);
return true;
}
+
+#endif // SB_CRYPTOAPI_DEPRECATED_VERSION
diff --git a/src/starboard/shared/starboard/cryptography/cryptography_internal.h b/src/starboard/shared/starboard/cryptography/cryptography_internal.h
index a7b93ebd..4a5ffa2 100644
--- a/src/starboard/shared/starboard/cryptography/cryptography_internal.h
+++ b/src/starboard/shared/starboard/cryptography/cryptography_internal.h
@@ -15,6 +15,10 @@
#ifndef STARBOARD_SHARED_STARBOARD_CRYPTOGRAPHY_CRYPTOGRAPHY_INTERNAL_H_
#define STARBOARD_SHARED_STARBOARD_CRYPTOGRAPHY_CRYPTOGRAPHY_INTERNAL_H_
+#if SB_API_VERSION >= SB_CRYPTOAPI_DEPRECATED_VERSION
+#error "Starboard Crypto API is deprecated"
+#else
+
#include "starboard/cryptography.h"
#include "starboard/shared/internal_only.h"
@@ -48,4 +52,6 @@
uint32_t counter;
};
+#endif // SB_CRYPTOAPI_DEPRECATED_VERSION
+
#endif // STARBOARD_SHARED_STARBOARD_CRYPTOGRAPHY_CRYPTOGRAPHY_INTERNAL_H_
diff --git a/src/starboard/shared/starboard/cryptography/cryptography_set_authenticated_data.cc b/src/starboard/shared/starboard/cryptography/cryptography_set_authenticated_data.cc
index 28deaca..7af5fce 100644
--- a/src/starboard/shared/starboard/cryptography/cryptography_set_authenticated_data.cc
+++ b/src/starboard/shared/starboard/cryptography/cryptography_set_authenticated_data.cc
@@ -13,6 +13,9 @@
// limitations under the License.
#include "starboard/configuration.h"
+
+#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+
#include "starboard/cryptography.h"
#include "starboard/shared/starboard/cryptography/cryptography_internal.h"
#include "starboard/shared/starboard/cryptography/software_aes.h"
@@ -32,3 +35,5 @@
int result = AES_gcm128_aad(&transformer->gcm_context, data, data_size);
return result == 1;
}
+
+#endif // SB_CRYPTOAPI_DEPRECATED_VERSION
diff --git a/src/starboard/shared/starboard/cryptography/cryptography_set_initialization_vector.cc b/src/starboard/shared/starboard/cryptography/cryptography_set_initialization_vector.cc
index 64dc487..8c70ae0 100644
--- a/src/starboard/shared/starboard/cryptography/cryptography_set_initialization_vector.cc
+++ b/src/starboard/shared/starboard/cryptography/cryptography_set_initialization_vector.cc
@@ -12,11 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "starboard/configuration.h"
+
+#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+
#include "starboard/cryptography.h"
#include <algorithm>
-#include "starboard/configuration.h"
#include "starboard/memory.h"
#include "starboard/shared/starboard/cryptography/cryptography_internal.h"
#include "starboard/shared/starboard/cryptography/software_aes.h"
@@ -38,3 +41,5 @@
static_cast<int>(sizeof(transformer->ivec))));
}
}
+
+#endif // SB_CRYPTOAPI_DEPRECATED_VERSION
diff --git a/src/starboard/shared/starboard/cryptography/cryptography_transform.cc b/src/starboard/shared/starboard/cryptography/cryptography_transform.cc
index 92b6be3..8a84ee0 100644
--- a/src/starboard/shared/starboard/cryptography/cryptography_transform.cc
+++ b/src/starboard/shared/starboard/cryptography/cryptography_transform.cc
@@ -13,6 +13,9 @@
// limitations under the License.
#include "starboard/configuration.h"
+
+#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+
#include "starboard/cryptography.h"
#include "starboard/shared/starboard/cryptography/cryptography_internal.h"
#include "starboard/shared/starboard/cryptography/software_aes.h"
@@ -110,3 +113,5 @@
return in_data_size;
}
+
+#endif // SB_CRYPTOAPI_DEPRECATED_VERSION
diff --git a/src/starboard/shared/starboard/cryptography/software_aes.cc b/src/starboard/shared/starboard/cryptography/software_aes.cc
index ec50a11..32793d4 100644
--- a/src/starboard/shared/starboard/cryptography/software_aes.cc
+++ b/src/starboard/shared/starboard/cryptography/software_aes.cc
@@ -60,6 +60,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "starboard/configuration.h"
+
+#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+
#include "starboard/shared/starboard/cryptography/software_aes.h"
#include "starboard/common/byte_swap.h"
@@ -1568,3 +1572,5 @@
} // namespace starboard
} // namespace shared
} // namespace starboard
+
+#endif // SB_CRYPTOAPI_DEPRECATED_VERSION
diff --git a/src/starboard/shared/starboard/cryptography/software_aes.h b/src/starboard/shared/starboard/cryptography/software_aes.h
index c429076..e05391f 100644
--- a/src/starboard/shared/starboard/cryptography/software_aes.h
+++ b/src/starboard/shared/starboard/cryptography/software_aes.h
@@ -63,6 +63,10 @@
#ifndef STARBOARD_SHARED_STARBOARD_CRYPTOGRAPHY_SOFTWARE_AES_H_
#define STARBOARD_SHARED_STARBOARD_CRYPTOGRAPHY_SOFTWARE_AES_H_
+#if SB_API_VERSION >= SB_CRYPTOAPI_DEPRECATED_VERSION
+#error "Starboard Crypto API is deprecated"
+#else
+
#include "starboard/common/log.h"
#include "starboard/configuration.h"
#include "starboard/types.h"
@@ -212,4 +216,6 @@
} // namespace shared
} // namespace starboard
+#endif // SB_CRYPTOAPI_DEPRECATED_VERSION
+
#endif // STARBOARD_SHARED_STARBOARD_CRYPTOGRAPHY_SOFTWARE_AES_H_
diff --git a/src/starboard/shared/starboard/drm/drm_is_server_certificate_updatable.cc b/src/starboard/shared/starboard/drm/drm_is_server_certificate_updatable.cc
index b169c31..9c3d946 100644
--- a/src/starboard/shared/starboard/drm/drm_is_server_certificate_updatable.cc
+++ b/src/starboard/shared/starboard/drm/drm_is_server_certificate_updatable.cc
@@ -17,8 +17,6 @@
#include "starboard/common/log.h"
#include "starboard/shared/starboard/drm/drm_system_internal.h"
-#if SB_API_VERSION >= 10
-
bool SbDrmIsServerCertificateUpdatable(SbDrmSystem drm_system) {
if (!SbDrmSystemIsValid(drm_system)) {
SB_DLOG(ERROR) << "Invalid DRM system.";
@@ -27,5 +25,3 @@
return drm_system->IsServerCertificateUpdatable();
}
-
-#endif // SB_API_VERSION >= 10
diff --git a/src/starboard/shared/starboard/drm/drm_system_internal.h b/src/starboard/shared/starboard/drm/drm_system_internal.h
index 5cf70e5..792159a 100644
--- a/src/starboard/shared/starboard/drm/drm_system_internal.h
+++ b/src/starboard/shared/starboard/drm/drm_system_internal.h
@@ -41,13 +41,11 @@
virtual DecryptStatus Decrypt(InputBuffer* buffer) = 0;
-#if SB_API_VERSION >= 10
virtual bool IsServerCertificateUpdatable() = 0;
virtual void UpdateServerCertificate(int ticket,
const void* certificate,
int certificate_size) = 0;
-#endif // SB_API_VERSION >= 10
};
#endif // STARBOARD_SHARED_STARBOARD_DRM_DRM_SYSTEM_INTERNAL_H_
diff --git a/src/starboard/shared/starboard/drm/drm_update_server_certificate.cc b/src/starboard/shared/starboard/drm/drm_update_server_certificate.cc
index 2182f92..1c8f8e8 100644
--- a/src/starboard/shared/starboard/drm/drm_update_server_certificate.cc
+++ b/src/starboard/shared/starboard/drm/drm_update_server_certificate.cc
@@ -17,8 +17,6 @@
#include "starboard/common/log.h"
#include "starboard/shared/starboard/drm/drm_system_internal.h"
-#if SB_API_VERSION >= 10
-
void SbDrmUpdateServerCertificate(SbDrmSystem drm_system,
int ticket,
const void* certificate,
@@ -35,5 +33,3 @@
drm_system->UpdateServerCertificate(ticket, certificate, certificate_size);
}
-
-#endif // SB_API_VERSION >= 10
diff --git a/src/starboard/shared/starboard/lazy_initialization_internal.h b/src/starboard/shared/starboard/lazy_initialization_internal.h
index 6580285..58d3b84 100644
--- a/src/starboard/shared/starboard/lazy_initialization_internal.h
+++ b/src/starboard/shared/starboard/lazy_initialization_internal.h
@@ -58,7 +58,8 @@
SbThreadYield();
} while (SbAtomicAcquire_Load(state) != INITIALIZED_STATE_INITIALIZED);
} else {
- SB_DCHECK(original == INITIALIZED_STATE_INITIALIZED);
+ SB_DCHECK(original == INITIALIZED_STATE_INITIALIZED)
+ << "Unexpected original=" << original;
}
return true;
diff --git a/src/starboard/shared/starboard/media/avc_util.cc b/src/starboard/shared/starboard/media/avc_util.cc
new file mode 100644
index 0000000..d5b9620
--- /dev/null
+++ b/src/starboard/shared/starboard/media/avc_util.cc
@@ -0,0 +1,219 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/shared/starboard/media/avc_util.h"
+
+#include <type_traits>
+
+#include "starboard/memory.h"
+
+namespace starboard {
+namespace shared {
+namespace starboard {
+namespace media {
+
+namespace {
+
+const uint8_t kAnnexBHeader[] = {0, 0, 0, 1};
+const auto kAnnexBHeaderSizeInBytes =
+ AvcParameterSets::kAnnexBHeaderSizeInBytes;
+
+bool StartsWithAnnexBHeader(const uint8_t* annex_b_data,
+ size_t annex_b_data_size) {
+ static_assert(
+ sizeof(kAnnexBHeader) == AvcParameterSets::kAnnexBHeaderSizeInBytes,
+ "sizeof(kAnnexBHeader) doesn't match kAnnexBHeaderSizeInBytes");
+
+ if (annex_b_data_size < sizeof(kAnnexBHeader)) {
+ return false;
+ }
+ return SbMemoryCompare(annex_b_data, kAnnexBHeader, sizeof(kAnnexBHeader)) ==
+ 0;
+}
+
+// UInt8Type can be "uint8_t", or "const uint8_t".
+template <typename UInt8Type>
+bool AdvanceToNextAnnexBHeader(UInt8Type** annex_b_data,
+ size_t* annex_b_data_size) {
+ SB_DCHECK(annex_b_data);
+ SB_DCHECK(annex_b_data_size);
+
+ if (!StartsWithAnnexBHeader(*annex_b_data, *annex_b_data_size)) {
+ return false;
+ }
+
+ *annex_b_data += kAnnexBHeaderSizeInBytes;
+ *annex_b_data_size -= kAnnexBHeaderSizeInBytes;
+
+ while (*annex_b_data_size > 0) {
+ if (StartsWithAnnexBHeader(*annex_b_data, *annex_b_data_size)) {
+ return true;
+ }
+ ++*annex_b_data;
+ --*annex_b_data_size;
+ }
+ return true;
+}
+
+bool ExtractAnnexBNalu(const uint8_t** annex_b_data,
+ size_t* annex_b_data_size,
+ std::vector<uint8_t>* annex_b_nalu) {
+ SB_DCHECK(annex_b_data);
+ SB_DCHECK(annex_b_data_size);
+ SB_DCHECK(annex_b_nalu);
+
+ const uint8_t* saved_data = *annex_b_data;
+
+ if (!AdvanceToNextAnnexBHeader(annex_b_data, annex_b_data_size)) {
+ return false;
+ }
+
+ annex_b_nalu->assign(saved_data, *annex_b_data);
+ return true;
+}
+
+} // namespace
+
+AvcParameterSets::AvcParameterSets(Format format,
+ const uint8_t* data,
+ size_t size)
+ : format_(format) {
+ SB_DCHECK(format == kAnnexB);
+
+ is_valid_ =
+ format == kAnnexB && (size == 0 || StartsWithAnnexBHeader(data, size));
+
+ if (!is_valid_) {
+ return;
+ }
+
+ if (size == 0) {
+ return;
+ }
+
+ std::vector<uint8_t> nalu;
+ while (size > kAnnexBHeaderSizeInBytes &&
+ ExtractAnnexBNalu(&data, &size, &nalu)) {
+ if (nalu[kAnnexBHeaderSizeInBytes] == kSpsStartCode) {
+ if (first_sps_index_ == -1) {
+ first_sps_index_ = static_cast<int>(parameter_sets_.size());
+ }
+ parameter_sets_.push_back(nalu);
+ combined_size_in_bytes_ += nalu.size();
+ } else if (nalu[kAnnexBHeaderSizeInBytes] == kPpsStartCode) {
+ if (first_pps_index_ == -1) {
+ first_pps_index_ = static_cast<int>(parameter_sets_.size());
+ }
+ parameter_sets_.push_back(nalu);
+ combined_size_in_bytes_ += nalu.size();
+ } else {
+ break;
+ }
+ }
+}
+
+AvcParameterSets AvcParameterSets::ConvertTo(Format new_format) const {
+ if (format_ == new_format) {
+ return *this;
+ }
+
+ SB_DCHECK(format_ == kAnnexB);
+ SB_DCHECK(new_format == kHeadless);
+
+ AvcParameterSets new_parameter_sets(*this);
+ new_parameter_sets.format_ = new_format;
+ if (!new_parameter_sets.is_valid()) {
+ return new_parameter_sets;
+ }
+ for (auto& parameter_set : new_parameter_sets.parameter_sets_) {
+ SB_DCHECK(parameter_set.size() >= kAnnexBHeaderSizeInBytes);
+ parameter_set.erase(parameter_set.begin(),
+ parameter_set.begin() + kAnnexBHeaderSizeInBytes);
+ new_parameter_sets.combined_size_in_bytes_ -= kAnnexBHeaderSizeInBytes;
+ }
+
+ return new_parameter_sets;
+}
+
+bool AvcParameterSets::operator==(const AvcParameterSets& that) const {
+ if (is_valid() != that.is_valid()) {
+ return false;
+ }
+ if (!is_valid()) {
+ return true;
+ }
+
+ SB_DCHECK(format() == that.format());
+
+ if (parameter_sets_ == that.parameter_sets_) {
+ SB_DCHECK(first_sps_index_ == that.first_sps_index_);
+ SB_DCHECK(first_pps_index_ == that.first_pps_index_);
+ return true;
+ }
+ return false;
+}
+
+bool AvcParameterSets::operator!=(const AvcParameterSets& that) const {
+ return !(*this == that);
+}
+
+bool ConvertAnnexBToAvcc(const uint8_t* annex_b_source,
+ size_t size,
+ uint8_t* avcc_destination) {
+ if (size == 0) {
+ return true;
+ }
+
+ SB_DCHECK(annex_b_source);
+ SB_DCHECK(avcc_destination);
+
+ if (!StartsWithAnnexBHeader(annex_b_source, size)) {
+ return false;
+ }
+
+ auto annex_b_source_size = size;
+ // |avcc_destination_end| exists only for the purpose of validation.
+ const auto avcc_destination_end = avcc_destination + size;
+
+ const uint8_t* last_source = annex_b_source;
+
+ const auto kAvccLengthInBytes = kAnnexBHeaderSizeInBytes;
+
+ while (AdvanceToNextAnnexBHeader(&annex_b_source, &annex_b_source_size)) {
+ SB_DCHECK(annex_b_source - last_source >= kAnnexBHeaderSizeInBytes);
+ SB_DCHECK(avcc_destination < avcc_destination_end);
+
+ size_t payload_size =
+ annex_b_source - last_source - kAnnexBHeaderSizeInBytes;
+ avcc_destination[0] =
+ static_cast<uint8_t>((payload_size & 0xff000000) >> 24);
+ avcc_destination[1] = static_cast<uint8_t>((payload_size & 0xff0000) >> 16);
+ avcc_destination[2] = static_cast<uint8_t>((payload_size & 0xff00) >> 8);
+ avcc_destination[3] = static_cast<uint8_t>(payload_size & 0xff);
+ SbMemoryCopy(avcc_destination + kAvccLengthInBytes,
+ last_source + kAnnexBHeaderSizeInBytes, payload_size);
+ avcc_destination += annex_b_source - last_source;
+ last_source = annex_b_source;
+ }
+
+ SB_DCHECK(annex_b_source_size == 0);
+ SB_DCHECK(avcc_destination == avcc_destination_end);
+
+ return true;
+}
+
+} // namespace media
+} // namespace starboard
+} // namespace shared
+} // namespace starboard
diff --git a/src/starboard/shared/starboard/media/avc_util.h b/src/starboard/shared/starboard/media/avc_util.h
new file mode 100644
index 0000000..d603aac
--- /dev/null
+++ b/src/starboard/shared/starboard/media/avc_util.h
@@ -0,0 +1,110 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_SHARED_STARBOARD_MEDIA_AVC_UTIL_H_
+#define STARBOARD_SHARED_STARBOARD_MEDIA_AVC_UTIL_H_
+
+#include <vector>
+
+#include "starboard/common/log.h"
+#include "starboard/common/ref_counted.h"
+#include "starboard/shared/starboard/player/input_buffer_internal.h"
+#include "starboard/types.h"
+
+namespace starboard {
+namespace shared {
+namespace starboard {
+namespace media {
+
+// Parse avc nalus produced by the Cobalt demuxer.
+// It makes the following assumptions:
+// 1. It won't be used frequently. So it aimed to be easy to use, instead of
+// being efficient.
+// 2. The data it processes is produced by Cobalt, and should be valid most of
+// of the time. The class won't crash on invalid input, but besides checking
+// if the input starts with a nalu header, it doesn't do any further
+// validations. It is up to the decoder to detect invalid input.
+// 3. It assumes that multiple sps/pps nalus in different orders are different
+// parameter sets.
+class AvcParameterSets {
+ public:
+ enum Format {
+ kAnnexB,
+ kHeadless,
+ };
+
+ static const size_t kAnnexBHeaderSizeInBytes = 4;
+ static const uint8_t kSpsStartCode = 0x67;
+ static const uint8_t kPpsStartCode = 0x68;
+
+ // Only |format == kAnnexB| is supported, which is checked in the ctor.
+ AvcParameterSets(Format format, const uint8_t* data, size_t size);
+
+ Format format() const { return format_; }
+ bool is_valid() const { return is_valid_; }
+ bool has_sps_and_pps() const {
+ return first_sps_index_ != -1 && first_pps_index_ != -1;
+ }
+
+ const std::vector<uint8_t>& first_sps() const {
+ SB_DCHECK(first_sps_index_ != -1);
+ return parameter_sets_[first_sps_index_];
+ }
+ const std::vector<uint8_t>& first_pps() const {
+ SB_DCHECK(first_pps_index_ != -1);
+ return parameter_sets_[first_pps_index_];
+ }
+
+ std::vector<const uint8_t*> GetAddresses() const {
+ std::vector<const uint8_t*> addresses;
+ for (auto& parameter_set : parameter_sets_) {
+ addresses.push_back(parameter_set.data());
+ }
+ return addresses;
+ }
+ std::vector<size_t> GetSizesInBytes() const {
+ std::vector<size_t> sizes_in_bytes;
+ for (auto& parameter_set : parameter_sets_) {
+ sizes_in_bytes.push_back(parameter_set.size());
+ }
+ return sizes_in_bytes;
+ }
+ size_t combined_size_in_bytes() const { return combined_size_in_bytes_; }
+
+ AvcParameterSets ConvertTo(Format new_format) const;
+
+ bool operator==(const AvcParameterSets& that) const;
+ bool operator!=(const AvcParameterSets& that) const;
+
+ private:
+ Format format_ = kAnnexB;
+ bool is_valid_ = false;
+ int first_sps_index_ = -1;
+ int first_pps_index_ = -1;
+ std::vector<std::vector<uint8_t>> parameter_sets_;
+ size_t combined_size_in_bytes_ = 0;
+};
+
+// The function will fail only when the input doesn't start with an Annex B
+// nalu header.
+bool ConvertAnnexBToAvcc(const uint8_t* annex_b_source,
+ size_t size,
+ uint8_t* avcc_destination);
+
+} // namespace media
+} // namespace starboard
+} // namespace shared
+} // namespace starboard
+
+#endif // STARBOARD_SHARED_STARBOARD_MEDIA_AVC_UTIL_H_
diff --git a/src/starboard/shared/starboard/media/avc_util_test.cc b/src/starboard/shared/starboard/media/avc_util_test.cc
new file mode 100644
index 0000000..09345cb
--- /dev/null
+++ b/src/starboard/shared/starboard/media/avc_util_test.cc
@@ -0,0 +1,524 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/shared/starboard/media/avc_util.h"
+
+#include <vector>
+
+#include "starboard/common/optional.h"
+#include "starboard/shared/starboard/player/filter/testing/test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace starboard {
+namespace shared {
+namespace starboard {
+namespace media {
+namespace {
+
+using ::starboard::shared::starboard::media::ConvertAnnexBToAvcc;
+
+const auto kAnnexB = AvcParameterSets::kAnnexB;
+const auto kHeadless = AvcParameterSets::kHeadless;
+const auto kAnnexBHeaderSizeInBytes =
+ AvcParameterSets::kAnnexBHeaderSizeInBytes;
+const uint8_t kSliceStartCode = 0x61;
+const uint8_t kIdrStartCode = 0x65;
+const uint8_t kSpsStartCode = AvcParameterSets::kSpsStartCode;
+const uint8_t kPpsStartCode = AvcParameterSets::kPpsStartCode;
+
+const std::vector<uint8_t> kRawSlice = {kSliceStartCode, 0, 0, 1, 0, 0, 0};
+const std::vector<uint8_t> kRawIdr = {kIdrStartCode, 1, 2, 3, 4};
+const std::vector<uint8_t> kRawSps = {kSpsStartCode, 10, 11};
+const std::vector<uint8_t> kRawPps = {kPpsStartCode, 20};
+
+const std::vector<uint8_t> kNaluHeaderOnlyInAnnexB = {0, 0, 0, 1};
+const std::vector<uint8_t> kSpsInAnnexB = {0, 0, 0, 1, kSpsStartCode, 10, 11};
+const std::vector<uint8_t> kPpsInAnnexB = {0, 0, 0, 1, kPpsStartCode, 20};
+const std::vector<uint8_t> kIdrInAnnexB = {0, 0, 0, 1, kIdrStartCode,
+ 1, 2, 3, 4};
+const std::vector<uint8_t> kSliceInAnnexB = {0, 0, 0, 1, kSliceStartCode, 0, 0,
+ 1, 0, 0, 0};
+
+std::vector<uint8_t> operator+(const std::vector<uint8_t>& left,
+ const std::vector<uint8_t>& right) {
+ std::vector<uint8_t> result(left);
+ result.insert(result.end(), right.begin(), right.end());
+ return result;
+}
+
+std::vector<uint8_t> ToAnnexB(const std::vector<uint8_t>& nalu_body) {
+ return std::vector<uint8_t>({0, 0, 0, 1}) + nalu_body;
+}
+
+std::vector<uint8_t> ToAvcc(const std::vector<uint8_t>& nalu_body) {
+ std::vector<uint8_t> size(4);
+ size[0] = static_cast<uint8_t>((nalu_body.size() & 0xff000000) >> 24);
+ size[1] = static_cast<uint8_t>((nalu_body.size() & 0xff0000) >> 16);
+ size[2] = static_cast<uint8_t>((nalu_body.size() & 0xff00) >> 8);
+ size[3] = static_cast<uint8_t>(nalu_body.size() & 0xff);
+ return size + nalu_body;
+}
+
+// Return a nalu that is guaranteed to be different than the input parameter.
+std::vector<uint8_t> Mutate(const std::vector<uint8_t>& nalu_in_annex_b) {
+ return nalu_in_annex_b + std::vector<uint8_t>({123});
+}
+
+std::vector<uint8_t> ConvertAnnexBToAvcc(
+ const std::vector<uint8_t>& nalus_in_annex_b) {
+ std::vector<uint8_t> nalus_in_avcc(nalus_in_annex_b.size());
+ SB_CHECK(ConvertAnnexBToAvcc(nalus_in_annex_b.data(), nalus_in_annex_b.size(),
+ nalus_in_avcc.data()));
+ return nalus_in_avcc;
+}
+
+void VerifyConvertTo(const AvcParameterSets& parameter_sets_in_annex_b) {
+ auto parameter_sets_headless = parameter_sets_in_annex_b.ConvertTo(kHeadless);
+
+ ASSERT_TRUE(parameter_sets_headless.is_valid());
+ ASSERT_EQ(parameter_sets_headless.format(), kHeadless);
+ ASSERT_EQ(parameter_sets_headless.has_sps_and_pps(),
+ parameter_sets_in_annex_b.has_sps_and_pps());
+ if (parameter_sets_in_annex_b.has_sps_and_pps()) {
+ ASSERT_EQ(ToAnnexB(parameter_sets_headless.first_sps()),
+ parameter_sets_in_annex_b.first_sps());
+ ASSERT_EQ(ToAnnexB(parameter_sets_headless.first_pps()),
+ parameter_sets_in_annex_b.first_pps());
+ }
+ ASSERT_EQ(parameter_sets_headless.GetAddresses().size(),
+ parameter_sets_in_annex_b.GetAddresses().size());
+ ASSERT_EQ(parameter_sets_headless.GetSizesInBytes().size(),
+ parameter_sets_in_annex_b.GetSizesInBytes().size());
+ for (size_t i = 0; i < parameter_sets_headless.GetAddresses().size(); ++i) {
+ auto nalu_headless =
+ std::vector<uint8_t>(parameter_sets_headless.GetAddresses()[i],
+ parameter_sets_headless.GetAddresses()[i] +
+ parameter_sets_headless.GetSizesInBytes()[i]);
+ auto nalu_in_annex_b = std::vector<uint8_t>(
+ parameter_sets_in_annex_b.GetAddresses()[i],
+ parameter_sets_in_annex_b.GetAddresses()[i] +
+ parameter_sets_in_annex_b.GetSizesInBytes()[i]);
+ ASSERT_EQ(ToAnnexB(nalu_headless), nalu_in_annex_b);
+ }
+ ASSERT_EQ(parameter_sets_headless.combined_size_in_bytes() +
+ kAnnexBHeaderSizeInBytes *
+ parameter_sets_headless.GetAddresses().size(),
+ parameter_sets_in_annex_b.combined_size_in_bytes());
+}
+
+void VerifyAnnexB(const std::vector<uint8_t>& nalus_in_annex_b,
+ const std::vector<uint8_t>& first_sps_in_annex_b,
+ const std::vector<uint8_t>& first_pps_in_annex_b,
+ const std::vector<uint8_t>& parameter_sets_in_annex_b) {
+ AvcParameterSets parameter_sets(kAnnexB, nalus_in_annex_b.data(),
+ nalus_in_annex_b.size());
+
+ ASSERT_TRUE(parameter_sets.is_valid());
+ ASSERT_EQ(parameter_sets.format(), kAnnexB);
+ ASSERT_TRUE(parameter_sets.has_sps_and_pps());
+ ASSERT_EQ(parameter_sets.first_sps(), first_sps_in_annex_b);
+ ASSERT_EQ(parameter_sets.first_pps(), first_pps_in_annex_b);
+ ASSERT_EQ(parameter_sets.combined_size_in_bytes(),
+ parameter_sets_in_annex_b.size());
+
+ ASSERT_TRUE(parameter_sets == parameter_sets);
+ ASSERT_FALSE(parameter_sets != parameter_sets);
+
+ const auto& addresses = parameter_sets.GetAddresses();
+ const auto& sizes = parameter_sets.GetSizesInBytes();
+ ASSERT_EQ(addresses.size(), sizes.size());
+
+ std::vector<uint8_t> accumulated_parameter_sets;
+ for (size_t i = 0; i < addresses.size(); ++i) {
+ accumulated_parameter_sets =
+ accumulated_parameter_sets +
+ std::vector<uint8_t>(addresses[i], addresses[i] + sizes[i]);
+ }
+ ASSERT_EQ(accumulated_parameter_sets, parameter_sets_in_annex_b);
+
+ VerifyConvertTo(parameter_sets);
+}
+
+void VerifyAllEmpty(const std::vector<uint8_t>& nalus_in_annex_b) {
+ AvcParameterSets parameter_sets(kAnnexB, nalus_in_annex_b.data(),
+ nalus_in_annex_b.size());
+
+ ASSERT_EQ(parameter_sets.format(), kAnnexB);
+
+ for (int i = 0; i < 2; ++i) {
+ if (i == 1) {
+ parameter_sets = parameter_sets.ConvertTo(kHeadless);
+ ASSERT_EQ(parameter_sets.format(), kHeadless);
+ }
+ ASSERT_TRUE(parameter_sets.is_valid());
+ ASSERT_FALSE(parameter_sets.has_sps_and_pps());
+ ASSERT_TRUE(parameter_sets.GetAddresses().empty());
+ ASSERT_TRUE(parameter_sets.GetSizesInBytes().empty());
+ ASSERT_EQ(parameter_sets.combined_size_in_bytes(), 0);
+ }
+
+ VerifyConvertTo(parameter_sets);
+}
+
+bool HasEqualParameterSets(const std::vector<uint8_t>& nalus_in_annex_b_1,
+ const std::vector<uint8_t>& nalus_in_annex_b_2) {
+ AvcParameterSets parameter_sets_1(kAnnexB, nalus_in_annex_b_1.data(),
+ nalus_in_annex_b_1.size());
+ AvcParameterSets parameter_sets_2(kAnnexB, nalus_in_annex_b_2.data(),
+ nalus_in_annex_b_2.size());
+
+ SB_CHECK((parameter_sets_1 == parameter_sets_2) !=
+ (parameter_sets_1 != parameter_sets_2));
+
+ return parameter_sets_1 == parameter_sets_2;
+}
+
+TEST(AvcParameterSetsTest, Ctor) {
+ AvcParameterSets parameter_sets_1(kAnnexB, nullptr, 0);
+ AvcParameterSets parameter_sets_2(kAnnexB, kSpsInAnnexB.data(),
+ kSpsInAnnexB.size());
+ AvcParameterSets parameter_sets_3(kAnnexB, kPpsInAnnexB.data(),
+ kPpsInAnnexB.size());
+ AvcParameterSets parameter_sets_4(kAnnexB, kIdrInAnnexB.data(),
+ kIdrInAnnexB.size());
+
+ auto nalus_in_annex_b = kSpsInAnnexB + kPpsInAnnexB + kIdrInAnnexB;
+ AvcParameterSets parameter_sets_5(kAnnexB, nalus_in_annex_b.data(),
+ nalus_in_annex_b.size());
+}
+
+TEST(AvcParameterSetsTest, SingleSpsAndPps) {
+ auto sps_before_pps = kSpsInAnnexB + kPpsInAnnexB + kIdrInAnnexB;
+ auto pps_before_sps = kPpsInAnnexB + kSpsInAnnexB + kIdrInAnnexB;
+
+ VerifyAnnexB(sps_before_pps, kSpsInAnnexB, kPpsInAnnexB,
+ kSpsInAnnexB + kPpsInAnnexB);
+ VerifyAnnexB(pps_before_sps, kSpsInAnnexB, kPpsInAnnexB,
+ kPpsInAnnexB + kSpsInAnnexB);
+
+ // Change sps and pps position are treated as unequal.
+ ASSERT_FALSE(HasEqualParameterSets(sps_before_pps, pps_before_sps));
+}
+
+TEST(AvcParameterSetsTest, MultipleSpsAndPps) {
+ for (int i = 0; i < 4; ++i) {
+ std::vector<uint8_t> parameter_sets_in_annex_b;
+ switch (i) {
+ case 0:
+ parameter_sets_in_annex_b = kSpsInAnnexB + Mutate(kSpsInAnnexB) +
+ kPpsInAnnexB + Mutate(kPpsInAnnexB);
+ break;
+ case 1:
+ parameter_sets_in_annex_b = kSpsInAnnexB + kPpsInAnnexB +
+ Mutate(kSpsInAnnexB) + Mutate(kPpsInAnnexB);
+ break;
+ case 2:
+ parameter_sets_in_annex_b = kPpsInAnnexB + kSpsInAnnexB +
+ Mutate(kSpsInAnnexB) + Mutate(kPpsInAnnexB);
+ break;
+ case 3:
+ parameter_sets_in_annex_b = kPpsInAnnexB + Mutate(kPpsInAnnexB) +
+ kSpsInAnnexB + Mutate(kSpsInAnnexB);
+ break;
+ }
+ auto nalus_in_annex_b =
+ parameter_sets_in_annex_b + kIdrInAnnexB + kSliceInAnnexB;
+
+ VerifyAnnexB(nalus_in_annex_b, kSpsInAnnexB, kPpsInAnnexB,
+ parameter_sets_in_annex_b);
+
+ ASSERT_FALSE(HasEqualParameterSets(kSpsInAnnexB + kPpsInAnnexB,
+ parameter_sets_in_annex_b));
+ }
+}
+
+TEST(AvcParameterSetsTest, SpsWithoutPps) {
+ auto leading_sps_nalus = kSpsInAnnexB;
+ for (int i = 0; i < 5; ++i) {
+ auto nalus_in_annex_b = leading_sps_nalus + kIdrInAnnexB;
+
+ AvcParameterSets parameter_sets(kAnnexB, nalus_in_annex_b.data(),
+ nalus_in_annex_b.size());
+
+ ASSERT_TRUE(parameter_sets.is_valid());
+ ASSERT_FALSE(parameter_sets.has_sps_and_pps());
+ ASSERT_EQ(kSpsInAnnexB, parameter_sets.first_sps());
+ ASSERT_EQ(parameter_sets.combined_size_in_bytes(),
+ leading_sps_nalus.size());
+
+ ASSERT_EQ(parameter_sets.GetAddresses().size(), i + 1);
+ ASSERT_EQ(parameter_sets.GetSizesInBytes().size(), i + 1);
+ ASSERT_EQ(kSpsInAnnexB,
+ std::vector<uint8_t>(parameter_sets.GetAddresses()[0],
+ parameter_sets.GetAddresses()[0] +
+ parameter_sets.GetSizesInBytes()[0]));
+
+ leading_sps_nalus = leading_sps_nalus + Mutate(kSpsInAnnexB);
+ }
+}
+
+TEST(AvcParameterSetsTest, PpsWithoutSps) {
+ auto leading_pps_nalus = kPpsInAnnexB;
+ for (int i = 0; i < 5; ++i) {
+ auto nalus_in_annex_b = leading_pps_nalus + kIdrInAnnexB;
+
+ AvcParameterSets parameter_sets(kAnnexB, nalus_in_annex_b.data(),
+ nalus_in_annex_b.size());
+
+ ASSERT_TRUE(parameter_sets.is_valid());
+ ASSERT_FALSE(parameter_sets.has_sps_and_pps());
+ ASSERT_EQ(kPpsInAnnexB, parameter_sets.first_pps());
+ ASSERT_EQ(parameter_sets.combined_size_in_bytes(),
+ leading_pps_nalus.size());
+
+ ASSERT_EQ(parameter_sets.GetAddresses().size(), i + 1);
+ ASSERT_EQ(parameter_sets.GetSizesInBytes().size(), i + 1);
+ ASSERT_EQ(kPpsInAnnexB,
+ std::vector<uint8_t>(parameter_sets.GetAddresses()[0],
+ parameter_sets.GetAddresses()[0] +
+ parameter_sets.GetSizesInBytes()[0]));
+
+ leading_pps_nalus = leading_pps_nalus + Mutate(kPpsInAnnexB);
+ }
+}
+
+TEST(AvcParameterSetsTest, MultipleSpsAndPpsWithoutPayload) {
+ for (int i = 0; i < 4; ++i) {
+ std::vector<uint8_t> parameter_sets_in_annex_b;
+ switch (i) {
+ case 0:
+ parameter_sets_in_annex_b = kSpsInAnnexB + Mutate(kSpsInAnnexB) +
+ kPpsInAnnexB + Mutate(kPpsInAnnexB);
+ break;
+ case 1:
+ parameter_sets_in_annex_b = kSpsInAnnexB + kPpsInAnnexB +
+ Mutate(kSpsInAnnexB) + Mutate(kPpsInAnnexB);
+ break;
+ case 2:
+ parameter_sets_in_annex_b = kPpsInAnnexB + kSpsInAnnexB +
+ Mutate(kSpsInAnnexB) + Mutate(kPpsInAnnexB);
+ break;
+ case 3:
+ parameter_sets_in_annex_b = kPpsInAnnexB + Mutate(kPpsInAnnexB) +
+ kSpsInAnnexB + Mutate(kSpsInAnnexB);
+ break;
+ }
+
+ AvcParameterSets parameter_sets(kAnnexB, parameter_sets_in_annex_b.data(),
+ parameter_sets_in_annex_b.size());
+
+ VerifyAnnexB(parameter_sets_in_annex_b, kSpsInAnnexB, kPpsInAnnexB,
+ parameter_sets_in_annex_b);
+ }
+}
+
+TEST(AvcParameterSetsTest, SpsAfterPayload) {
+ auto parameter_sets_in_annex_b = kSpsInAnnexB + kPpsInAnnexB;
+ auto nalus_in_annex_b =
+ parameter_sets_in_annex_b + kIdrInAnnexB + kSpsInAnnexB;
+
+ VerifyAnnexB(nalus_in_annex_b, kSpsInAnnexB, kPpsInAnnexB,
+ parameter_sets_in_annex_b);
+ ASSERT_TRUE(
+ HasEqualParameterSets(parameter_sets_in_annex_b, nalus_in_annex_b));
+}
+
+TEST(AvcParameterSetsTest, PpsAfterPayload) {
+ auto parameter_sets_in_annex_b = kSpsInAnnexB + kPpsInAnnexB;
+ auto nalus_in_annex_b =
+ parameter_sets_in_annex_b + kIdrInAnnexB + kPpsInAnnexB;
+
+ VerifyAnnexB(nalus_in_annex_b, kSpsInAnnexB, kPpsInAnnexB,
+ parameter_sets_in_annex_b);
+ ASSERT_TRUE(
+ HasEqualParameterSets(parameter_sets_in_annex_b, nalus_in_annex_b));
+}
+
+TEST(AvcParameterSetsTest, SpsAndPpsAfterPayloadWithoutSpsAndPps) {
+ auto parameter_sets_in_annex_b = kSpsInAnnexB + kPpsInAnnexB;
+ auto nalus_in_annex_b =
+ kIdrInAnnexB + kPpsInAnnexB + parameter_sets_in_annex_b;
+
+ VerifyAllEmpty(nalus_in_annex_b);
+}
+
+TEST(AvcParameterSetsTest, Nullptr) {
+ AvcParameterSets parameter_sets(kAnnexB, nullptr, 0);
+
+ ASSERT_TRUE(parameter_sets.is_valid());
+ ASSERT_EQ(parameter_sets.format(), kAnnexB);
+ ASSERT_FALSE(parameter_sets.has_sps_and_pps());
+ ASSERT_TRUE(parameter_sets.GetAddresses().empty());
+ ASSERT_TRUE(parameter_sets.GetSizesInBytes().empty());
+ ASSERT_EQ(parameter_sets.combined_size_in_bytes(), 0);
+}
+
+TEST(AvcParameterSetsTest, NaluHeaderWithoutType) {
+ {
+ AvcParameterSets parameter_sets(kAnnexB, kNaluHeaderOnlyInAnnexB.data(),
+ kNaluHeaderOnlyInAnnexB.size());
+
+ ASSERT_TRUE(parameter_sets.is_valid());
+ ASSERT_EQ(parameter_sets.format(), kAnnexB);
+ ASSERT_FALSE(parameter_sets.has_sps_and_pps());
+ ASSERT_TRUE(parameter_sets.GetAddresses().empty());
+ ASSERT_TRUE(parameter_sets.GetSizesInBytes().empty());
+ ASSERT_EQ(parameter_sets.combined_size_in_bytes(), 0);
+ }
+ for (int i = 0; i < 2; ++i) {
+ auto parameter_sets_in_annex_b = kSpsInAnnexB + kPpsInAnnexB;
+ std::vector<uint8_t> nalus_in_annex_b;
+ if (i == 0) {
+ nalus_in_annex_b = parameter_sets_in_annex_b + kNaluHeaderOnlyInAnnexB;
+ } else {
+ nalus_in_annex_b =
+ parameter_sets_in_annex_b + kIdrInAnnexB + kNaluHeaderOnlyInAnnexB;
+ }
+
+ VerifyAnnexB(nalus_in_annex_b, kSpsInAnnexB, kPpsInAnnexB,
+ parameter_sets_in_annex_b);
+ }
+}
+
+TEST(AvcParameterSetsTest, InvalidNaluHeader) {
+ { VerifyAllEmpty(kNaluHeaderOnlyInAnnexB); }
+ {
+ auto parameter_sets_in_annex_b = kSpsInAnnexB + kPpsInAnnexB;
+ auto nalus_in_annex_b = parameter_sets_in_annex_b + kNaluHeaderOnlyInAnnexB;
+
+ VerifyAnnexB(nalus_in_annex_b, kSpsInAnnexB, kPpsInAnnexB,
+ parameter_sets_in_annex_b);
+ }
+ {
+ auto parameter_sets_in_annex_b = kSpsInAnnexB + kPpsInAnnexB;
+ auto nalus_in_annex_b =
+ parameter_sets_in_annex_b + kIdrInAnnexB + kNaluHeaderOnlyInAnnexB;
+
+ VerifyAnnexB(nalus_in_annex_b, kSpsInAnnexB, kPpsInAnnexB,
+ parameter_sets_in_annex_b);
+ }
+ {
+ auto parameter_sets_in_annex_b = kSpsInAnnexB + kPpsInAnnexB;
+ auto nalus_in_annex_b =
+ parameter_sets_in_annex_b + kIdrInAnnexB + kNaluHeaderOnlyInAnnexB;
+ nalus_in_annex_b.erase(nalus_in_annex_b.begin()); // One less 0
+
+ AvcParameterSets parameter_sets(kAnnexB, nalus_in_annex_b.data(),
+ nalus_in_annex_b.size());
+ ASSERT_FALSE(parameter_sets.is_valid());
+ }
+ {
+ auto parameter_sets_in_annex_b = kSpsInAnnexB + kPpsInAnnexB;
+ auto nalus_in_annex_b =
+ parameter_sets_in_annex_b + kIdrInAnnexB + kNaluHeaderOnlyInAnnexB;
+ nalus_in_annex_b.insert(nalus_in_annex_b.begin(), 0); // One extra 0
+
+ AvcParameterSets parameter_sets(kAnnexB, nalus_in_annex_b.data(),
+ nalus_in_annex_b.size());
+ ASSERT_FALSE(parameter_sets.is_valid());
+ }
+}
+
+TEST(AvcParameterSetsTest, MultiNalusWithouSpsPps) {
+ std::vector<uint8_t> nalus_in_annex_b = kIdrInAnnexB + kSliceInAnnexB;
+
+ for (int i = 0; i < 3; ++i) {
+ VerifyAllEmpty(nalus_in_annex_b);
+
+ nalus_in_annex_b = nalus_in_annex_b + nalus_in_annex_b;
+
+ ASSERT_TRUE(
+ HasEqualParameterSets(nalus_in_annex_b, std::vector<uint8_t>()));
+ }
+}
+
+TEST(AvcParameterSetsTest, ConvertAnnexBToAvcc) {
+ {
+ std::vector<uint8_t> raw_nalus[] = {kRawSlice, kRawIdr, kRawSps, kRawPps};
+ std::vector<uint8_t> nalus_in_annex_b;
+ std::vector<uint8_t> nalus_in_avcc;
+
+ for (int i = 0; i < 20; ++i) {
+ nalus_in_annex_b =
+ nalus_in_annex_b + ToAnnexB(raw_nalus[i % SB_ARRAY_SIZE(raw_nalus)]);
+ nalus_in_avcc =
+ nalus_in_avcc + ToAvcc(raw_nalus[i % SB_ARRAY_SIZE(raw_nalus)]);
+
+ ASSERT_EQ(ConvertAnnexBToAvcc(nalus_in_annex_b), nalus_in_avcc);
+ }
+ }
+ {
+ std::vector<uint8_t> raw_nalus[] = {kRawSps, kRawPps, kRawSlice, kRawIdr};
+ std::vector<uint8_t> nalus_in_annex_b;
+ std::vector<uint8_t> nalus_in_avcc;
+
+ for (int i = 0; i < 20; ++i) {
+ nalus_in_annex_b =
+ nalus_in_annex_b + ToAnnexB(raw_nalus[i % SB_ARRAY_SIZE(raw_nalus)]);
+ nalus_in_avcc =
+ nalus_in_avcc + ToAvcc(raw_nalus[i % SB_ARRAY_SIZE(raw_nalus)]);
+
+ ASSERT_EQ(ConvertAnnexBToAvcc(nalus_in_annex_b), nalus_in_avcc);
+ }
+ }
+}
+
+TEST(AvcParameterSetsTest, ConvertAnnexBToAvccEmptyNalus) {
+ const std::vector<uint8_t> kEmpty;
+ const std::vector<uint8_t> kRawNalu = {1, 2, 3, 4, 5};
+
+ std::vector<uint8_t> nalus_in_annex_b;
+ std::vector<uint8_t> nalus_in_avcc;
+
+ for (int i = 0; i < 3; ++i) {
+ nalus_in_annex_b = nalus_in_annex_b + ToAnnexB(kEmpty);
+ nalus_in_avcc = nalus_in_avcc + ToAvcc(kEmpty);
+
+ ASSERT_EQ(ConvertAnnexBToAvcc(nalus_in_annex_b), nalus_in_avcc);
+ }
+
+ ASSERT_EQ(ConvertAnnexBToAvcc(ToAnnexB(kEmpty) + ToAnnexB(kRawNalu)),
+ ToAvcc(kEmpty) + ToAvcc(kRawNalu));
+ ASSERT_EQ(ConvertAnnexBToAvcc(ToAnnexB(kRawNalu) + ToAnnexB(kEmpty)),
+ ToAvcc(kRawNalu) + ToAvcc(kEmpty));
+}
+
+TEST(AvcParameterSetsTest, ConvertAnnexBToAvccInvalidNalus) {
+ {
+ auto parameter_sets_in_annex_b = kSpsInAnnexB + kPpsInAnnexB;
+ auto nalus_in_annex_b =
+ parameter_sets_in_annex_b + kIdrInAnnexB + kNaluHeaderOnlyInAnnexB;
+ nalus_in_annex_b.erase(nalus_in_annex_b.begin()); // One less 0
+ auto nalus_in_avcc = nalus_in_annex_b;
+ ASSERT_FALSE(ConvertAnnexBToAvcc(nalus_in_annex_b.data(),
+ nalus_in_annex_b.size(),
+ nalus_in_avcc.data()));
+ }
+ {
+ auto parameter_sets_in_annex_b = kSpsInAnnexB + kPpsInAnnexB;
+ auto nalus_in_annex_b =
+ parameter_sets_in_annex_b + kIdrInAnnexB + kNaluHeaderOnlyInAnnexB;
+ nalus_in_annex_b.insert(nalus_in_annex_b.begin(), 0); // One extra 0
+ auto nalus_in_avcc = nalus_in_annex_b;
+ ASSERT_FALSE(ConvertAnnexBToAvcc(nalus_in_annex_b.data(),
+ nalus_in_annex_b.size(),
+ nalus_in_avcc.data()));
+ }
+}
+
+} // namespace
+} // namespace media
+} // namespace starboard
+} // namespace shared
+} // namespace starboard
diff --git a/src/starboard/shared/starboard/media/codec_util.cc b/src/starboard/shared/starboard/media/codec_util.cc
index ce45a9b..54c905f 100644
--- a/src/starboard/shared/starboard/media/codec_util.cc
+++ b/src/starboard/shared/starboard/media/codec_util.cc
@@ -576,6 +576,52 @@
} // namespace
+VideoConfig::VideoConfig(SbMediaVideoCodec video_codec,
+ int width,
+ int height,
+ const uint8_t* data,
+ size_t size)
+ : width_(width), height_(height) {
+ if (video_codec == kSbMediaVideoCodecVp9) {
+ video_codec_ = video_codec;
+ } else if (video_codec == kSbMediaVideoCodecH264) {
+ avc_parameter_sets_ =
+ AvcParameterSets(AvcParameterSets::kAnnexB, data, size);
+ if (avc_parameter_sets_->is_valid()) {
+ video_codec_ = video_codec;
+ }
+ } else {
+ SB_NOTREACHED();
+ }
+}
+
+#if SB_API_VERSION >= 11
+VideoConfig::VideoConfig(const SbMediaVideoSampleInfo& video_sample_info,
+ const uint8_t* data,
+ size_t size)
+ : VideoConfig(video_sample_info.codec,
+ video_sample_info.frame_width,
+ video_sample_info.frame_height,
+ data,
+ size) {
+ SB_DCHECK(video_sample_info.is_key_frame);
+}
+#endif // SB_API_VERSION >= 11
+
+bool VideoConfig::operator==(const VideoConfig& that) const {
+ if (video_codec_ == kSbMediaVideoCodecNone &&
+ that.video_codec_ == kSbMediaVideoCodecNone) {
+ return true;
+ }
+ return video_codec_ == that.video_codec_ &&
+ avc_parameter_sets_ == that.avc_parameter_sets_ &&
+ width_ == that.width_ && height_ == that.height_;
+}
+
+bool VideoConfig::operator!=(const VideoConfig& that) const {
+ return !(*this == that);
+}
+
SbMediaAudioCodec GetAudioCodecFromString(const char* codec) {
if (SbStringCompare(codec, "mp4a.40.", 8) == 0) {
return kSbMediaAudioCodecAac;
diff --git a/src/starboard/shared/starboard/media/codec_util.h b/src/starboard/shared/starboard/media/codec_util.h
index 3edd3d5..c2dc302 100644
--- a/src/starboard/shared/starboard/media/codec_util.h
+++ b/src/starboard/shared/starboard/media/codec_util.h
@@ -15,14 +15,56 @@
#ifndef STARBOARD_SHARED_STARBOARD_MEDIA_CODEC_UTIL_H_
#define STARBOARD_SHARED_STARBOARD_MEDIA_CODEC_UTIL_H_
+#include <vector>
+
+#include "starboard/common/optional.h"
#include "starboard/media.h"
#include "starboard/shared/internal_only.h"
+#include "starboard/shared/starboard/media/avc_util.h"
namespace starboard {
namespace shared {
namespace starboard {
namespace media {
+// This class captures necessary information to describe a video config. It can
+// be used to detect config change of video stream during the playback.
+// The class only supports h264 and vp9 for now, which is checked in its ctor.
+class VideoConfig {
+ public:
+ // |data| must point to the encoded data of a key frame.
+ VideoConfig(SbMediaVideoCodec video_codec,
+ int width,
+ int height,
+ const uint8_t* data,
+ size_t size);
+
+#if SB_API_VERSION >= 11
+ VideoConfig(const SbMediaVideoSampleInfo& video_sample_info,
+ const uint8_t* data,
+ size_t size);
+#endif // SB_API_VERSION >= 11
+
+ bool is_valid() const { return video_codec_ != kSbMediaVideoCodecNone; }
+
+ const AvcParameterSets& avc_parameter_sets() const {
+ SB_DCHECK(is_valid());
+ SB_DCHECK(video_codec_ == kSbMediaVideoCodecH264);
+ SB_DCHECK(avc_parameter_sets_);
+ return avc_parameter_sets_.value();
+ }
+
+ bool operator==(const VideoConfig& that) const;
+ bool operator!=(const VideoConfig& that) const;
+
+ private:
+ SbMediaVideoCodec video_codec_ = kSbMediaVideoCodecNone;
+ int width_ = -1;
+ int height_ = -1;
+ // Only valid when |video_codec_| is |kSbMediaVideoCodecH264|.
+ optional<AvcParameterSets> avc_parameter_sets_;
+};
+
SbMediaAudioCodec GetAudioCodecFromString(const char* codec);
// This function parses the video codec string and returns a codec. All fields
diff --git a/src/starboard/shared/starboard/media/codec_util_test.cc b/src/starboard/shared/starboard/media/codec_util_test.cc
index 3399504..df2ede3 100644
--- a/src/starboard/shared/starboard/media/codec_util_test.cc
+++ b/src/starboard/shared/starboard/media/codec_util_test.cc
@@ -14,6 +14,9 @@
#include "starboard/shared/starboard/media/codec_util.h"
+#include <vector>
+
+#include "starboard/shared/starboard/media/avc_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace starboard {
@@ -22,7 +25,198 @@
namespace media {
namespace {
-class CodecUtilTest : public ::testing::Test {
+const auto kIdrStartCode = 0x65;
+const auto kSpsStartCode = AvcParameterSets::kSpsStartCode;
+const auto kPpsStartCode = AvcParameterSets::kPpsStartCode;
+const auto kAnnexB = AvcParameterSets::kAnnexB;
+
+const std::vector<uint8_t> kSpsInAnnexB = {0, 0, 0, 1, kSpsStartCode, 10, 11};
+const std::vector<uint8_t> kPpsInAnnexB = {0, 0, 0, 1, kPpsStartCode, 20};
+const std::vector<uint8_t> kIdrInAnnexB = {0, 0, 0, 1, kIdrStartCode,
+ 1, 2, 3, 4};
+
+std::vector<uint8_t> operator+(const std::vector<uint8_t>& left,
+ const std::vector<uint8_t>& right) {
+ std::vector<uint8_t> result(left);
+ result.insert(result.end(), right.begin(), right.end());
+ return result;
+}
+
+#if SB_API_VERSION >= 11
+TEST(VideoConfigTest, CtorWithSbMediaVideoSampleInfo) {
+ SbMediaVideoSampleInfo video_sample_info = {kSbMediaVideoCodecH264};
+ video_sample_info.is_key_frame = true;
+ video_sample_info.frame_width = 1920;
+ video_sample_info.frame_height = 1080;
+
+ std::vector<uint8_t> nalus_in_annex_b =
+ kSpsInAnnexB + kPpsInAnnexB + kIdrInAnnexB;
+
+ VideoConfig config_1(video_sample_info.codec, video_sample_info.frame_width,
+ video_sample_info.frame_height, nalus_in_annex_b.data(),
+ nalus_in_annex_b.size());
+ VideoConfig config_2(video_sample_info, nalus_in_annex_b.data(),
+ nalus_in_annex_b.size());
+ ASSERT_TRUE(config_1 == config_2);
+}
+#endif // SB_API_VERSION >= 11
+
+TEST(VideoConfigTest, IsValid) {
+ std::vector<uint8_t> nalus_in_annex_b =
+ kSpsInAnnexB + kPpsInAnnexB + kIdrInAnnexB;
+
+ {
+ VideoConfig config(kSbMediaVideoCodecH264, 1920, 1080, kPpsInAnnexB.data(),
+ kPpsInAnnexB.size());
+ ASSERT_TRUE(config.is_valid());
+ }
+ {
+ VideoConfig config(kSbMediaVideoCodecH264, 1920, 1080, kIdrInAnnexB.data(),
+ kIdrInAnnexB.size());
+ ASSERT_TRUE(config.is_valid());
+ }
+ {
+ VideoConfig config(kSbMediaVideoCodecH264, 1920, 1080,
+ nalus_in_annex_b.data(), nalus_in_annex_b.size());
+ ASSERT_TRUE(config.is_valid());
+ }
+ {
+ // The implementation only fails when the format is avc and the input isn't
+ // empty and doesn't start with a nalu header.
+ VideoConfig config(kSbMediaVideoCodecH264, 1920, 1080,
+ nalus_in_annex_b.data() + 1,
+ nalus_in_annex_b.size() - 1);
+ ASSERT_FALSE(config.is_valid());
+ }
+ {
+ VideoConfig config(kSbMediaVideoCodecVp9, 1920, 1080, nullptr, 0);
+ ASSERT_TRUE(config.is_valid());
+ }
+}
+
+TEST(VideoConfigTest, SelfComparison) {
+ {
+ std::vector<uint8_t> nalus_in_annex_b =
+ kSpsInAnnexB + kPpsInAnnexB + kIdrInAnnexB;
+
+ VideoConfig config(kSbMediaVideoCodecH264, 640, 480,
+ nalus_in_annex_b.data(), nalus_in_annex_b.size());
+ EXPECT_TRUE(config == config);
+ EXPECT_FALSE(config != config);
+ }
+ {
+ VideoConfig config(kSbMediaVideoCodecVp9, 640, 480, nullptr, 0);
+ EXPECT_TRUE(config == config);
+ EXPECT_FALSE(config != config);
+ }
+}
+
+TEST(VideoConfigTest, H264) {
+ std::vector<uint8_t> nalus_in_annex_b =
+ kSpsInAnnexB + kPpsInAnnexB + kIdrInAnnexB;
+
+ VideoConfig config(kSbMediaVideoCodecH264, 640, 480, nalus_in_annex_b.data(),
+ nalus_in_annex_b.size());
+
+ // Different resolution, same parameter sets.
+ VideoConfig config_1(kSbMediaVideoCodecH264, 1920, 1080,
+ nalus_in_annex_b.data(), nalus_in_annex_b.size());
+ EXPECT_TRUE(config != config_1);
+ EXPECT_TRUE(config.avc_parameter_sets() == config_1.avc_parameter_sets());
+ EXPECT_FALSE(config == config_1);
+
+ // Same resolution, different parameter sets.
+ nalus_in_annex_b =
+ kSpsInAnnexB + kPpsInAnnexB + std::vector<uint8_t>({99}) + kIdrInAnnexB;
+ VideoConfig config_2(kSbMediaVideoCodecH264, 640, 480,
+ nalus_in_annex_b.data(), nalus_in_annex_b.size());
+ EXPECT_TRUE(config != config_2);
+ EXPECT_FALSE(config == config_2);
+
+ // Same resolution, same parameter sets, different idr data.
+ nalus_in_annex_b = kSpsInAnnexB + kPpsInAnnexB + kIdrInAnnexB;
+ nalus_in_annex_b.push_back(99);
+
+ VideoConfig config_3(kSbMediaVideoCodecH264, 640, 480,
+ nalus_in_annex_b.data(), nalus_in_annex_b.size());
+ EXPECT_TRUE(config == config_3);
+ EXPECT_FALSE(config != config_3);
+}
+
+TEST(VideoConfigTest, H264MultiSpsPps) {
+ // Single sps and pps.
+ std::vector<uint8_t> nalus_in_annex_b =
+ kSpsInAnnexB + kPpsInAnnexB + kIdrInAnnexB;
+
+ VideoConfig config_single_sps_pps(kSbMediaVideoCodecH264, 640, 480,
+ nalus_in_annex_b.data(),
+ nalus_in_annex_b.size());
+
+ // Same resolution, multiple parameter sets.
+ nalus_in_annex_b =
+ kSpsInAnnexB + kSpsInAnnexB + kPpsInAnnexB + kPpsInAnnexB + kIdrInAnnexB;
+
+ VideoConfig config_dual_sps_pps(kSbMediaVideoCodecH264, 640, 480,
+ nalus_in_annex_b.data(),
+ nalus_in_annex_b.size());
+ EXPECT_TRUE(config_single_sps_pps != config_dual_sps_pps);
+ EXPECT_FALSE(config_single_sps_pps == config_dual_sps_pps);
+ EXPECT_TRUE(config_dual_sps_pps.avc_parameter_sets() ==
+ AvcParameterSets(kAnnexB, nalus_in_annex_b.data(),
+ nalus_in_annex_b.size()));
+
+ // Same resolution, different parameter sets.
+ nalus_in_annex_b =
+ kSpsInAnnexB + kPpsInAnnexB + std::vector<uint8_t>({99}) + kIdrInAnnexB;
+ VideoConfig config_1(kSbMediaVideoCodecH264, 640, 480,
+ nalus_in_annex_b.data(), nalus_in_annex_b.size());
+ EXPECT_TRUE(config_single_sps_pps != config_1);
+ EXPECT_FALSE(config_single_sps_pps == config_1);
+
+ // Same resolution, same parameter sets, different idr data.
+ nalus_in_annex_b = kSpsInAnnexB + kPpsInAnnexB + kIdrInAnnexB;
+ nalus_in_annex_b.push_back(99);
+
+ VideoConfig config_2(kSbMediaVideoCodecH264, 640, 480,
+ nalus_in_annex_b.data(), nalus_in_annex_b.size());
+ EXPECT_TRUE(config_single_sps_pps == config_2);
+ EXPECT_FALSE(config_single_sps_pps != config_2);
+}
+
+TEST(VideoConfigTest, Vp9) {
+ // The class shouldn't look into vp9 bitstreams.
+ const uint8_t kInvalidData[] = {1, 7, 25};
+
+ VideoConfig config(kSbMediaVideoCodecVp9, 640, 480, kInvalidData,
+ SB_ARRAY_SIZE(kInvalidData));
+
+ // Different resolution, same data.
+ VideoConfig config_1(kSbMediaVideoCodecVp9, 1920, 1080, kInvalidData,
+ SB_ARRAY_SIZE(kInvalidData));
+ EXPECT_TRUE(config != config_1);
+ EXPECT_FALSE(config == config_1);
+
+ // Same resolution, different data (one less byte).
+ VideoConfig config_2(kSbMediaVideoCodecVp9, 640, 480, kInvalidData,
+ SB_ARRAY_SIZE(kInvalidData) - 1);
+ EXPECT_TRUE(config == config_2);
+ EXPECT_FALSE(config != config_2);
+}
+
+TEST(VideoConfigTest, H264VsVp9) {
+ std::vector<uint8_t> nalus_in_annex_b =
+ kSpsInAnnexB + kPpsInAnnexB + kIdrInAnnexB;
+
+ VideoConfig config_h264(kSbMediaVideoCodecH264, 640, 480,
+ nalus_in_annex_b.data(), nalus_in_annex_b.size());
+ VideoConfig config_vp9(kSbMediaVideoCodecVp9, 640, 480,
+ nalus_in_annex_b.data(), nalus_in_annex_b.size());
+
+ EXPECT_TRUE(config_h264 != config_vp9);
+ EXPECT_FALSE(config_h264 == config_vp9);
+}
+
+class ParseVideoCodecTest : public ::testing::Test {
protected:
bool Parse(const char* codec_string) {
return ParseVideoCodec(codec_string, &codec_, &profile_, &level_,
@@ -39,7 +233,7 @@
SbMediaMatrixId matrix_id_;
};
-TEST_F(CodecUtilTest, SimpleCodecs) {
+TEST_F(ParseVideoCodecTest, SimpleCodecs) {
const char* kCodecStrings[] = {"vp8", "vp9"};
const SbMediaVideoCodec kVideoCodecs[] = {kSbMediaVideoCodecVp8,
kSbMediaVideoCodecVp9};
@@ -55,7 +249,7 @@
}
}
-TEST_F(CodecUtilTest, ShortFormAv1) {
+TEST_F(ParseVideoCodecTest, ShortFormAv1) {
ASSERT_TRUE(Parse("av01.0.01M.08"));
#if SB_API_VERSION < 11
EXPECT_EQ(codec_, kSbMediaVideoCodecVp10);
@@ -70,7 +264,7 @@
EXPECT_EQ(matrix_id_, kSbMediaMatrixIdBt709);
}
-TEST_F(CodecUtilTest, LongFormAv1) {
+TEST_F(ParseVideoCodecTest, LongFormAv1) {
ASSERT_TRUE(Parse("av01.0.04M.10.0.110.09.16.09.0"));
#if SB_API_VERSION < 11
EXPECT_EQ(codec_, kSbMediaVideoCodecVp10);
@@ -85,7 +279,7 @@
EXPECT_EQ(matrix_id_, kSbMediaMatrixIdBt2020NonconstantLuminance);
}
-TEST_F(CodecUtilTest, InvalidAv1) {
+TEST_F(ParseVideoCodecTest, InvalidAv1) {
EXPECT_FALSE(Parse("av01.0.04M.10.0.110.9.16.9.0"));
EXPECT_FALSE(Parse("av01.0.04M.10.0.110.09.16.09"));
EXPECT_FALSE(Parse("av01.0.04M.10.0.110.09.16"));
@@ -101,7 +295,7 @@
EXPECT_FALSE(Parse("av01.0.04M.10.0.110.09.16.09.2"));
}
-TEST_F(CodecUtilTest, Avc) {
+TEST_F(ParseVideoCodecTest, Avc) {
ASSERT_TRUE(Parse("avc1.640028"));
EXPECT_EQ(codec_, kSbMediaVideoCodecH264);
EXPECT_EQ(profile_, 100);
@@ -121,13 +315,13 @@
EXPECT_EQ(matrix_id_, kSbMediaMatrixIdUnspecified);
}
-TEST_F(CodecUtilTest, InvalidAvc) {
+TEST_F(ParseVideoCodecTest, InvalidAvc) {
EXPECT_FALSE(Parse("avc1.64002"));
EXPECT_FALSE(Parse("avc2.640028"));
EXPECT_FALSE(Parse("avc3.640028.1"));
}
-TEST_F(CodecUtilTest, H265) {
+TEST_F(ParseVideoCodecTest, H265) {
ASSERT_TRUE(Parse("hvc1.1.2.L93.B0"));
EXPECT_EQ(codec_, kSbMediaVideoCodecH265);
EXPECT_EQ(profile_, 1);
@@ -145,7 +339,7 @@
EXPECT_TRUE(Parse("hvc1.C1.ABCDEF01.H93.B0"));
}
-TEST_F(CodecUtilTest, InvalidH265) {
+TEST_F(ParseVideoCodecTest, InvalidH265) {
EXPECT_FALSE(Parse("hvc2.1.2.L93.B0"));
EXPECT_FALSE(Parse("hvc1.D1.2.L93.B0"));
EXPECT_FALSE(Parse("hvc1.A111.2.L93.B0"));
@@ -156,7 +350,7 @@
EXPECT_FALSE(Parse("hvc1.1.2.L93.B0.B1.B2.B3.B4.B5.B6"));
}
-TEST_F(CodecUtilTest, ShortFormVp9) {
+TEST_F(ParseVideoCodecTest, ShortFormVp9) {
ASSERT_TRUE(Parse("vp09.00.41.08"));
EXPECT_EQ(codec_, kSbMediaVideoCodecVp9);
EXPECT_EQ(profile_, 0);
@@ -167,7 +361,7 @@
EXPECT_EQ(matrix_id_, kSbMediaMatrixIdBt709);
}
-TEST_F(CodecUtilTest, MediumFormVp9) {
+TEST_F(ParseVideoCodecTest, MediumFormVp9) {
ASSERT_TRUE(Parse("vp09.02.10.10.01.09.16.09"));
EXPECT_EQ(codec_, kSbMediaVideoCodecVp9);
EXPECT_EQ(profile_, 2);
@@ -178,7 +372,7 @@
EXPECT_EQ(matrix_id_, kSbMediaMatrixIdBt2020NonconstantLuminance);
}
-TEST_F(CodecUtilTest, LongFormVp9) {
+TEST_F(ParseVideoCodecTest, LongFormVp9) {
ASSERT_TRUE(Parse("vp09.02.10.10.01.09.16.09.01"));
EXPECT_EQ(codec_, kSbMediaVideoCodecVp9);
EXPECT_EQ(profile_, 2);
@@ -189,7 +383,7 @@
EXPECT_EQ(matrix_id_, kSbMediaMatrixIdBt2020NonconstantLuminance);
}
-TEST_F(CodecUtilTest, InvalidVp9) {
+TEST_F(ParseVideoCodecTest, InvalidVp9) {
EXPECT_FALSE(Parse("vp09.02.10.10.01.9.16.9"));
EXPECT_FALSE(Parse("vp09.02.10.10.01.09.16"));
EXPECT_FALSE(Parse("vp09.02.10.10.01.09"));
diff --git a/src/starboard/shared/starboard/media/media.gyp b/src/starboard/shared/starboard/media/media.gyp
index fb4e361..50e97b5 100644
--- a/src/starboard/shared/starboard/media/media.gyp
+++ b/src/starboard/shared/starboard/media/media.gyp
@@ -19,6 +19,8 @@
'target_name': 'media_util',
'type': 'static_library',
'sources': [
+ '<(DEPTH)/starboard/shared/starboard/media/avc_util.cc',
+ '<(DEPTH)/starboard/shared/starboard/media/avc_util.h',
'<(DEPTH)/starboard/shared/starboard/media/codec_util.cc',
'<(DEPTH)/starboard/shared/starboard/media/codec_util.h',
'<(DEPTH)/starboard/shared/starboard/media/media_util.cc',
diff --git a/src/starboard/shared/starboard/media/media_get_audio_buffer_budget.cc b/src/starboard/shared/starboard/media/media_get_audio_buffer_budget.cc
index 7f909ac..8a88034 100644
--- a/src/starboard/shared/starboard/media/media_get_audio_buffer_budget.cc
+++ b/src/starboard/shared/starboard/media/media_get_audio_buffer_budget.cc
@@ -14,23 +14,6 @@
#include "starboard/media.h"
-#include "starboard/common/log.h"
-
-#if SB_API_VERSION >= 10
-// This is the legacy default value of the GYP variable.
-#define LEGACY_NON_VIDEO_BUDGET 5 * 1024 * 1024
-
int SbMediaGetAudioBufferBudget() {
-#if defined(COBALT_MEDIA_BUFFER_NON_VIDEO_BUDGET) && \
- COBALT_MEDIA_BUFFER_NON_VIDEO_BUDGET != LEGACY_NON_VIDEO_BUDGET
- SB_DLOG(WARNING) << "COBALT_MEDIA_BUFFER_NON_VIDEO_BUDGET will be deprecated "
- "in a future Starboard version.";
- // Use define forwarded from GYP variable.
- return COBALT_MEDIA_BUFFER_NON_VIDEO_BUDGET;
-#else // defined(COBALT_MEDIA_BUFFER_NON_VIDEO_BUDGET) &&
- // COBALT_MEDIA_BUFFER_NON_VIDEO_BUDGET != LEGACY_NON_VIDEO_BUDGET
return 5 * 1024 * 1024;
-#endif // defined(COBALT_MEDIA_BUFFER_NON_VIDEO_BUDGET) &&
- // COBALT_MEDIA_BUFFER_NON_VIDEO_BUDGET != LEGACY_NON_VIDEO_BUDGET
}
-#endif // SB_API_VERSION >= 10
diff --git a/src/starboard/shared/starboard/media/media_get_audio_output_count_stereo_only.cc b/src/starboard/shared/starboard/media/media_get_audio_output_count_stereo_only.cc
index c101880..7c908c8 100644
--- a/src/starboard/shared/starboard/media/media_get_audio_output_count_stereo_only.cc
+++ b/src/starboard/shared/starboard/media/media_get_audio_output_count_stereo_only.cc
@@ -16,15 +16,9 @@
#include "starboard/media.h"
-#if SB_API_VERSION >= 10
#error File media_get_audio_output_count_stereo_only.cc is deprecated, \
consider using media_get_audio_output_count_single_audio_output.cc instead.
-#else // SB_API_VERSION >= 10
-#pragma message( \
- "File media_get_audio_output_count_stereo_only.cc will be deprecated, " \
- "consider using media_get_audio_output_count_single_audio_output.cc " \
- "instead.")
-#endif // SB_API_VERSION >= 10
+
int SbMediaGetAudioOutputCount() {
return 1;
}
diff --git a/src/starboard/shared/starboard/media/media_get_buffer_alignment.cc b/src/starboard/shared/starboard/media/media_get_buffer_alignment.cc
index 067795a..9b0b88a 100644
--- a/src/starboard/shared/starboard/media/media_get_buffer_alignment.cc
+++ b/src/starboard/shared/starboard/media/media_get_buffer_alignment.cc
@@ -14,25 +14,7 @@
#include "starboard/media.h"
-#include "starboard/common/log.h"
-
-#if SB_API_VERSION >= 10
-// This is the legacy default value of the GYP variable.
-#define LEGACY_BUFFER_ALIGNMENT 1
-
int SbMediaGetBufferAlignment(SbMediaType type) {
SB_UNREFERENCED_PARAMETER(type);
-#if defined(COBALT_MEDIA_BUFFER_ALIGNMENT) && \
- COBALT_MEDIA_BUFFER_ALIGNMENT != LEGACY_BUFFER_ALIGNMENT
-#pragma message( \
- "COBALT_MEDIA_BUFFER_ALIGNMENT will be deprecated in a future " \
- "Starboard version.")
- // Use define forwarded from GYP variable.
- return COBALT_MEDIA_BUFFER_ALIGNMENT;
-#else // defined(COBALT_MEDIA_BUFFER_ALIGNMENT && COBALT_MEDIA_BUFFER_ALIGNMENT
- // != LEGACY_BUFFER_ALIGNMENT
return 1;
-#endif // defined(COBALT_MEDIA_BUFFER_ALIGNMENT &&
- // COBALT_MEDIA_BUFFER_ALIGNMENT != LEGACY_BUFFER_ALIGNMENT
}
-#endif // SB_API_VERSION >= 10
diff --git a/src/starboard/shared/starboard/media/media_get_buffer_allocation_unit.cc b/src/starboard/shared/starboard/media/media_get_buffer_allocation_unit.cc
index d9d2909..78c7d30 100644
--- a/src/starboard/shared/starboard/media/media_get_buffer_allocation_unit.cc
+++ b/src/starboard/shared/starboard/media/media_get_buffer_allocation_unit.cc
@@ -14,21 +14,6 @@
#include "starboard/media.h"
-#include "starboard/common/log.h"
-
-#if SB_API_VERSION >= 10
-// This is the legacy default value of the GYP variable.
-#define LEGACY_ALLOCATION_UNIT 1 * 1024 * 1024
-
int SbMediaGetBufferAllocationUnit() {
-#if defined(COBALT_MEDIA_BUFFER_ALLOCATION_UNIT) && \
- COBALT_MEDIA_BUFFER_ALLOCATION_UNIT != LEGACY_ALLOCATION_UNIT
- SB_DLOG(WARNING) << "COBALT_MEDIA_BUFFER_ALLOCATION_UNIT will be deprecated "
- "in a future Starboard version.";
- // Use define forwarded from GYP variable.
- return COBALT_MEDIA_BUFFER_ALLOCATION_UNIT;
-#else // defined(COBALT_MEDIA_BUFFER_ALLOCATION_UNIT
return 4 * 1024 * 1024;
-#endif // defined(COBALT_MEDIA_BUFFER_ALLOCATION_UNIT
}
-#endif // SB_API_VERSION >= 10
diff --git a/src/starboard/shared/starboard/media/media_get_buffer_garbage_collection_duration_threshold.cc b/src/starboard/shared/starboard/media/media_get_buffer_garbage_collection_duration_threshold.cc
index b9e30fd..a89285c 100644
--- a/src/starboard/shared/starboard/media/media_get_buffer_garbage_collection_duration_threshold.cc
+++ b/src/starboard/shared/starboard/media/media_get_buffer_garbage_collection_duration_threshold.cc
@@ -14,31 +14,6 @@
#include "starboard/media.h"
-#include "starboard/common/log.h"
-
-#if SB_API_VERSION >= 10
-// This is the legacy default value of the GYP variable.
-#define LEGACY_GARBAGE_COLLECTION_DURATION 170
-
SbTime SbMediaGetBufferGarbageCollectionDurationThreshold() {
-#if defined( \
- COBALT_MEDIA_SOURCE_GARBAGE_COLLECTION_DURATION_THRESHOLD_IN_SECONDS) && \
- COBALT_MEDIA_SOURCE_GARBAGE_COLLECTION_DURATION_THRESHOLD_IN_SECONDS != \
- LEGACY_GARBAGE_COLLECTION_DURATION
-// Use define forwarded from GYP variable.
-#pragma message( \
- "COBALT_MEDIA_SOURCE_GARBAGE_COLLECTION_DURATION_THRESHOLD_IN_SECONDS " \
- "will be deprecated in a future Starboard version.")
- return COBALT_MEDIA_SOURCE_GARBAGE_COLLECTION_DURATION_THRESHOLD_IN_SECONDS *
- kSbTimeSecond;
-#else // defined(COBALT_MEDIA_SOURCE_GARBAGE_COLLECTION_DURATION_THRESHOLD_IN_SECONDS)
- // &&
- // COBALT_MEDIA_SOURCE_GARBAGE_COLLECTION_DURATION_THRESHOLD_IN_SECONDS !=
- // LEGACY_GARBAGE_COLLECTION_DURATION
return 170 * kSbTimeSecond;
-#endif // defined(COBALT_MEDIA_SOURCE_GARBAGE_COLLECTION_DURATION_THRESHOLD_IN_SECONDS)
- // &&
- // COBALT_MEDIA_SOURCE_GARBAGE_COLLECTION_DURATION_THRESHOLD_IN_SECONDS !=
- // LEGACY_GARBAGE_COLLECTION_DURATION
}
-#endif // SB_API_VERSION >= 10
diff --git a/src/starboard/shared/starboard/media/media_get_buffer_padding.cc b/src/starboard/shared/starboard/media/media_get_buffer_padding.cc
index 2665ea6..3384e9f 100644
--- a/src/starboard/shared/starboard/media/media_get_buffer_padding.cc
+++ b/src/starboard/shared/starboard/media/media_get_buffer_padding.cc
@@ -14,25 +14,7 @@
#include "starboard/media.h"
-#include "starboard/common/log.h"
-
-#if SB_API_VERSION >= 10
-
-#define LEGACY_BUFFER_PADDING 0
-
int SbMediaGetBufferPadding(SbMediaType type) {
SB_UNREFERENCED_PARAMETER(type);
-#if defined(COBALT_MEDIA_BUFFER_PADDING) && \
- COBALT_MEDIA_BUFFER_PADDING != LEGACY_BUFFER_PADDING
-#pragma message( \
- "COBALT_MEDIA_BUFFER_PADDING will be deprecated in a future Starboard " \
- "version.")
- // Use define forwarded from GYP variable.
- return COBALT_MEDIA_BUFFER_PADDING;
-#else // defined(COBALT_MEDIA_BUFFER_PADDING) && COBALT_MEDIA_BUFFER_PADDING !=
- // LEGACY_BUFFER_PADDING
return 0;
-#endif // defined(COBALT_MEDIA_BUFFER_PADDING) && COBALT_MEDIA_BUFFER_PADDING
- // != LEGACY_BUFFER_PADDING
}
-#endif // SB_API_VERSION >= 10
diff --git a/src/starboard/shared/starboard/media/media_get_buffer_storage_type.cc b/src/starboard/shared/starboard/media/media_get_buffer_storage_type.cc
index c96b296..3d8dfcd 100644
--- a/src/starboard/shared/starboard/media/media_get_buffer_storage_type.cc
+++ b/src/starboard/shared/starboard/media/media_get_buffer_storage_type.cc
@@ -14,22 +14,6 @@
#include "starboard/media.h"
-#include "starboard/common/log.h"
-
-#if SB_API_VERSION >= 10
-
SbMediaBufferStorageType SbMediaGetBufferStorageType() {
-// Use define forwarded from GYP variable.
-#if defined(COBALT_MEDIA_BUFFER_STORAGE_TYPE_MEMORY)
- // This is the legacy default value of the GYP variable, so don't warn.
return kSbMediaBufferStorageTypeMemory;
-#elif defined(COBALT_MEDIA_BUFFER_STORAGE_TYPE_FILE)
- SB_DLOG(WARNING) << "COBALT_MEDIA_BUFFER_STORAGE_TYPE_FILE will be "
- "deprecated in a future Starboard version.";
- return kSbMediaBufferStorageTypeFile;
-#else // defined(COBALT_MEDIA_BUFFER_STORAGE_TYPE_MEMORY)
- // In the absence of other information, assume memory storage is the default.
- return kSbMediaBufferStorageTypeMemory;
-#endif // defined(COBALT_MEDIA_BUFFER_STORAGE_TYPE_MEMORY)
}
-#endif // SB_API_VERSION >= 10
diff --git a/src/starboard/shared/starboard/media/media_get_initial_buffer_capacity.cc b/src/starboard/shared/starboard/media/media_get_initial_buffer_capacity.cc
index 1947456..2e0e86e 100644
--- a/src/starboard/shared/starboard/media/media_get_initial_buffer_capacity.cc
+++ b/src/starboard/shared/starboard/media/media_get_initial_buffer_capacity.cc
@@ -14,24 +14,6 @@
#include "starboard/media.h"
-#include "starboard/common/log.h"
-
-#if SB_API_VERSION >= 10
-// This is the legacy default value of the GYP variable.
-#define LEGACY_INITIAL_CAPACITY 21 * 1024 * 1024
-
int SbMediaGetInitialBufferCapacity() {
-#if defined(COBALT_MEDIA_BUFFER_INITIAL_CAPACITY) && \
- COBALT_MEDIA_BUFFER_INITIAL_CAPACITY != LEGACY_INITIAL_CAPACITY
-#pragma message( \
- "COBALT_MEDIA_BUFFER_INITIAL_CAPACITY will be deprecated in a future " \
- "Starboard version.")
- // Use define forwarded from GYP variable.
- return COBALT_MEDIA_BUFFER_INITIAL_CAPACITY;
-#else // defined(COBALT_MEDIA_BUFFER_INITIAL_CAPACITY) &&
- // COBALT_MEDIA_BUFFER_INITIAL_CAPACITY != LEGACY_INITIAL_CAPACITY
return 21 * 1024 * 1024;
-#endif // defined(COBALT_MEDIA_BUFFER_INITIAL_CAPACITY) &&
- // COBALT_MEDIA_BUFFER_INITIAL_CAPACITY != LEGACY_INITIAL_CAPACITY
}
-#endif // SB_API_VERSION >= 10
diff --git a/src/starboard/shared/starboard/media/media_get_max_buffer_capacity.cc b/src/starboard/shared/starboard/media/media_get_max_buffer_capacity.cc
index 1410b43..f501f92 100644
--- a/src/starboard/shared/starboard/media/media_get_max_buffer_capacity.cc
+++ b/src/starboard/shared/starboard/media/media_get_max_buffer_capacity.cc
@@ -14,13 +14,6 @@
#include "starboard/media.h"
-#include "starboard/common/log.h"
-
-#if SB_API_VERSION >= 10
-// These are the legacy default values of the GYP variables.
-#define LEGACY_MAX_CAPACITY_1080P 50 * 1024 * 1024
-#define LEGACY_MAX_CAPACITY_4K 140 * 1024 * 1024
-
int SbMediaGetMaxBufferCapacity(SbMediaVideoCodec codec,
int resolution_width,
int resolution_height,
@@ -32,17 +25,7 @@
// The maximum amount of memory that will be used to store media buffers
// when video resolution is 1080p. If 0, then memory can grow without bound.
// This must be larger than sum of 1080p video budget and non-video budget.
-#if defined(COBALT_MEDIA_BUFFER_MAX_CAPACITY_1080P) && \
- COBALT_MEDIA_BUFFER_MAX_CAPACITY_1080P != LEGACY_MAX_CAPACITY_1080P
- SB_DLOG(WARNING) << "COBALT_MEDIA_BUFFER_MAX_CAPACITY_1080P will be "
- "deprecated in a future Starboard version.";
- // Use define forwarded from GYP variable.
- return COBALT_MEDIA_BUFFER_MAX_CAPACITY_1080P;
-#else // defined(COBALT_MEDIA_BUFFER_MAX_CAPACITY_1080P) &&
- // COBALT_MEDIA_BUFFER_MAX_CAPACITY_1080P != LEGACY_MAX_CAPACITY_1080P
return 50 * 1024 * 1024;
-#endif // defined(COBALT_MEDIA_BUFFER_MAX_CAPACITY_1080P) &&
- // COBALT_MEDIA_BUFFER_MAX_CAPACITY_1080P != LEGACY_MAX_CAPACITY_1080P
}
if (resolution_width <= 3840 && resolution_height <= 2160) {
@@ -51,17 +34,7 @@
// when video resolution is 4k and bit per pixel is lower than 8. If 0,
// then memory can grow without bound. This must be larger than sum of 4k
// video budget and non-video budget.
-#if defined(COBALT_MEDIA_BUFFER_MAX_CAPACITY_4K) && \
- COBALT_MEDIA_BUFFER_MAX_CAPACITY_4K != LEGACY_MAX_CAPACITY_4K
- SB_DLOG(WARNING) << "COBALT_MEDIA_BUFFER_MAX_CAPACITY_4K will be "
- "deprecated in a future Starboard version.";
- // Use define forwarded from GYP variable.
- return COBALT_MEDIA_BUFFER_MAX_CAPACITY_4K;
-#else // defined(COBALT_MEDIA_BUFFER_MAX_CAPACITY_4K) &&
- // COBALT_MEDIA_BUFFER_MAX_CAPACITY_4K != LEGACY_MAX_CAPACITY_4K
return 140 * 1024 * 1024;
-#endif // defined(COBALT_MEDIA_BUFFER_MAX_CAPACITY_4K) &&
- // COBALT_MEDIA_BUFFER_MAX_CAPACITY_4K != LEGACY_MAX_CAPACITY_4K
} else {
// The maximum amount of memory that will be used to store media buffers
// when video resolution is 4k and bit per pixel is greater than 8. If 0,
@@ -76,4 +49,3 @@
// must be larger than sum of 8k video budget and non-video budget.
return 360 * 1024 * 1024;
}
-#endif // SB_API_VERSION >= 10
diff --git a/src/starboard/shared/starboard/media/media_get_progressive_buffer_budget.cc b/src/starboard/shared/starboard/media/media_get_progressive_buffer_budget.cc
index 35b68b9..2c80ec7 100644
--- a/src/starboard/shared/starboard/media/media_get_progressive_buffer_budget.cc
+++ b/src/starboard/shared/starboard/media/media_get_progressive_buffer_budget.cc
@@ -14,12 +14,6 @@
#include "starboard/media.h"
-#include "starboard/common/log.h"
-
-#if SB_API_VERSION >= 10
-// This is the legacy default value of the GYP variable.
-#define LEGACY_PROGRESSIVE_BUDGET 12 * 1024 * 1024
-
int SbMediaGetProgressiveBufferBudget(SbMediaVideoCodec codec,
int resolution_width,
int resolution_height,
@@ -28,16 +22,5 @@
SB_UNREFERENCED_PARAMETER(resolution_width);
SB_UNREFERENCED_PARAMETER(resolution_height);
SB_UNREFERENCED_PARAMETER(bits_per_pixel);
-#if defined(COBALT_MEDIA_BUFFER_PROGRESSIVE_BUDGET) && \
- COBALT_MEDIA_BUFFER_PROGRESSIVE_BUDGET != LEGACY_PROGRESSIVE_BUDGET
- SB_DLOG(WARNING) << "COBALT_MEDIA_BUFFER_PROGRESSIVE_BUDGET will be "
- "deprecated in a future Starboard version.";
- // Use define forwarded from GYP variable.
- return COBALT_MEDIA_BUFFER_PROGRESSIVE_BUDGET;
-#else // defined(COBALT_MEDIA_BUFFER_PROGRESSIVE_BUDGET) &&
- // COBALT_MEDIA_BUFFER_PROGRESSIVE_BUDGET != LEGACY_PROGRESSIVE_BUDGET
return 12 * 1024 * 1024;
-#endif // defined(COBALT_MEDIA_BUFFER_PROGRESSIVE_BUDGET) &&
- // COBALT_MEDIA_BUFFER_PROGRESSIVE_BUDGET != LEGACY_PROGRESSIVE_BUDGET
}
-#endif // SB_API_VERSION >= 10
diff --git a/src/starboard/shared/starboard/media/media_get_video_buffer_budget.cc b/src/starboard/shared/starboard/media/media_get_video_buffer_budget.cc
index bb8352e..339f204 100644
--- a/src/starboard/shared/starboard/media/media_get_video_buffer_budget.cc
+++ b/src/starboard/shared/starboard/media/media_get_video_buffer_budget.cc
@@ -14,13 +14,6 @@
#include "starboard/media.h"
-#include "starboard/common/log.h"
-
-#if SB_API_VERSION >= 10
-// These are the legacy default values of the GYP variables.
-#define LEGACY_VIDEO_BUDGET_1080P 30 * 1024 * 1024
-#define LEGACY_VIDEO_BUDGET_4K 100 * 1024 * 1024
-
int SbMediaGetVideoBufferBudget(SbMediaVideoCodec codec,
int resolution_width,
int resolution_height,
@@ -32,17 +25,7 @@
// Specifies the maximum amount of memory used by video buffers of media
// source before triggering a garbage collection when the video resolution
// is lower than 1080p (1920x1080).
-#if defined(COBALT_MEDIA_BUFFER_VIDEO_BUDGET_1080P) && \
- COBALT_MEDIA_BUFFER_VIDEO_BUDGET_1080P != LEGACY_VIDEO_BUDGET_1080P
- SB_DLOG(WARNING) << "COBALT_MEDIA_BUFFER_VIDEO_BUDGET_1080P will be "
- "deprecated in a future Starboard version.";
- // Use define forwarded from GYP variable.
- return COBALT_MEDIA_BUFFER_VIDEO_BUDGET_1080P;
-#else // defined(COBALT_MEDIA_BUFFER_VIDEO_BUDGET_1080P) &&
- // COBALT_MEDIA_BUFFER_VIDEO_BUDGET_1080P != LEGACY_VIDEO_BUDGET_1080P
return 30 * 1024 * 1024;
-#endif // defined(COBALT_MEDIA_BUFFER_VIDEO_BUDGET_1080P) &&
- // COBALT_MEDIA_BUFFER_VIDEO_BUDGET_1080P != LEGACY_VIDEO_BUDGET_1080P
}
if (resolution_width <= 3840 && resolution_height <= 2160) {
@@ -50,17 +33,7 @@
// Specifies the maximum amount of memory used by video buffers of media
// source before triggering a garbage collection when the video resolution
// is lower than 4k (3840x2160) and bit per pixel is lower than 8.
-#if defined(COBALT_MEDIA_BUFFER_VIDEO_BUDGET_4K) && \
- COBALT_MEDIA_BUFFER_VIDEO_BUDGET_4K != LEGACY_VIDEO_BUDGET_4K
- SB_DLOG(WARNING) << "COBALT_MEDIA_BUFFER_VIDEO_BUDGET_4K will be "
- "deprecated in a future Starboard version.";
- // Use define forwarded from GYP variable.
- return COBALT_MEDIA_BUFFER_VIDEO_BUDGET_4K;
-#else // defined(COBALT_MEDIA_BUFFER_VIDEO_BUDGET_4K) &&
- // COBALT_MEDIA_BUFFER_VIDEO_BUDGET_4K != LEGACY_VIDEO_BUDGET_4K
return 100 * 1024 * 1024;
-#endif // defined(COBALT_MEDIA_BUFFER_VIDEO_BUDGET_4K) &&
- // COBALT_MEDIA_BUFFER_VIDEO_BUDGET_4K != LEGACY_VIDEO_BUDGET_4K
} else {
// Specifies the maximum amount of memory used by video buffers of media
// source before triggering a garbage collection when video resolution is
@@ -74,4 +47,3 @@
// lower than 8k (7680x4320).
return 300 * 1024 * 1024;
}
-#endif // SB_API_VERSION >= 10
diff --git a/src/starboard/shared/starboard/media/media_is_audio_supported_aac_and_opus.cc b/src/starboard/shared/starboard/media/media_is_audio_supported_aac_and_opus.cc
index 23937a7..ff2a9d3 100644
--- a/src/starboard/shared/starboard/media/media_is_audio_supported_aac_and_opus.cc
+++ b/src/starboard/shared/starboard/media/media_is_audio_supported_aac_and_opus.cc
@@ -18,7 +18,15 @@
#include "starboard/configuration_constants.h"
#include "starboard/media.h"
-bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec, int64_t bitrate) {
+bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec,
+#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+ const char* content_type,
+#endif // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+ int64_t bitrate) {
+#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+ SB_UNREFERENCED_PARAMETER(content_type);
+#endif // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+
if (audio_codec == kSbMediaAudioCodecAac) {
return bitrate <= kSbMediaMaxAudioBitrateInBitsPerSecond;
}
diff --git a/src/starboard/shared/starboard/media/media_is_audio_supported_aac_only.cc b/src/starboard/shared/starboard/media/media_is_audio_supported_aac_only.cc
index 843ba3a..7bdcec8 100644
--- a/src/starboard/shared/starboard/media/media_is_audio_supported_aac_only.cc
+++ b/src/starboard/shared/starboard/media/media_is_audio_supported_aac_only.cc
@@ -18,7 +18,15 @@
#include "starboard/configuration_constants.h"
#include "starboard/media.h"
-bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec, int64_t bitrate) {
+bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec,
+#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+ const char* content_type,
+#endif // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+ int64_t bitrate) {
+#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+ SB_UNREFERENCED_PARAMETER(content_type);
+#endif // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+
return audio_codec == kSbMediaAudioCodecAac &&
bitrate <= kSbMediaMaxAudioBitrateInBitsPerSecond;
}
diff --git a/src/starboard/shared/starboard/media/media_is_buffer_pool_allocate_on_demand.cc b/src/starboard/shared/starboard/media/media_is_buffer_pool_allocate_on_demand.cc
index 1caf8a0..229b4b3 100644
--- a/src/starboard/shared/starboard/media/media_is_buffer_pool_allocate_on_demand.cc
+++ b/src/starboard/shared/starboard/media/media_is_buffer_pool_allocate_on_demand.cc
@@ -14,25 +14,6 @@
#include "starboard/media.h"
-#include "starboard/common/log.h"
-
-#if SB_API_VERSION >= 10
-// This is the legacy default value of the GYP variable.
-#define LEGACY_ALLOCATE_ON_DEMAND 1
-
bool SbMediaIsBufferPoolAllocateOnDemand() {
-#if defined(COBALT_MEDIA_BUFFER_POOL_ALLOCATE_ON_DEMAND) && \
- COBALT_MEDIA_BUFFER_POOL_ALLOCATE_ON_DEMAND != LEGACY_ALLOCATE_ON_DEMAND
-#pragma message( \
- "COBALT_MEDIA_BUFFER_POOL_ALLOCATE_ON_DEMAND will be deprecated in a " \
- "future Starboard version.")
- return static_cast<bool>(COBALT_MEDIA_BUFFER_POOL_ALLOCATE_ON_DEMAND);
-#else // defined(COBALT_MEDIA_BUFFER_POOL_ALLOCATE_ON_DEMAND) &&
- // COBALT_MEDIA_BUFFER_POOL_ALLOCATE_ON_DEMAND !=
- // LEGACY_ALLOCATE_ON_DEMAND
return true;
-#endif // defined(COBALT_MEDIA_BUFFER_POOL_ALLOCATE_ON_DEMAND) &&
- // COBALT_MEDIA_BUFFER_POOL_ALLOCATE_ON_DEMAND !=
- // LEGACY_ALLOCATE_ON_DEMAND
}
-#endif // SB_API_VERSION >= 10
diff --git a/src/starboard/shared/starboard/media/media_is_buffer_using_memory_pool.cc b/src/starboard/shared/starboard/media/media_is_buffer_using_memory_pool.cc
index dc65a41..db84689 100644
--- a/src/starboard/shared/starboard/media/media_is_buffer_using_memory_pool.cc
+++ b/src/starboard/shared/starboard/media/media_is_buffer_using_memory_pool.cc
@@ -14,8 +14,6 @@
#include "starboard/media.h"
-#if SB_API_VERSION >= 10
bool SbMediaIsBufferUsingMemoryPool() {
return true;
}
-#endif // SB_API_VERSION >= 10
diff --git a/src/starboard/shared/starboard/media/media_support_internal.h b/src/starboard/shared/starboard/media/media_support_internal.h
index 5e14541..b106f0a 100644
--- a/src/starboard/shared/starboard/media/media_support_internal.h
+++ b/src/starboard/shared/starboard/media/media_support_internal.h
@@ -15,6 +15,7 @@
#ifndef STARBOARD_SHARED_STARBOARD_MEDIA_MEDIA_SUPPORT_INTERNAL_H_
#define STARBOARD_SHARED_STARBOARD_MEDIA_MEDIA_SUPPORT_INTERNAL_H_
+#include "starboard/configuration.h"
#include "starboard/media.h"
#include "starboard/shared/internal_only.h"
@@ -28,6 +29,9 @@
// function returns |false|.
//
// |video_codec|: The video codec used in the media content.
+// |content_type|: The full content type passed to the corresponding dom
+// interface if there is any. Otherwise it will be set to "".
+// It should never to set to NULL.
// |profile|: The profile in the context of |video_codec|. It should be set to
// -1 when it is unknown or not applicable.
// |level|: The level in the context of |video_codec|. It should be set to -1
@@ -54,6 +58,24 @@
// it indicates that the fps shouldn't be considered.
// |decode_to_texture_required|: Whether or not the resulting video frames can
// be decoded and used as textures by the GPU.
+#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+
+bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec,
+ const char* content_type,
+ int profile,
+ int level,
+ int bit_depth,
+ SbMediaPrimaryId primary_id,
+ SbMediaTransferId transfer_id,
+ SbMediaMatrixId matrix_id,
+ int frame_width,
+ int frame_height,
+ int64_t bitrate,
+ int fps,
+ bool decode_to_texture_required);
+
+#else // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+
bool SbMediaIsVideoSupported(SbMediaVideoCodec video_codec,
#if SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
int profile,
@@ -66,21 +88,32 @@
int frame_width,
int frame_height,
int64_t bitrate,
- int fps
-#if SB_API_VERSION >= 10
- ,
- bool decode_to_texture_required
-#endif // SB_API_VERSION >= 10
- );
+ int fps,
+ bool decode_to_texture_required);
+
+#endif // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
// Indicates whether this platform supports |audio_codec| at |bitrate|.
// If |audio_codec| is not supported under any condition, this function
// returns |false|.
//
// |audio_codec|: The media's audio codec (|SbMediaAudioCodec|).
+// |content_type|: The full content type passed to the corresponding dom
+// interface if there is any. Otherwise it will be set to "".
+// It should never to set to NULL.
// |bitrate|: The media's bitrate.
+#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+
+bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec,
+ const char* content_type,
+ int64_t bitrate);
+
+#else // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+
bool SbMediaIsAudioSupported(SbMediaAudioCodec audio_codec, int64_t bitrate);
+#endif // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+
#if !SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
// Indicates whether this platform supports |transfer_id| as a transfer
// characteristics. If |transfer_id| is not supported under any condition, this
diff --git a/src/starboard/shared/starboard/media/media_tests.gypi b/src/starboard/shared/starboard/media/media_tests.gypi
index 1d0583d..a07a89b 100644
--- a/src/starboard/shared/starboard/media/media_tests.gypi
+++ b/src/starboard/shared/starboard/media/media_tests.gypi
@@ -17,6 +17,7 @@
# This will be included by 'starboard_platform_tests.gyp' so full path names
# have to be used here.
'media_tests_sources': [
+ '<(DEPTH)/starboard/shared/starboard/media/avc_util_test.cc',
'<(DEPTH)/starboard/shared/starboard/media/codec_util_test.cc',
'<(DEPTH)/starboard/shared/starboard/media/mime_type_test.cc',
],
diff --git a/src/starboard/shared/starboard/media/media_util.cc b/src/starboard/shared/starboard/media/media_util.cc
index 0efe732..d309add 100644
--- a/src/starboard/shared/starboard/media/media_util.cc
+++ b/src/starboard/shared/starboard/media/media_util.cc
@@ -60,7 +60,11 @@
int bitrate = mime_type.GetParamIntValue("bitrate", kDefaultBitRate);
- if (!SbMediaIsAudioSupported(audio_codec, bitrate)) {
+ if (!SbMediaIsAudioSupported(audio_codec,
+#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+ mime_type.raw_content_type().c_str(),
+#endif // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+ bitrate)) {
return false;
}
@@ -100,10 +104,6 @@
const std::string& codec,
const char* key_system,
bool decode_to_texture_required) {
-#if SB_API_VERSION < 10
- SB_UNREFERENCED_PARAMETER(decode_to_texture_required);
-#endif // SB_API_VERSION < 10
-
SbMediaVideoCodec video_codec;
int profile = -1;
int level = -1;
@@ -161,23 +161,18 @@
int bitrate = mime_type.GetParamIntValue("bitrate", kDefaultBitRate);
#if SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
- if (!SbMediaIsVideoSupported(video_codec, profile, level, bit_depth,
- primary_id, transfer_id, matrix_id, width,
- height, bitrate, fps
-#if SB_API_VERSION >= 10
- ,
- decode_to_texture_required
-#endif // SB_API_VERSION >= 10
- )) {
+ if (!SbMediaIsVideoSupported(video_codec,
+#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+ mime_type.raw_content_type().c_str(),
+#endif // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+ profile, level, bit_depth, primary_id,
+ transfer_id, matrix_id, width, height, bitrate,
+ fps, decode_to_texture_required)) {
return false;
}
#else // SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
- if (!SbMediaIsVideoSupported(video_codec, width, height, bitrate, fps
-#if SB_API_VERSION >= 10
- ,
- decode_to_texture_required
-#endif // SB_API_VERSION >= 10
- )) {
+ if (!SbMediaIsVideoSupported(video_codec, width, height, bitrate, fps,
+ decode_to_texture_required)) {
return false;
}
#endif // SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
@@ -367,7 +362,6 @@
}
bool decode_to_texture_required = false;
-#if SB_API_VERSION >= 10
std::string decode_to_texture_value =
mime_type.GetParamStringValue("decode-to-texture", "false");
if (decode_to_texture_value == "true") {
@@ -377,7 +371,6 @@
// decode-to-texture, trivially reject.
return kSbMediaSupportTypeNotSupported;
}
-#endif // SB_API_VERSION >= 10
if (codecs.size() == 0) {
// This is a progressive query. We only support "video/mp4" in this case.
diff --git a/src/starboard/shared/starboard/media/mime_type.cc b/src/starboard/shared/starboard/media/mime_type.cc
index d1ce94e..f84439a 100644
--- a/src/starboard/shared/starboard/media/mime_type.cc
+++ b/src/starboard/shared/starboard/media/mime_type.cc
@@ -85,7 +85,8 @@
const int MimeType::kInvalidParamIndex = -1;
-MimeType::MimeType(const std::string& content_type) : is_valid_(false) {
+MimeType::MimeType(const std::string& content_type)
+ : raw_content_type_(content_type), is_valid_(false) {
Strings components = SplitAndTrim(content_type, ';');
if (components.empty()) {
diff --git a/src/starboard/shared/starboard/media/mime_type.h b/src/starboard/shared/starboard/media/mime_type.h
index 9f69b0f..7c3d619 100644
--- a/src/starboard/shared/starboard/media/mime_type.h
+++ b/src/starboard/shared/starboard/media/mime_type.h
@@ -56,6 +56,7 @@
explicit MimeType(const std::string& content_type);
+ const std::string& raw_content_type() const { return raw_content_type_; }
bool is_valid() const { return is_valid_; }
const std::string& type() const { return type_; }
@@ -90,6 +91,7 @@
int GetParamIndexByName(const char* name) const;
+ const std::string raw_content_type_;
bool is_valid_;
std::string type_;
std::string subtype_;
diff --git a/src/starboard/shared/starboard/media/mime_type_test.cc b/src/starboard/shared/starboard/media/mime_type_test.cc
index d051e39..7b29757 100644
--- a/src/starboard/shared/starboard/media/mime_type_test.cc
+++ b/src/starboard/shared/starboard/media/mime_type_test.cc
@@ -22,6 +22,19 @@
namespace media {
namespace {
+TEST(MimeTypeTest, RawContentType) {
+ {
+ const char kContentTypeWithSpace[] = " video/mp4; name0=123; name1=123.4 ";
+ MimeType mime_type(kContentTypeWithSpace);
+ EXPECT_EQ(mime_type.raw_content_type(), kContentTypeWithSpace);
+ }
+ {
+ const char kInvalidContentType[] = "video /mp4";
+ MimeType mime_type(kInvalidContentType);
+ EXPECT_EQ(mime_type.raw_content_type(), kInvalidContentType);
+ }
+}
+
TEST(MimeTypeTest, EmptyString) {
MimeType mime_type("");
EXPECT_FALSE(mime_type.is_valid());
diff --git a/src/starboard/shared/starboard/player/decoded_audio_internal.cc b/src/starboard/shared/starboard/player/decoded_audio_internal.cc
index 1e5ac07..1e21a40 100644
--- a/src/starboard/shared/starboard/player/decoded_audio_internal.cc
+++ b/src/starboard/shared/starboard/player/decoded_audio_internal.cc
@@ -27,6 +27,8 @@
namespace {
+using ::starboard::shared::starboard::media::GetBytesPerSample;
+
void ConvertSample(const int16_t* source, float* destination) {
*destination = static_cast<float>(*source) / 32768.f;
}
@@ -59,13 +61,7 @@
size_(size) {}
int DecodedAudio::frames() const {
- int bytes_per_sample;
- if (sample_type_ == kSbMediaAudioSampleTypeInt16Deprecated) {
- bytes_per_sample = 2;
- } else {
- SB_DCHECK(sample_type_ == kSbMediaAudioSampleTypeFloat32);
- bytes_per_sample = 4;
- }
+ int bytes_per_sample = GetBytesPerSample(sample_type_);
SB_DCHECK(size_ % (bytes_per_sample * channels_) == 0);
return static_cast<int>(size_ / bytes_per_sample / channels_);
}
@@ -75,6 +71,44 @@
size_ = new_size;
}
+void DecodedAudio::AdjustForSeekTime(int samples_per_second,
+ SbTime seeking_to_time) {
+ SB_DCHECK(!is_end_of_stream());
+ SB_DCHECK(samples_per_second != 0);
+
+ int frames_to_remove =
+ (seeking_to_time - timestamp()) * samples_per_second / kSbTimeSecond;
+
+ if (samples_per_second == 0 || frames_to_remove < 0 ||
+ frames_to_remove >= frames()) {
+ SB_LOG(WARNING) << "AdjustForSeekTime failed for seeking_to_time at "
+ << seeking_to_time << " for samples_per_second "
+ << samples_per_second << ", and there are " << frames()
+ << " frames in the DecodedAudio object.";
+ return;
+ }
+
+ auto bytes_per_sample = GetBytesPerSample(sample_type_);
+ auto bytes_per_frame = bytes_per_sample * channels();
+
+ if (storage_type_ == kSbMediaAudioFrameStorageTypeInterleaved) {
+ SbMemoryMove(buffer(), buffer() + bytes_per_frame * frames_to_remove,
+ (frames() - frames_to_remove) * bytes_per_frame);
+ } else {
+ SB_DCHECK(storage_type_ == kSbMediaAudioFrameStorageTypePlanar);
+ const uint8_t* source_addr = buffer();
+ uint8_t* dest_addr = buffer();
+ for (int channel = 0; channel < channels(); ++channel) {
+ SbMemoryMove(dest_addr, source_addr + bytes_per_sample * frames_to_remove,
+ (frames() - frames_to_remove) * bytes_per_sample);
+ source_addr += frames() * bytes_per_sample;
+ dest_addr += (frames() - frames_to_remove) * bytes_per_sample;
+ }
+ }
+ size_ = (frames() - frames_to_remove) * bytes_per_frame;
+ timestamp_ += frames_to_remove * kSbTimeSecond / samples_per_second;
+}
+
void DecodedAudio::SwitchFormatTo(
SbMediaAudioSampleType new_sample_type,
SbMediaAudioFrameStorageType new_storage_type) {
diff --git a/src/starboard/shared/starboard/player/decoded_audio_internal.h b/src/starboard/shared/starboard/player/decoded_audio_internal.h
index 4afbc88..0ac7681 100644
--- a/src/starboard/shared/starboard/player/decoded_audio_internal.h
+++ b/src/starboard/shared/starboard/player/decoded_audio_internal.h
@@ -54,6 +54,10 @@
void SwitchFormatTo(SbMediaAudioSampleType new_sample_type,
SbMediaAudioFrameStorageType new_storage_type);
void ShrinkTo(size_t new_size);
+ // During seeking, the target time can be in the middle of the DecodedAudio
+ // object. This function will adjust the object to the seek target time by
+ // removing the frames in the beginning that are before the seek target time.
+ void AdjustForSeekTime(int samples_per_second, SbTime seeking_to_time);
private:
void SwitchSampleTypeTo(SbMediaAudioSampleType new_sample_type);
diff --git a/src/starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.cc b/src/starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.cc
index 76973fd..ae3b448 100644
--- a/src/starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.cc
+++ b/src/starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.cc
@@ -188,11 +188,7 @@
audio_decoder_creator_(input_audio_sample_info_, drm_system_);
if (!audio_decoder_) {
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
error_cb_(kSbPlayerErrorDecode, "Decoder adapter cannot create decoder.");
-#else // SB_HAS(PLAYER_ERROR_MESSAGE)
- error_cb_();
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
return;
}
audio_decoder_->Initialize(
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_internal.h b/src/starboard/shared/starboard/player/filter/audio_renderer_internal.h
index 74365bf..4a518cc 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_internal.h
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_internal.h
@@ -1,4 +1,4 @@
-// Copyright 2016 The Cobalt Authors. All Rights Reserved.
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -15,31 +15,8 @@
#ifndef STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_AUDIO_RENDERER_INTERNAL_H_
#define STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_AUDIO_RENDERER_INTERNAL_H_
-#include <functional>
-#include <vector>
-
-#include "starboard/atomic.h"
-#include "starboard/common/log.h"
-#include "starboard/common/mutex.h"
-#include "starboard/common/optional.h"
-#include "starboard/common/scoped_ptr.h"
-#include "starboard/media.h"
-#include "starboard/shared/internal_only.h"
-#include "starboard/shared/starboard/player/decoded_audio_internal.h"
-#include "starboard/shared/starboard/player/filter/audio_decoder_internal.h"
-#include "starboard/shared/starboard/player/filter/audio_frame_tracker.h"
-#include "starboard/shared/starboard/player/filter/audio_renderer_sink.h"
-#include "starboard/shared/starboard/player/filter/audio_resampler.h"
-#include "starboard/shared/starboard/player/filter/audio_time_stretcher.h"
-#include "starboard/shared/starboard/player/filter/media_time_provider.h"
+#include "starboard/shared/starboard/player/filter/common.h"
#include "starboard/shared/starboard/player/input_buffer_internal.h"
-#include "starboard/shared/starboard/player/job_queue.h"
-#include "starboard/time.h"
-#include "starboard/types.h"
-
-// Uncomment the following statement to log the media time stats with deviation
-// when GetCurrentMediaTime() is called.
-// #define SB_LOG_MEDIA_TIME_STATS 1
namespace starboard {
namespace shared {
@@ -47,169 +24,22 @@
namespace player {
namespace filter {
-const int kFramesInBufferBeginUnderflow = 1024;
-
-// A class that sits in between the audio decoder, the audio sink and the
-// pipeline to coordinate data transfer between these parties. It also serves
-// as the authority of playback time.
-class AudioRenderer : public MediaTimeProvider,
- private AudioRendererSink::RenderCallback,
- private JobQueue::JobOwner {
+class AudioRenderer {
public:
- // |max_cached_frames| is a soft limit for the max audio frames this class can
- // cache so it can:
- // 1. Avoid using too much memory.
- // 2. Have the audio cache full to simulate the state that the renderer can no
- // longer accept more data.
- // |min_frames_per_append| is the min number of frames that the audio renderer
- // tries to append to the sink buffer at once.
- AudioRenderer(scoped_ptr<AudioDecoder> decoder,
- scoped_ptr<AudioRendererSink> audio_renderer_sink,
- const SbMediaAudioSampleInfo& audio_sample_info,
- int max_cached_frames,
- int min_frames_per_append);
- ~AudioRenderer();
+ virtual ~AudioRenderer() {}
- void Initialize(const ErrorCB& error_cb,
- const PrerolledCB& prerolled_cb,
- const EndedCB& ended_cb);
- void WriteSample(const scoped_refptr<InputBuffer>& input_buffer);
- void WriteEndOfStream();
+ virtual void Initialize(const ErrorCB& error_cb,
+ const PrerolledCB& prerolled_cb,
+ const EndedCB& ended_cb) = 0;
+ virtual void WriteSample(const scoped_refptr<InputBuffer>& input_buffer) = 0;
+ virtual void WriteEndOfStream() = 0;
- void SetVolume(double volume);
+ virtual void SetVolume(double volume) = 0;
// TODO: Remove the eos state querying functions and their tests.
- bool IsEndOfStreamWritten() const;
- bool IsEndOfStreamPlayed() const;
- bool CanAcceptMoreData() const;
-
- // MediaTimeProvider methods
- void Play() override;
- void Pause() override;
- void SetPlaybackRate(double playback_rate) override;
- void Seek(SbTime seek_to_time) override;
- SbTime GetCurrentMediaTime(bool* is_playing,
- bool* is_eos_played,
- bool* is_underflow) override;
-
- private:
- enum EOSState {
- kEOSNotReceived,
- kEOSWrittenToDecoder,
- kEOSDecoded,
- kEOSSentToSink
- };
-
- const int max_cached_frames_;
- const int min_frames_per_append_;
- // |buffered_frames_to_start_| would be initialized in OnFirstOutput().
- // Before it's initialized, set it to a large number.
- int buffered_frames_to_start_ = 48 * 1024;
-
- ErrorCB error_cb_;
- PrerolledCB prerolled_cb_;
- EndedCB ended_cb_;
-
- Mutex mutex_;
-
- bool paused_ = true;
- bool consume_frames_called_ = false;
- bool seeking_ = false;
- SbTime seeking_to_time_ = 0;
- SbTime last_media_time_ = 0;
- AudioFrameTracker audio_frame_tracker_;
- bool ended_cb_called_ = false;
-
- int64_t total_frames_sent_to_sink_ = 0;
- int64_t total_frames_consumed_by_sink_ = 0;
- int32_t frames_consumed_by_sink_since_last_get_current_time_;
-
- scoped_ptr<AudioDecoder> decoder_;
-
- int64_t frames_consumed_set_at_;
- double playback_rate_ = 1.0;
-
- // AudioRendererSink methods
- void GetSourceStatus(int* frames_in_buffer,
- int* offset_in_frames,
- bool* is_playing,
- bool* is_eos_reached) override;
-#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || \
- SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
- void ConsumeFrames(int frames_consumed, SbTime frames_consumed_at) override;
-#else // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
- // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
- void ConsumeFrames(int frames_consumed) override;
-#endif // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
- // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
- void OnError(bool capability_changed) override;
-
- void UpdateVariablesOnSinkThread_Locked(SbTime system_time_on_consume_frames);
-
- void OnFirstOutput(const SbMediaAudioSampleType decoded_sample_type,
- const SbMediaAudioFrameStorageType decoded_storage_type,
- const int decoded_sample_rate);
- bool IsEndOfStreamPlayed_Locked() const;
-
- void OnDecoderConsumed();
- void OnDecoderOutput();
- void ProcessAudioData();
- void FillResamplerAndTimeStretcher();
- bool AppendAudioToFrameBuffer(bool* is_frame_buffer_full);
-
- EOSState eos_state_ = kEOSNotReceived;
- const int channels_;
- const SbMediaAudioSampleType sink_sample_type_;
- const int bytes_per_frame_;
-
- scoped_ptr<AudioResampler> resampler_;
- optional<int> decoder_sample_rate_;
- AudioTimeStretcher time_stretcher_;
-
- std::vector<uint8_t> frame_buffer_;
- uint8_t* frame_buffers_[1];
-
- int32_t pending_decoder_outputs_ = 0;
-
- bool can_accept_more_data_ = true;
- JobQueue::JobToken process_audio_data_job_token_;
- std::function<void()> process_audio_data_job_;
-
- // Our owner will attempt to seek to time 0 when playback begins. In
- // general, seeking could require a full reset of the underlying decoder on
- // some platforms, so we make an effort to improve playback startup
- // performance by keeping track of whether we already have a fresh decoder,
- // and can thus avoid doing a full reset.
- bool first_input_written_ = false;
-
- scoped_ptr<AudioRendererSink> audio_renderer_sink_;
- bool is_eos_reached_on_sink_thread_ = false;
- bool is_playing_on_sink_thread_ = false;
- int64_t frames_in_buffer_on_sink_thread_ = 0;
- int64_t offset_in_frames_on_sink_thread_ = 0;
- int64_t frames_consumed_on_sink_thread_ = 0;
- SbTime frames_consumed_set_at_on_sink_thread_ = 0;
- int64_t silence_frames_written_after_eos_on_sink_thread_ = 0;
- int64_t silence_frames_consumed_on_sink_thread_ = 0;
-
-#if SB_LOG_MEDIA_TIME_STATS
- SbTime system_and_media_time_offset_ = -1;
- SbTime min_drift_ = kSbTimeMax;
- SbTime max_drift_ = 0;
- int64_t total_frames_consumed_ = 0;
-#endif // SB_LOG_MEDIA_TIME_STATS
-
- // Set to true when there are fewer than |kFramesInBufferBeginUnderflow|
- // frames in buffer. Set to false when the queue is full or EOS.
- bool underflow_ = false;
-
-#if SB_PLAYER_FILTER_ENABLE_STATE_CHECK
- static const int32_t kMaxSinkCallbacksBetweenCheck = 1024;
- static const SbTime kCheckAudioSinkStatusInterval = kSbTimeSecond;
- void CheckAudioSinkStatus();
-
- atomic_int32_t sink_callbacks_since_last_check_;
-#endif // SB_PLAYER_FILTER_ENABLE_STATE_CHECK
+ virtual bool IsEndOfStreamWritten() const = 0;
+ virtual bool IsEndOfStreamPlayed() const = 0;
+ virtual bool CanAcceptMoreData() const = 0;
};
} // namespace filter
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_internal.cc b/src/starboard/shared/starboard/player/filter/audio_renderer_internal_impl.cc
similarity index 88%
rename from src/starboard/shared/starboard/player/filter/audio_renderer_internal.cc
rename to src/starboard/shared/starboard/player/filter/audio_renderer_internal_impl.cc
index dc013f1..08f306e 100644
--- a/src/starboard/shared/starboard/player/filter/audio_renderer_internal.cc
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_internal_impl.cc
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "starboard/shared/starboard/player/filter/audio_renderer_internal.h"
+#include "starboard/shared/starboard/player/filter/audio_renderer_internal_impl.h"
#include <algorithm>
@@ -28,7 +28,7 @@
namespace {
// This class works only when the input format and output format are the same.
-// It allows for a simplified AudioRenderer implementation by always using a
+// It allows for a simplified AudioRendererImpl implementation by always using a
// resampler.
class IdentityAudioResampler : public AudioResampler {
public:
@@ -49,8 +49,8 @@
bool eos_reached_;
};
-// AudioRenderer uses AudioTimeStretcher internally to adjust to playback rate.
-// So we try to use kSbMediaAudioSampleTypeFloat32 and only use
+// AudioRendererImpl uses AudioTimeStretcher internally to adjust to playback
+// rate. So we try to use kSbMediaAudioSampleTypeFloat32 and only use
// kSbMediaAudioSampleTypeInt16Deprecated when float32 is not supported. To use
// kSbMediaAudioSampleTypeFloat32 will cause an extra conversion from float32 to
// int16 before the samples are sent to the audio sink.
@@ -64,11 +64,12 @@
} // namespace
-AudioRenderer::AudioRenderer(scoped_ptr<AudioDecoder> decoder,
- scoped_ptr<AudioRendererSink> audio_renderer_sink,
- const SbMediaAudioSampleInfo& audio_sample_info,
- int max_cached_frames,
- int min_frames_per_append)
+AudioRendererImpl::AudioRendererImpl(
+ scoped_ptr<AudioDecoder> decoder,
+ scoped_ptr<AudioRendererSink> audio_renderer_sink,
+ const SbMediaAudioSampleInfo& audio_sample_info,
+ int max_cached_frames,
+ int min_frames_per_append)
: max_cached_frames_(max_cached_frames),
min_frames_per_append_(min_frames_per_append),
channels_(audio_sample_info.number_of_channels),
@@ -78,10 +79,10 @@
frames_consumed_set_at_(SbTimeGetMonotonicNow()),
decoder_(decoder.Pass()),
process_audio_data_job_(
- std::bind(&AudioRenderer::ProcessAudioData, this)),
+ std::bind(&AudioRendererImpl::ProcessAudioData, this)),
audio_renderer_sink_(audio_renderer_sink.Pass()) {
- SB_DLOG(INFO) << "Creating AudioRenderer with " << channels_ << " channels, "
- << bytes_per_frame_ << " bytes per frame, "
+ SB_DLOG(INFO) << "Creating AudioRendererImpl with " << channels_
+ << " channels, " << bytes_per_frame_ << " bytes per frame, "
<< max_cached_frames_ << " max cached frames, and "
<< min_frames_per_append_ << " min frames per append.";
SB_DCHECK(decoder_ != NULL);
@@ -91,22 +92,22 @@
frame_buffers_[0] = &frame_buffer_[0];
#if SB_PLAYER_FILTER_ENABLE_STATE_CHECK
- Schedule(std::bind(&AudioRenderer::CheckAudioSinkStatus, this),
+ Schedule(std::bind(&AudioRendererImpl::CheckAudioSinkStatus, this),
kCheckAudioSinkStatusInterval);
#endif // SB_PLAYER_FILTER_ENABLE_STATE_CHECK
}
-AudioRenderer::~AudioRenderer() {
- SB_DLOG(INFO) << "Destroying AudioRenderer with " << channels_
+AudioRendererImpl::~AudioRendererImpl() {
+ SB_DLOG(INFO) << "Destroying AudioRendererImpl with " << channels_
<< " channels, " << bytes_per_frame_ << " bytes per frame, "
<< max_cached_frames_ << " max cached frames, and "
<< min_frames_per_append_ << " min frames per append.";
SB_DCHECK(BelongsToCurrentThread());
}
-void AudioRenderer::Initialize(const ErrorCB& error_cb,
- const PrerolledCB& prerolled_cb,
- const EndedCB& ended_cb) {
+void AudioRendererImpl::Initialize(const ErrorCB& error_cb,
+ const PrerolledCB& prerolled_cb,
+ const EndedCB& ended_cb) {
SB_DCHECK(error_cb);
SB_DCHECK(prerolled_cb);
SB_DCHECK(ended_cb);
@@ -118,11 +119,11 @@
prerolled_cb_ = prerolled_cb;
ended_cb_ = ended_cb;
- decoder_->Initialize(std::bind(&AudioRenderer::OnDecoderOutput, this),
+ decoder_->Initialize(std::bind(&AudioRendererImpl::OnDecoderOutput, this),
error_cb);
}
-void AudioRenderer::WriteSample(
+void AudioRendererImpl::WriteSample(
const scoped_refptr<InputBuffer>& input_buffer) {
SB_DCHECK(BelongsToCurrentThread());
SB_DCHECK(input_buffer);
@@ -137,11 +138,11 @@
can_accept_more_data_ = false;
decoder_->Decode(input_buffer,
- std::bind(&AudioRenderer::OnDecoderConsumed, this));
+ std::bind(&AudioRendererImpl::OnDecoderConsumed, this));
first_input_written_ = true;
}
-void AudioRenderer::WriteEndOfStream() {
+void AudioRendererImpl::WriteEndOfStream() {
SB_DCHECK(BelongsToCurrentThread());
// TODO: Check |can_accept_more_data_| and make WriteEndOfStream() depend on
// CanAcceptMoreData() or callback.
@@ -160,28 +161,28 @@
first_input_written_ = true;
}
-void AudioRenderer::SetVolume(double volume) {
+void AudioRendererImpl::SetVolume(double volume) {
SB_DCHECK(BelongsToCurrentThread());
audio_renderer_sink_->SetVolume(volume);
}
-bool AudioRenderer::IsEndOfStreamWritten() const {
+bool AudioRendererImpl::IsEndOfStreamWritten() const {
SB_DCHECK(BelongsToCurrentThread());
return eos_state_ >= kEOSWrittenToDecoder;
}
-bool AudioRenderer::IsEndOfStreamPlayed() const {
+bool AudioRendererImpl::IsEndOfStreamPlayed() const {
ScopedLock lock(mutex_);
return IsEndOfStreamPlayed_Locked();
}
-bool AudioRenderer::CanAcceptMoreData() const {
+bool AudioRendererImpl::CanAcceptMoreData() const {
SB_DCHECK(BelongsToCurrentThread());
return eos_state_ == kEOSNotReceived && can_accept_more_data_ &&
(!decoder_sample_rate_ || !time_stretcher_.IsQueueFull());
}
-void AudioRenderer::Play() {
+void AudioRendererImpl::Play() {
SB_DCHECK(BelongsToCurrentThread());
ScopedLock lock(mutex_);
@@ -189,14 +190,14 @@
consume_frames_called_ = false;
}
-void AudioRenderer::Pause() {
+void AudioRendererImpl::Pause() {
SB_DCHECK(BelongsToCurrentThread());
ScopedLock lock(mutex_);
paused_ = true;
}
-void AudioRenderer::SetPlaybackRate(double playback_rate) {
+void AudioRendererImpl::SetPlaybackRate(double playback_rate) {
SB_DCHECK(BelongsToCurrentThread());
ScopedLock lock(mutex_);
@@ -221,7 +222,7 @@
}
}
-void AudioRenderer::Seek(SbTime seek_to_time) {
+void AudioRendererImpl::Seek(SbTime seek_to_time) {
SB_DCHECK(BelongsToCurrentThread());
SB_DCHECK(seek_to_time >= 0);
@@ -271,14 +272,14 @@
CancelPendingJobs();
#if SB_PLAYER_FILTER_ENABLE_STATE_CHECK
- Schedule(std::bind(&AudioRenderer::CheckAudioSinkStatus, this),
+ Schedule(std::bind(&AudioRendererImpl::CheckAudioSinkStatus, this),
kCheckAudioSinkStatusInterval);
#endif // SB_PLAYER_FILTER_ENABLE_STATE_CHECK
}
-SbTime AudioRenderer::GetCurrentMediaTime(bool* is_playing,
- bool* is_eos_played,
- bool* is_underflow) {
+SbTime AudioRendererImpl::GetCurrentMediaTime(bool* is_playing,
+ bool* is_eos_played,
+ bool* is_underflow) {
SB_DCHECK(is_playing);
SB_DCHECK(is_eos_played);
SB_DCHECK(is_underflow);
@@ -360,10 +361,10 @@
return media_time;
}
-void AudioRenderer::GetSourceStatus(int* frames_in_buffer,
- int* offset_in_frames,
- bool* is_playing,
- bool* is_eos_reached) {
+void AudioRendererImpl::GetSourceStatus(int* frames_in_buffer,
+ int* offset_in_frames,
+ bool* is_playing,
+ bool* is_eos_reached) {
#if SB_PLAYER_FILTER_ENABLE_STATE_CHECK
sink_callbacks_since_last_check_.increment();
#endif // SB_PLAYER_FILTER_ENABLE_STATE_CHECK
@@ -404,14 +405,14 @@
}
}
-void AudioRenderer::ConsumeFrames(int frames_consumed
+void AudioRendererImpl::ConsumeFrames(int frames_consumed
#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || \
SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
- ,
- SbTime frames_consumed_at
+ ,
+ SbTime frames_consumed_at
#endif // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
// SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
- ) {
+) {
#if SB_PLAYER_FILTER_ENABLE_STATE_CHECK
sink_callbacks_since_last_check_.increment();
#endif // SB_PLAYER_FILTER_ENABLE_STATE_CHECK
@@ -447,7 +448,7 @@
}
}
-void AudioRenderer::OnError(bool capability_changed) {
+void AudioRendererImpl::OnError(bool capability_changed) {
SB_DCHECK(error_cb_);
if (capability_changed) {
error_cb_(kSbPlayerErrorCapabilityChanged, "failed to start audio sink");
@@ -459,7 +460,7 @@
}
}
-void AudioRenderer::UpdateVariablesOnSinkThread_Locked(
+void AudioRendererImpl::UpdateVariablesOnSinkThread_Locked(
SbTime system_time_on_consume_frames) {
mutex_.DCheckAcquired();
@@ -505,7 +506,7 @@
}
}
-void AudioRenderer::OnFirstOutput(
+void AudioRendererImpl::OnFirstOutput(
const SbMediaAudioSampleType decoded_sample_type,
const SbMediaAudioFrameStorageType decoded_storage_type,
const int decoded_sample_rate) {
@@ -540,22 +541,18 @@
reinterpret_cast<SbAudioSinkFrameBuffers>(frame_buffers_),
max_cached_frames_, this);
if (!audio_renderer_sink_->HasStarted()) {
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
SB_LOG(ERROR) << "Failed to start audio sink.";
error_cb_(kSbPlayerErrorDecode, "failed to start audio sink");
-#else // SB_HAS(PLAYER_ERROR_MESSAGE)
- error_cb_();
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
}
}
-bool AudioRenderer::IsEndOfStreamPlayed_Locked() const {
+bool AudioRendererImpl::IsEndOfStreamPlayed_Locked() const {
mutex_.DCheckAcquired();
return eos_state_ >= kEOSSentToSink &&
total_frames_sent_to_sink_ == total_frames_consumed_by_sink_;
}
-void AudioRenderer::OnDecoderConsumed() {
+void AudioRendererImpl::OnDecoderConsumed() {
SB_DCHECK(BelongsToCurrentThread());
// TODO: Unify EOS and non EOS request once WriteEndOfStream() depends on
@@ -567,7 +564,7 @@
}
}
-void AudioRenderer::OnDecoderOutput() {
+void AudioRendererImpl::OnDecoderOutput() {
SB_DCHECK(BelongsToCurrentThread());
++pending_decoder_outputs_;
@@ -580,7 +577,7 @@
ProcessAudioData();
}
-void AudioRenderer::ProcessAudioData() {
+void AudioRendererImpl::ProcessAudioData() {
SB_DCHECK(BelongsToCurrentThread());
process_audio_data_job_token_.ResetToInvalid();
@@ -609,6 +606,10 @@
decoder_->Read(&decoded_audio_sample_rate);
SB_DCHECK(decoded_audio);
if (!audio_renderer_sink_->HasStarted()) {
+ if (!decoded_audio->is_end_of_stream()) {
+ decoded_audio->AdjustForSeekTime(decoded_audio_sample_rate,
+ seeking_to_time_);
+ }
OnFirstOutput(decoded_audio->sample_type(), decoded_audio->storage_type(),
decoded_audio_sample_rate);
}
@@ -674,7 +675,7 @@
}
}
-bool AudioRenderer::AppendAudioToFrameBuffer(bool* is_frame_buffer_full) {
+bool AudioRendererImpl::AppendAudioToFrameBuffer(bool* is_frame_buffer_full) {
SB_DCHECK(BelongsToCurrentThread());
SB_DCHECK(is_frame_buffer_full);
@@ -742,7 +743,7 @@
}
#if SB_PLAYER_FILTER_ENABLE_STATE_CHECK
-void AudioRenderer::CheckAudioSinkStatus() {
+void AudioRendererImpl::CheckAudioSinkStatus() {
SB_DCHECK(BelongsToCurrentThread());
// Check if sink callbacks are called too frequently.
@@ -771,7 +772,7 @@
<< sink_callbacks_since_last_check
<< " callbacks since last check.";
}
- Schedule(std::bind(&AudioRenderer::CheckAudioSinkStatus, this),
+ Schedule(std::bind(&AudioRendererImpl::CheckAudioSinkStatus, this),
kCheckAudioSinkStatusInterval);
}
#endif // SB_PLAYER_FILTER_ENABLE_STATE_CHECK
diff --git a/src/starboard/shared/starboard/player/filter/audio_renderer_internal_impl.h b/src/starboard/shared/starboard/player/filter/audio_renderer_internal_impl.h
new file mode 100644
index 0000000..e984ec2
--- /dev/null
+++ b/src/starboard/shared/starboard/player/filter/audio_renderer_internal_impl.h
@@ -0,0 +1,223 @@
+// Copyright 2016 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_AUDIO_RENDERER_INTERNAL_IMPL_H_
+#define STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_AUDIO_RENDERER_INTERNAL_IMPL_H_
+
+#include <functional>
+#include <vector>
+
+#include "starboard/atomic.h"
+#include "starboard/common/log.h"
+#include "starboard/common/mutex.h"
+#include "starboard/common/optional.h"
+#include "starboard/common/scoped_ptr.h"
+#include "starboard/media.h"
+#include "starboard/shared/internal_only.h"
+#include "starboard/shared/starboard/player/decoded_audio_internal.h"
+#include "starboard/shared/starboard/player/filter/audio_decoder_internal.h"
+#include "starboard/shared/starboard/player/filter/audio_frame_tracker.h"
+#include "starboard/shared/starboard/player/filter/audio_renderer_internal.h"
+#include "starboard/shared/starboard/player/filter/audio_renderer_sink.h"
+#include "starboard/shared/starboard/player/filter/audio_resampler.h"
+#include "starboard/shared/starboard/player/filter/audio_time_stretcher.h"
+#include "starboard/shared/starboard/player/filter/media_time_provider.h"
+#include "starboard/shared/starboard/player/input_buffer_internal.h"
+#include "starboard/shared/starboard/player/job_queue.h"
+#include "starboard/time.h"
+#include "starboard/types.h"
+
+// Uncomment the following statement to log the media time stats with deviation
+// when GetCurrentMediaTime() is called.
+// #define SB_LOG_MEDIA_TIME_STATS 1
+
+namespace starboard {
+namespace shared {
+namespace starboard {
+namespace player {
+namespace filter {
+
+const int kFramesInBufferBeginUnderflow = 1024;
+
+// A class that sits in between the audio decoder, the audio sink and the
+// pipeline to coordinate data transfer between these parties. It also serves
+// as the authority of playback time.
+class AudioRendererImpl : public AudioRenderer,
+ public MediaTimeProvider,
+ private AudioRendererSink::RenderCallback,
+ private JobQueue::JobOwner {
+ public:
+ // |max_cached_frames| is a soft limit for the max audio frames this class can
+ // cache so it can:
+ // 1. Avoid using too much memory.
+ // 2. Have the audio cache full to simulate the state that the renderer can no
+ // longer accept more data.
+ // |min_frames_per_append| is the min number of frames that the audio renderer
+ // tries to append to the sink buffer at once.
+ AudioRendererImpl(scoped_ptr<AudioDecoder> decoder,
+ scoped_ptr<AudioRendererSink> audio_renderer_sink,
+ const SbMediaAudioSampleInfo& audio_sample_info,
+ int max_cached_frames,
+ int min_frames_per_append);
+ ~AudioRendererImpl() override;
+
+ void Initialize(const ErrorCB& error_cb,
+ const PrerolledCB& prerolled_cb,
+ const EndedCB& ended_cb) override;
+ void WriteSample(const scoped_refptr<InputBuffer>& input_buffer) override;
+ void WriteEndOfStream() override;
+
+ void SetVolume(double volume) override;
+
+ // TODO: Remove the eos state querying functions and their tests.
+ bool IsEndOfStreamWritten() const override;
+ bool IsEndOfStreamPlayed() const override;
+ bool CanAcceptMoreData() const override;
+
+ // MediaTimeProvider methods
+ void Play() override;
+ void Pause() override;
+ void SetPlaybackRate(double playback_rate) override;
+ void Seek(SbTime seek_to_time) override;
+ SbTime GetCurrentMediaTime(bool* is_playing,
+ bool* is_eos_played,
+ bool* is_underflow) override;
+
+ private:
+ enum EOSState {
+ kEOSNotReceived,
+ kEOSWrittenToDecoder,
+ kEOSDecoded,
+ kEOSSentToSink
+ };
+
+ const int max_cached_frames_;
+ const int min_frames_per_append_;
+ // |buffered_frames_to_start_| would be initialized in OnFirstOutput().
+ // Before it's initialized, set it to a large number.
+ int buffered_frames_to_start_ = 48 * 1024;
+
+ ErrorCB error_cb_;
+ PrerolledCB prerolled_cb_;
+ EndedCB ended_cb_;
+
+ Mutex mutex_;
+
+ bool paused_ = true;
+ bool consume_frames_called_ = false;
+ bool seeking_ = false;
+ SbTime seeking_to_time_ = 0;
+ SbTime last_media_time_ = 0;
+ AudioFrameTracker audio_frame_tracker_;
+ bool ended_cb_called_ = false;
+
+ int64_t total_frames_sent_to_sink_ = 0;
+ int64_t total_frames_consumed_by_sink_ = 0;
+ int32_t frames_consumed_by_sink_since_last_get_current_time_;
+
+ scoped_ptr<AudioDecoder> decoder_;
+
+ int64_t frames_consumed_set_at_;
+ double playback_rate_ = 1.0;
+
+ // AudioRendererSink methods
+ void GetSourceStatus(int* frames_in_buffer,
+ int* offset_in_frames,
+ bool* is_playing,
+ bool* is_eos_reached) override;
+#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION || \
+ SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
+ void ConsumeFrames(int frames_consumed, SbTime frames_consumed_at) override;
+#else // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
+ // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
+ void ConsumeFrames(int frames_consumed) override;
+#endif // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION ||
+ // SB_HAS(ASYNC_AUDIO_FRAMES_REPORTING)
+ void OnError(bool capability_changed) override;
+
+ void UpdateVariablesOnSinkThread_Locked(SbTime system_time_on_consume_frames);
+
+ void OnFirstOutput(const SbMediaAudioSampleType decoded_sample_type,
+ const SbMediaAudioFrameStorageType decoded_storage_type,
+ const int decoded_sample_rate);
+ bool IsEndOfStreamPlayed_Locked() const;
+
+ void OnDecoderConsumed();
+ void OnDecoderOutput();
+ void ProcessAudioData();
+ void FillResamplerAndTimeStretcher();
+ bool AppendAudioToFrameBuffer(bool* is_frame_buffer_full);
+
+ EOSState eos_state_ = kEOSNotReceived;
+ const int channels_;
+ const SbMediaAudioSampleType sink_sample_type_;
+ const int bytes_per_frame_;
+
+ scoped_ptr<AudioResampler> resampler_;
+ optional<int> decoder_sample_rate_;
+ AudioTimeStretcher time_stretcher_;
+
+ std::vector<uint8_t> frame_buffer_;
+ uint8_t* frame_buffers_[1];
+
+ int32_t pending_decoder_outputs_ = 0;
+
+ bool can_accept_more_data_ = true;
+ JobQueue::JobToken process_audio_data_job_token_;
+ std::function<void()> process_audio_data_job_;
+
+ // Our owner will attempt to seek to time 0 when playback begins. In
+ // general, seeking could require a full reset of the underlying decoder on
+ // some platforms, so we make an effort to improve playback startup
+ // performance by keeping track of whether we already have a fresh decoder,
+ // and can thus avoid doing a full reset.
+ bool first_input_written_ = false;
+
+ scoped_ptr<AudioRendererSink> audio_renderer_sink_;
+ bool is_eos_reached_on_sink_thread_ = false;
+ bool is_playing_on_sink_thread_ = false;
+ int64_t frames_in_buffer_on_sink_thread_ = 0;
+ int64_t offset_in_frames_on_sink_thread_ = 0;
+ int64_t frames_consumed_on_sink_thread_ = 0;
+ SbTime frames_consumed_set_at_on_sink_thread_ = 0;
+ int64_t silence_frames_written_after_eos_on_sink_thread_ = 0;
+ int64_t silence_frames_consumed_on_sink_thread_ = 0;
+
+#if SB_LOG_MEDIA_TIME_STATS
+ SbTime system_and_media_time_offset_ = -1;
+ SbTime min_drift_ = kSbTimeMax;
+ SbTime max_drift_ = 0;
+ int64_t total_frames_consumed_ = 0;
+#endif // SB_LOG_MEDIA_TIME_STATS
+
+ // Set to true when there are fewer than |kFramesInBufferBeginUnderflow|
+ // frames in buffer. Set to false when the queue is full or EOS.
+ bool underflow_ = false;
+
+#if SB_PLAYER_FILTER_ENABLE_STATE_CHECK
+ static const int32_t kMaxSinkCallbacksBetweenCheck = 1024;
+ static const SbTime kCheckAudioSinkStatusInterval = kSbTimeSecond;
+ void CheckAudioSinkStatus();
+
+ atomic_int32_t sink_callbacks_since_last_check_;
+#endif // SB_PLAYER_FILTER_ENABLE_STATE_CHECK
+};
+
+} // namespace filter
+} // namespace player
+} // namespace starboard
+} // namespace shared
+} // namespace starboard
+
+#endif // STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_AUDIO_RENDERER_INTERNAL_IMPL_H_
diff --git a/src/starboard/shared/starboard/player/filter/common.h b/src/starboard/shared/starboard/player/filter/common.h
index abfac92..b487763 100644
--- a/src/starboard/shared/starboard/player/filter/common.h
+++ b/src/starboard/shared/starboard/player/filter/common.h
@@ -27,13 +27,9 @@
namespace player {
namespace filter {
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
typedef std::function<void(SbPlayerError error,
const std::string& error_message)>
ErrorCB;
-#else // SB_HAS(PLAYER_ERROR_MESSAGE)
-typedef std::function<void()> ErrorCB;
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
typedef std::function<void()> PrerolledCB;
typedef std::function<void()> EndedCB;
diff --git a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
index 0d51a92..6c9ff3e 100644
--- a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
+++ b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
@@ -125,11 +125,7 @@
update_media_info_cb_ = update_media_info_cb;
get_player_state_cb_ = get_player_state_cb;
update_player_state_cb_ = update_player_state_cb;
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
update_player_error_cb_ = update_player_error_cb;
-#else // SB_HAS(PLAYER_ERROR_MESSAGE)
- SB_DCHECK(!update_player_error_cb);
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
scoped_ptr<PlayerComponents::Factory> factory =
PlayerComponents::Factory::Create();
@@ -185,11 +181,7 @@
SB_LOG(INFO) << "Initialize audio renderer with volume " << volume_;
audio_renderer_->Initialize(
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
std::bind(&FilterBasedPlayerWorkerHandler::OnError, this, _1, _2),
-#else // SB_HAS(PLAYER_ERROR_MESSAGE)
- std::bind(&FilterBasedPlayerWorkerHandler::OnError, this),
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
std::bind(&FilterBasedPlayerWorkerHandler::OnPrerolled, this,
kSbMediaTypeAudio),
std::bind(&FilterBasedPlayerWorkerHandler::OnEnded, this,
@@ -202,11 +194,7 @@
SB_LOG(INFO) << "Initialize video renderer.";
video_renderer_->Initialize(
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
std::bind(&FilterBasedPlayerWorkerHandler::OnError, this, _1, _2),
-#else // SB_HAS(PLAYER_ERROR_MESSAGE)
- std::bind(&FilterBasedPlayerWorkerHandler::OnError, this),
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
std::bind(&FilterBasedPlayerWorkerHandler::OnPrerolled, this,
kSbMediaTypeVideo),
std::bind(&FilterBasedPlayerWorkerHandler::OnEnded, this,
@@ -408,12 +396,19 @@
const PlayerWorker::Bounds& bounds) {
SB_DCHECK(BelongsToCurrentThread());
- SB_LOG(INFO) << "Set bounds to "
- << "x: " << bounds.x << ", y: " << bounds.y
- << ", width: " << bounds.width << ", height: " << bounds.height
- << ", z_index: " << bounds.z_index;
-
if (SbMemoryCompare(&bounds_, &bounds, sizeof(bounds_)) != 0) {
+ // |z_index| is changed quite frequently. Assign |z_index| first, so we
+ // only log when the other members of |bounds| have been changed to avoid
+ // spamming the log.
+ bounds_.z_index = bounds.z_index;
+ bool bounds_changed =
+ SbMemoryCompare(&bounds_, &bounds, sizeof(bounds_)) != 0;
+ SB_LOG_IF(INFO, bounds_changed)
+ << "Set bounds to "
+ << "x: " << bounds.x << ", y: " << bounds.y
+ << ", width: " << bounds.width << ", height: " << bounds.height
+ << ", z_index: " << bounds.z_index;
+
bounds_ = bounds;
if (video_renderer_) {
// TODO: Force a frame update
@@ -425,7 +420,6 @@
return true;
}
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
void FilterBasedPlayerWorkerHandler::OnError(SbPlayerError error,
const std::string& error_message) {
if (!BelongsToCurrentThread()) {
@@ -440,16 +434,6 @@
: error_message);
}
}
-#else // SB_HAS(PLAYER_ERROR_MESSAGE)
-void FilterBasedPlayerWorkerHandler::OnError() {
- if (!BelongsToCurrentThread()) {
- Schedule(std::bind(&FilterBasedPlayerWorkerHandler::OnError, this));
- return;
- }
-
- update_player_state_cb_(kSbPlayerStateError);
-}
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
void FilterBasedPlayerWorkerHandler::OnPrerolled(SbMediaType media_type) {
if (!BelongsToCurrentThread()) {
@@ -473,6 +457,10 @@
if ((!audio_renderer_ || audio_prerolled_) &&
(!video_renderer_ || video_prerolled_)) {
update_player_state_cb_(kSbPlayerStatePresenting);
+ // The call is required to improve the calculation of media time in
+ // PlayerInternal, because it updates the system monotonic time used as the
+ // base of media time extrapolation.
+ Update();
if (!paused_) {
media_time_provider_->Play();
}
@@ -547,6 +535,9 @@
}
SbDecodeTarget FilterBasedPlayerWorkerHandler::GetCurrentDecodeTarget() {
+ if (output_mode_ != kSbPlayerOutputModeDecodeToTexture) {
+ return kSbDecodeTargetInvalid;
+ }
SbDecodeTarget decode_target = kSbDecodeTargetInvalid;
if (player_components_existence_mutex_.AcquireTry()) {
if (video_renderer_) {
diff --git a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.h b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.h
index 5529860..f0082b0 100644
--- a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.h
+++ b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.h
@@ -75,11 +75,7 @@
void Stop() override;
void Update();
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
void OnError(SbPlayerError error, const std::string& error_message);
-#else // SB_HAS(PLAYER_ERROR_MESSAGE)
- void OnError();
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
void OnPrerolled(SbMediaType media_type);
void OnEnded(SbMediaType media_type);
diff --git a/src/starboard/shared/starboard/player/filter/player_components.cc b/src/starboard/shared/starboard/player/filter/player_components.cc
index 288d905..1bee234 100644
--- a/src/starboard/shared/starboard/player/filter/player_components.cc
+++ b/src/starboard/shared/starboard/player/filter/player_components.cc
@@ -18,12 +18,14 @@
#include "starboard/shared/starboard/application.h"
#include "starboard/shared/starboard/command_line.h"
#include "starboard/shared/starboard/player/filter/adaptive_audio_decoder_internal.h"
+#include "starboard/shared/starboard/player/filter/audio_renderer_internal_impl.h"
#include "starboard/shared/starboard/player/filter/audio_renderer_sink_impl.h"
#include "starboard/shared/starboard/player/filter/media_time_provider_impl.h"
#include "starboard/shared/starboard/player/filter/punchout_video_renderer_sink.h"
#include "starboard/shared/starboard/player/filter/stub_audio_decoder.h"
#include "starboard/shared/starboard/player/filter/stub_video_decoder.h"
#include "starboard/shared/starboard/player/filter/video_render_algorithm_impl.h"
+#include "starboard/shared/starboard/player/filter/video_renderer_internal_impl.h"
namespace starboard {
namespace shared {
@@ -45,8 +47,8 @@
class PlayerComponentsImpl : public PlayerComponents {
public:
PlayerComponentsImpl(scoped_ptr<MediaTimeProviderImpl> media_time_provider,
- scoped_ptr<AudioRenderer> audio_renderer,
- scoped_ptr<VideoRenderer> video_renderer)
+ scoped_ptr<AudioRendererImpl> audio_renderer,
+ scoped_ptr<VideoRendererImpl> video_renderer)
: media_time_provider_(media_time_provider.Pass()),
audio_renderer_(audio_renderer.Pass()),
video_renderer_(video_renderer.Pass()) {
@@ -65,8 +67,8 @@
private:
// |media_time_provider_| will only be used when |audio_renderer_| is nullptr.
scoped_ptr<MediaTimeProviderImpl> media_time_provider_;
- scoped_ptr<AudioRenderer> audio_renderer_;
- scoped_ptr<VideoRenderer> video_renderer_;
+ scoped_ptr<AudioRendererImpl> audio_renderer_;
+ scoped_ptr<VideoRendererImpl> video_renderer_;
};
} // namespace
@@ -215,8 +217,8 @@
}
scoped_ptr<MediaTimeProviderImpl> media_time_provider_impl;
- scoped_ptr<AudioRenderer> audio_renderer;
- scoped_ptr<VideoRenderer> video_renderer;
+ scoped_ptr<AudioRendererImpl> audio_renderer;
+ scoped_ptr<VideoRendererImpl> video_renderer;
if (creation_parameters.audio_codec() != kSbMediaAudioCodecNone) {
SB_DCHECK(audio_decoder);
@@ -227,9 +229,9 @@
&min_frames_per_append);
audio_renderer.reset(
- new AudioRenderer(audio_decoder.Pass(), audio_renderer_sink.Pass(),
- creation_parameters.audio_sample_info(),
- max_cached_frames, min_frames_per_append));
+ new AudioRendererImpl(audio_decoder.Pass(), audio_renderer_sink.Pass(),
+ creation_parameters.audio_sample_info(),
+ max_cached_frames, min_frames_per_append));
}
if (creation_parameters.video_codec() != kSbMediaVideoCodecNone) {
@@ -245,9 +247,9 @@
new MonotonicSystemTimeProviderImpl)));
media_time_provider = media_time_provider_impl.get();
}
- video_renderer.reset(
- new VideoRenderer(video_decoder.Pass(), media_time_provider,
- video_render_algorithm.Pass(), video_renderer_sink));
+ video_renderer.reset(new VideoRendererImpl(
+ video_decoder.Pass(), media_time_provider,
+ video_render_algorithm.Pass(), video_renderer_sink));
}
SB_DCHECK(audio_renderer || video_renderer);
diff --git a/src/starboard/shared/starboard/player/filter/player_components.h b/src/starboard/shared/starboard/player/filter/player_components.h
index c41837c..567c4a1 100644
--- a/src/starboard/shared/starboard/player/filter/player_components.h
+++ b/src/starboard/shared/starboard/player/filter/player_components.h
@@ -114,11 +114,9 @@
#endif // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
SbPlayer player() const {
- SB_DCHECK(video_codec_ != kSbMediaVideoCodecNone);
return player_;
}
SbPlayerOutputMode output_mode() const {
- SB_DCHECK(video_codec_ != kSbMediaVideoCodecNone);
return output_mode_;
}
SbDecodeTargetGraphicsContextProvider*
diff --git a/src/starboard/shared/starboard/player/filter/player_filter.gypi b/src/starboard/shared/starboard/player/filter/player_filter.gypi
index 02024e1..2d79207 100644
--- a/src/starboard/shared/starboard/player/filter/player_filter.gypi
+++ b/src/starboard/shared/starboard/player/filter/player_filter.gypi
@@ -21,8 +21,9 @@
'<(DEPTH)/starboard/shared/starboard/player/filter/audio_decoder_internal.h',
'<(DEPTH)/starboard/shared/starboard/player/filter/audio_frame_tracker.cc',
'<(DEPTH)/starboard/shared/starboard/player/filter/audio_frame_tracker.h',
- '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_internal.cc',
'<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_internal.h',
+ '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_internal_impl.cc',
+ '<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_internal_impl.h',
'<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_sink.h',
'<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.cc',
'<(DEPTH)/starboard/shared/starboard/player/filter/audio_renderer_sink_impl.h',
@@ -63,8 +64,9 @@
'<(DEPTH)/starboard/shared/starboard/player/filter/video_render_algorithm.h',
'<(DEPTH)/starboard/shared/starboard/player/filter/video_render_algorithm_impl.cc',
'<(DEPTH)/starboard/shared/starboard/player/filter/video_render_algorithm_impl.h',
- '<(DEPTH)/starboard/shared/starboard/player/filter/video_renderer_internal.cc',
'<(DEPTH)/starboard/shared/starboard/player/filter/video_renderer_internal.h',
+ '<(DEPTH)/starboard/shared/starboard/player/filter/video_renderer_internal_impl.cc',
+ '<(DEPTH)/starboard/shared/starboard/player/filter/video_renderer_internal_impl.h',
'<(DEPTH)/starboard/shared/starboard/player/filter/video_renderer_sink.h',
'<(DEPTH)/starboard/shared/starboard/player/filter/wsola_internal.cc',
'<(DEPTH)/starboard/shared/starboard/player/filter/wsola_internal.h',
diff --git a/src/starboard/shared/starboard/player/filter/testing/adaptive_audio_decoder_test.cc b/src/starboard/shared/starboard/player/filter/testing/adaptive_audio_decoder_test.cc
index 4c9481d..9da268a 100644
--- a/src/starboard/shared/starboard/player/filter/testing/adaptive_audio_decoder_test.cc
+++ b/src/starboard/shared/starboard/player/filter/testing/adaptive_audio_decoder_test.cc
@@ -13,8 +13,10 @@
// limitations under the License.
#include <cmath>
+#include <deque>
#include <functional>
#include <numeric>
+#include <queue>
#include "starboard/common/mutex.h"
#include "starboard/common/scoped_ptr.h"
@@ -23,13 +25,14 @@
#include "starboard/shared/starboard/player/filter/audio_decoder_internal.h"
#include "starboard/shared/starboard/player/filter/player_components.h"
#include "starboard/shared/starboard/player/filter/stub_player_components_factory.h"
+#include "starboard/shared/starboard/player/filter/testing/test_util.h"
+#include "starboard/shared/starboard/player/job_queue.h"
#include "starboard/shared/starboard/player/video_dmp_reader.h"
#include "starboard/thread.h"
#include "testing/gtest/include/gtest/gtest.h"
// TODO: Implement AudioDecoderMock and refactor the test accordingly.
-#if SB_HAS(PLAYER_FILTER_TESTS) && \
- SB_API_VERSION >= 11
+#if SB_API_VERSION >= 11
namespace starboard {
namespace shared {
@@ -48,25 +51,18 @@
const SbTimeMonotonic kWaitForNextEventTimeOut = 5 * kSbTimeSecond;
-void DeallocateSampleFunc(SbPlayer player,
- void* context,
- const void* sample_buffer) {
- SB_UNREFERENCED_PARAMETER(player);
- SB_UNREFERENCED_PARAMETER(context);
- SB_UNREFERENCED_PARAMETER(sample_buffer);
-}
-
scoped_refptr<InputBuffer> GetAudioInputBuffer(const VideoDmpReader& dmp_reader,
size_t index) {
auto player_sample_info =
dmp_reader.GetPlayerSampleInfo(kSbMediaTypeAudio, index);
#if SB_API_VERSION >= 11
- return new InputBuffer(DeallocateSampleFunc, NULL, NULL, player_sample_info);
+ return new InputBuffer(StubDeallocateSampleFunc, NULL, NULL,
+ player_sample_info);
#else // SB_API_VERSION >= 11
SbMediaAudioSampleInfo audio_sample_info =
dmp_reader.GetAudioSampleInfo(index);
- return new InputBuffer(kSbMediaTypeAudio, DeallocateSampleFunc, NULL, NULL,
- player_sample_info, &audio_sample_info);
+ return new InputBuffer(kSbMediaTypeAudio, StubDeallocateSampleFunc, NULL,
+ NULL, player_sample_info, &audio_sample_info);
#endif // SB_API_VERSION >= 11
}
@@ -125,22 +121,12 @@
ASSERT_GT(dmp_reader->number_of_audio_buffers(), 0);
}
- PlayerComponents::Factory::CreationParameters creation_parameters(
- dmp_readers_[0]->audio_codec(), dmp_readers_[0]->audio_sample_info());
-
scoped_ptr<AudioRendererSink> audio_renderer_sink;
- scoped_ptr<PlayerComponents::Factory> factory;
- if (using_stub_decoder_) {
- factory = StubPlayerComponentsFactory::Create();
- } else {
- factory = PlayerComponents::Factory::Create();
- }
- std::string error_message;
- ASSERT_TRUE(factory->CreateSubComponents(
- creation_parameters, &audio_decoder_, &audio_renderer_sink, nullptr,
- nullptr, nullptr, &error_message));
+ ASSERT_TRUE(CreateAudioComponents(using_stub_decoder_,
+ dmp_readers_[0]->audio_codec(),
+ dmp_readers_[0]->audio_sample_info(),
+ &audio_decoder_, &audio_renderer_sink));
ASSERT_TRUE(audio_decoder_);
-
audio_decoder_->Initialize(
std::bind(&AdaptiveAudioDecoderTest::OnOutput, this),
std::bind(&AdaptiveAudioDecoderTest::OnError, this));
@@ -372,38 +358,14 @@
}
vector<vector<const char*>> GetSupportedTests() {
- // beneath_the_canopy_aac_stereo.dmp
- // codec: kSbMediaAudioCodecAac
- // sampling rate: 44.1k
- // frames per AU: 1024
- // beneath_the_canopy_opus_stereo.dmp
- // codec: kSbMediaAudioCodecOpus
- // sampling rate: 48.0k
- // frames per AU: 960
- const char* kFilenames[] = {"beneath_the_canopy_aac_stereo.dmp",
- "beneath_the_canopy_aac_5_1.dmp",
- "beneath_the_canopy_aac_mono.dmp",
- "beneath_the_canopy_opus_5_1.dmp",
- "beneath_the_canopy_opus_stereo.dmp",
- "beneath_the_canopy_opus_mono.dmp",
- "sintel_329_ec3.dmp",
- "sintel_381_ac3.dmp"};
-
static vector<vector<const char*>> test_params;
if (!test_params.empty()) {
return test_params;
}
- vector<const char*> supported_files;
- for (auto filename : kFilenames) {
- VideoDmpReader dmp_reader(ResolveTestFileName(filename).c_str());
- SB_DCHECK(dmp_reader.number_of_audio_buffers() > 0);
- if (SbMediaIsAudioSupported(dmp_reader.audio_codec(),
- dmp_reader.audio_bitrate())) {
- supported_files.push_back(filename);
- }
- }
+ vector<const char*> supported_files = GetSupportedAudioTestFiles(false);
+
// Generate test cases. For example, we have |supported_files| [A, B, C].
// Add tests A->A, A->B, A->C, B->A, B->B, B->C, C->A, C->B and C->C.
for (int i = 0; i < supported_files.size(); i++) {
@@ -440,5 +402,4 @@
} // namespace shared
} // namespace starboard
-#endif // SB_HAS(PLAYER_FILTER_TESTS) &&
- // SB_API_VERSION >= 11
+#endif // SB_API_VERSION >= 11
diff --git a/src/starboard/shared/starboard/player/filter/testing/audio_channel_layout_mixer_test.cc b/src/starboard/shared/starboard/player/filter/testing/audio_channel_layout_mixer_test.cc
index 2ca3a1c..4dad168 100644
--- a/src/starboard/shared/starboard/player/filter/testing/audio_channel_layout_mixer_test.cc
+++ b/src/starboard/shared/starboard/player/filter/testing/audio_channel_layout_mixer_test.cc
@@ -22,8 +22,6 @@
#include "starboard/shared/starboard/player/filter/audio_channel_layout_mixer.h"
#include "testing/gtest/include/gtest/gtest.h"
-#if SB_HAS(PLAYER_FILTER_TESTS)
-
namespace starboard {
namespace shared {
namespace starboard {
@@ -343,5 +341,3 @@
} // namespace starboard
} // namespace shared
} // namespace starboard
-
-#endif // SB_HAS(PLAYER_FILTER_TESTS)
diff --git a/src/starboard/shared/starboard/player/filter/testing/audio_decoder_benchmark.cc b/src/starboard/shared/starboard/player/filter/testing/audio_decoder_benchmark.cc
new file mode 100644
index 0000000..f9f57f9
--- /dev/null
+++ b/src/starboard/shared/starboard/player/filter/testing/audio_decoder_benchmark.cc
@@ -0,0 +1,157 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/shared/starboard/player/filter/audio_decoder_internal.h"
+
+#include <algorithm>
+
+#include "starboard/common/log.h"
+#include "starboard/media.h"
+#include "starboard/player.h"
+#include "starboard/shared/starboard/player/decoded_audio_internal.h"
+#include "starboard/shared/starboard/player/filter/testing/test_util.h"
+#include "starboard/shared/starboard/player/input_buffer_internal.h"
+#include "starboard/shared/starboard/player/job_queue.h"
+#include "starboard/shared/starboard/player/video_dmp_reader.h"
+#include "third_party/google_benchmark/include/benchmark/benchmark.h"
+
+namespace starboard {
+namespace shared {
+namespace starboard {
+namespace player {
+namespace filter {
+namespace testing {
+namespace {
+
+using video_dmp::VideoDmpReader;
+
+const size_t kMaxNumberOfInputs = 256;
+
+class AudioDecoderHelper {
+ public:
+ explicit AudioDecoderHelper(const char* filename)
+ : dmp_reader_(ResolveTestFileName(filename).c_str()),
+ number_of_inputs_(std::min(dmp_reader_.number_of_audio_buffers(),
+ kMaxNumberOfInputs)) {
+ const bool kUseStubDecoder = false;
+ SB_CHECK(number_of_inputs_ > 0);
+ SB_CHECK(CreateAudioComponents(kUseStubDecoder, dmp_reader_.audio_codec(),
+ dmp_reader_.audio_sample_info(),
+ &audio_decoder_, &audio_renderer_sink_));
+ SB_CHECK(audio_decoder_);
+ audio_decoder_->Initialize(std::bind(&AudioDecoderHelper::OnOutput, this),
+ std::bind(&AudioDecoderHelper::OnError, this));
+ }
+
+ size_t number_of_inputs() const { return number_of_inputs_; }
+
+ void DecodeAll() {
+ SB_CHECK(current_input_buffer_index_ == 0);
+ OnConsumed(); // Kick off the first Decode() call
+ // Note that we deliberately don't add any time out to the loop, to ensure
+ // that the benchmark is accurate.
+ while (!end_of_stream_decoded_) {
+ job_queue_.RunUntilIdle();
+ }
+ }
+
+ private:
+ scoped_refptr<InputBuffer> GetAudioInputBuffer(size_t index) {
+ auto player_sample_info =
+ dmp_reader_.GetPlayerSampleInfo(kSbMediaTypeAudio, index);
+#if SB_API_VERSION >= 11
+ return new InputBuffer(StubDeallocateSampleFunc, NULL, NULL,
+ player_sample_info);
+#else // SB_API_VERSION >= 11
+ SbMediaAudioSampleInfo audio_sample_info =
+ dmp_reader_.GetAudioSampleInfo(index);
+ return new InputBuffer(kSbMediaTypeAudio, StubDeallocateSampleFunc, NULL,
+ NULL, player_sample_info, &audio_sample_info);
+#endif // SB_API_VERSION >= 11
+ }
+
+ void OnOutput() {
+ if (!job_queue_.BelongsToCurrentThread()) {
+ job_queue_.Schedule(std::bind(&AudioDecoderHelper::OnOutput, this));
+ return;
+ }
+ int decoded_sample_rate;
+ auto decoded_audio = audio_decoder_->Read(&decoded_sample_rate);
+ end_of_stream_decoded_ = decoded_audio->is_end_of_stream();
+ }
+
+ void OnError() { SB_NOTREACHED(); }
+
+ void OnConsumed() {
+ if (!job_queue_.BelongsToCurrentThread()) {
+ job_queue_.Schedule(std::bind(&AudioDecoderHelper::OnConsumed, this));
+ return;
+ }
+ if (current_input_buffer_index_ < number_of_inputs_) {
+ audio_decoder_->Decode(GetAudioInputBuffer(current_input_buffer_index_),
+ std::bind(&AudioDecoderHelper::OnConsumed, this));
+ ++current_input_buffer_index_;
+ } else {
+ SB_CHECK(current_input_buffer_index_ == number_of_inputs_);
+ audio_decoder_->WriteEndOfStream();
+ // Increment so we can know if WriteEndOfStream() is called twice.
+ ++current_input_buffer_index_;
+ }
+ }
+
+ VideoDmpReader dmp_reader_;
+ JobQueue job_queue_;
+
+ const size_t number_of_inputs_;
+ size_t current_input_buffer_index_ = 0;
+ bool end_of_stream_decoded_ = false;
+
+ scoped_ptr<AudioDecoder> audio_decoder_;
+ scoped_ptr<AudioRendererSink> audio_renderer_sink_;
+};
+
+} // namespace
+
+void RunBenchmark(::benchmark::State& state, const char* filename) {
+ size_t number_of_inputs = 0;
+ for (auto _ : state) {
+ state.PauseTiming();
+ AudioDecoderHelper helper(filename);
+ number_of_inputs = helper.number_of_inputs();
+ state.ResumeTiming();
+ helper.DecodeAll();
+ }
+ state.SetItemsProcessed(state.iterations() * number_of_inputs);
+}
+
+} // namespace testing
+} // namespace filter
+} // namespace player
+} // namespace starboard
+} // namespace shared
+} // namespace starboard
+
+// This function has to reside in the global namespace for BENCHMARK_CAPTURE to
+// pick it up.
+void BM_AudioDecoder(::benchmark::State& state, const char* filename) {
+ starboard::shared::starboard::player::filter::testing::RunBenchmark(state,
+ filename);
+}
+
+BENCHMARK_CAPTURE(BM_AudioDecoder,
+ aac_stereo,
+ "beneath_the_canopy_aac_stereo.dmp");
+BENCHMARK_CAPTURE(BM_AudioDecoder,
+ opus_stereo,
+ "beneath_the_canopy_opus_stereo.dmp");
diff --git a/src/starboard/shared/starboard/player/filter/testing/audio_decoder_test.cc b/src/starboard/shared/starboard/player/filter/testing/audio_decoder_test.cc
index 225d9a3..b2e1392 100644
--- a/src/starboard/shared/starboard/player/filter/testing/audio_decoder_test.cc
+++ b/src/starboard/shared/starboard/player/filter/testing/audio_decoder_test.cc
@@ -29,13 +29,12 @@
#include "starboard/shared/starboard/player/decoded_audio_internal.h"
#include "starboard/shared/starboard/player/filter/player_components.h"
#include "starboard/shared/starboard/player/filter/stub_player_components_factory.h"
+#include "starboard/shared/starboard/player/filter/testing/test_util.h"
+#include "starboard/shared/starboard/player/job_queue.h"
#include "starboard/shared/starboard/player/video_dmp_reader.h"
#include "starboard/thread.h"
#include "testing/gtest/include/gtest/gtest.h"
-#if SB_HAS(PLAYER_FILTER_TESTS)
-// TODO: Write test for HE-AAC
-
namespace starboard {
namespace shared {
namespace starboard {
@@ -51,35 +50,6 @@
const SbTimeMonotonic kWaitForNextEventTimeOut = 5 * kSbTimeSecond;
-std::string GetTestInputDirectory() {
- const size_t kPathSize = kSbFileMaxPath + 1;
-
- std::vector<char> content_path(kPathSize);
- SB_CHECK(SbSystemGetPath(kSbSystemPathContentDirectory, content_path.data(),
- kPathSize));
- std::string directory_path =
- std::string(content_path.data()) + kSbFileSepChar + "test" +
- kSbFileSepChar + "starboard" + kSbFileSepChar + "shared" +
- kSbFileSepChar + "starboard" + kSbFileSepChar + "player" +
- kSbFileSepChar + "testdata";
-
- SB_CHECK(SbDirectoryCanOpen(directory_path.c_str()))
- << "Cannot open directory " << directory_path;
- return directory_path;
-}
-
-void DeallocateSampleFunc(SbPlayer player,
- void* context,
- const void* sample_buffer) {
- SB_UNREFERENCED_PARAMETER(player);
- SB_UNREFERENCED_PARAMETER(context);
- SB_UNREFERENCED_PARAMETER(sample_buffer);
-}
-
-std::string ResolveTestFileName(const char* filename) {
- return GetTestInputDirectory() + kSbFileSepChar + filename;
-}
-
class AudioDecoderTest
: public ::testing::TestWithParam<std::tuple<const char*, bool> > {
public:
@@ -105,31 +75,12 @@
const SbMediaAudioSampleInfo& audio_sample_info,
scoped_ptr<AudioDecoder>* audio_decoder,
scoped_ptr<AudioRendererSink>* audio_renderer_sink) {
- ASSERT_TRUE(audio_decoder);
- ASSERT_TRUE(audio_renderer_sink);
-
- audio_renderer_sink->reset();
- audio_decoder->reset();
-
- PlayerComponents::Factory::CreationParameters creation_parameters(
- codec, audio_sample_info);
-
- scoped_ptr<PlayerComponents::Factory> factory;
- if (using_stub_decoder_) {
- factory = StubPlayerComponentsFactory::Create();
- } else {
- factory = PlayerComponents::Factory::Create();
- }
- std::string error_message;
- if (factory->CreateSubComponents(creation_parameters, audio_decoder,
- audio_renderer_sink, nullptr, nullptr,
- nullptr, &error_message)) {
+ if (CreateAudioComponents(using_stub_decoder_, codec, audio_sample_info,
+ audio_decoder, audio_renderer_sink)) {
SB_CHECK(*audio_decoder);
(*audio_decoder)
->Initialize(std::bind(&AudioDecoderTest::OnOutput, this),
std::bind(&AudioDecoderTest::OnError, this));
- } else {
- audio_decoder->reset();
}
}
@@ -349,13 +300,13 @@
auto player_sample_info =
dmp_reader_.GetPlayerSampleInfo(kSbMediaTypeAudio, index);
#if SB_API_VERSION >= 11
- auto input_buffer = new InputBuffer(DeallocateSampleFunc, nullptr, nullptr,
- player_sample_info);
+ auto input_buffer = new InputBuffer(StubDeallocateSampleFunc, nullptr,
+ nullptr, player_sample_info);
#else // SB_API_VERSION >= 11
SbMediaAudioSampleInfo audio_sample_info =
dmp_reader_.GetAudioSampleInfo(index);
auto input_buffer =
- new InputBuffer(kSbMediaTypeAudio, DeallocateSampleFunc, nullptr,
+ new InputBuffer(kSbMediaTypeAudio, StubDeallocateSampleFunc, nullptr,
nullptr, player_sample_info, &audio_sample_info);
#endif // SB_API_VERSION >= 11
auto iter = invalid_inputs_.find(index);
@@ -658,6 +609,7 @@
SbTime duration = kSbTimeSecond / 2;
SbMediaSetAudioWriteDuration(duration);
+ SbTime start = SbTimeGetMonotonicNow();
int start_index = 0;
Event event;
while (true) {
@@ -684,43 +636,21 @@
}
WriteEndOfStream();
ASSERT_NO_FATAL_FAILURE(DrainOutputs());
+ SbTime elapsed = SbTimeGetMonotonicNow() - start;
+ SB_LOG(INFO) << "Decoding " << dmp_reader_.number_of_audio_buffers() << " au "
+ << " of " << media::GetCodecName(dmp_reader_.audio_codec())
+ << " takes " << elapsed << " microseconds.";
+
ASSERT_TRUE(last_decoded_audio_);
ASSERT_NO_FATAL_FAILURE(AssertInvalidOutputFormat());
}
#endif // SB_API_VERSION >= 11
-std::vector<const char*> GetSupportedTests() {
- const char* kFilenames[] = {"beneath_the_canopy_aac_5_1.dmp",
- "beneath_the_canopy_aac_stereo.dmp",
- "beneath_the_canopy_opus_5_1.dmp",
- "beneath_the_canopy_opus_stereo.dmp",
- "heaac.dmp",
- "sintel_329_ec3.dmp",
- "sintel_381_ac3.dmp"};
-
- static std::vector<const char*> test_params;
-
- if (!test_params.empty()) {
- return test_params;
- }
-
- for (auto filename : kFilenames) {
- VideoDmpReader dmp_reader(ResolveTestFileName(filename).c_str());
- SB_DCHECK(dmp_reader.number_of_audio_buffers() > 0);
- if (SbMediaIsAudioSupported(dmp_reader.audio_codec(),
- dmp_reader.audio_bitrate())) {
- test_params.push_back(filename);
- }
- }
-
- SB_DCHECK(!test_params.empty());
- return test_params;
-}
-
INSTANTIATE_TEST_CASE_P(AudioDecoderTests,
AudioDecoderTest,
- Combine(ValuesIn(GetSupportedTests()), Bool()));
+ Combine(ValuesIn(GetSupportedAudioTestFiles(true)),
+ Bool()));
} // namespace
} // namespace testing
@@ -729,4 +659,3 @@
} // namespace starboard
} // namespace shared
} // namespace starboard
-#endif // SB_HAS(PLAYER_FILTER_TESTS)
diff --git a/src/starboard/shared/starboard/player/filter/testing/audio_renderer_internal_test.cc b/src/starboard/shared/starboard/player/filter/testing/audio_renderer_internal_test.cc
index 575d755..d3250c1 100644
--- a/src/starboard/shared/starboard/player/filter/testing/audio_renderer_internal_test.cc
+++ b/src/starboard/shared/starboard/player/filter/testing/audio_renderer_internal_test.cc
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "starboard/shared/starboard/player/filter/audio_renderer_internal.h"
+#include "starboard/shared/starboard/player/filter/audio_renderer_internal_impl.h"
#include <functional>
#include <set>
@@ -22,13 +22,13 @@
#include "starboard/media.h"
#include "starboard/memory.h"
#include "starboard/shared/starboard/media/media_util.h"
+#include "starboard/shared/starboard/player/filter/audio_renderer_sink.h"
#include "starboard/shared/starboard/player/filter/audio_renderer_sink_impl.h"
#include "starboard/shared/starboard/player/filter/mock_audio_decoder.h"
#include "starboard/shared/starboard/player/filter/mock_audio_renderer_sink.h"
#include "starboard/thread.h"
#include "testing/gtest/include/gtest/gtest.h"
-#if SB_HAS(PLAYER_FILTER_TESTS)
namespace starboard {
namespace shared {
namespace starboard {
@@ -113,7 +113,7 @@
const int kMaxCachedFrames = 256 * 1024;
const int kMaxFramesPerAppend = 16384;
- audio_renderer_.reset(new AudioRenderer(
+ audio_renderer_.reset(new AudioRendererImpl(
make_scoped_ptr<AudioDecoder>(audio_decoder_),
make_scoped_ptr<AudioRendererSink>(audio_renderer_sink_),
GetDefaultAudioSampleInfo(), kMaxCachedFrames, kMaxFramesPerAppend));
@@ -127,14 +127,14 @@
// until the renderer reaches its preroll threshold.
// Once the renderer is "full", an EndOfStream is written.
// Returns the number of frames written.
- int FillRendererWithDecodedAudioAndWriteEOS() {
+ int FillRendererWithDecodedAudioAndWriteEOS(SbTime start_timestamp) {
const int kFramesPerBuffer = 1024;
int frames_written = 0;
while (!prerolled_) {
- SbTime timestamp =
- frames_written * kSbTimeSecond / kDefaultSamplesPerSecond;
+ SbTime timestamp = start_timestamp + frames_written * kSbTimeSecond /
+ kDefaultSamplesPerSecond;
scoped_refptr<InputBuffer> input_buffer = CreateInputBuffer(timestamp);
WriteSample(input_buffer);
CallConsumedCB();
@@ -236,7 +236,7 @@
AudioDecoder::ConsumedCB consumed_cb_;
bool prerolled_ = true;
- scoped_ptr<AudioRenderer> audio_renderer_;
+ scoped_ptr<AudioRendererImpl> audio_renderer_;
MockAudioDecoder* audio_decoder_;
MockAudioRendererSink* audio_renderer_sink_;
AudioRendererSink::RenderCallback* renderer_callback_;
@@ -327,7 +327,7 @@
Seek(0);
- int frames_written = FillRendererWithDecodedAudioAndWriteEOS();
+ int frames_written = FillRendererWithDecodedAudioAndWriteEOS(0);
bool is_playing = true;
bool is_eos_played = true;
@@ -421,7 +421,7 @@
Seek(0);
- int frames_written = FillRendererWithDecodedAudioAndWriteEOS();
+ int frames_written = FillRendererWithDecodedAudioAndWriteEOS(0);
bool is_playing = false;
bool is_eos_played = true;
bool is_underflow = true;
@@ -453,7 +453,8 @@
// Consume frames in two batches, so we can test if |GetCurrentMediaTime()|
// is incrementing in an expected manner.
- const int frames_to_consume = std::min(frames_written, frames_in_buffer) / 2;
+ const int frames_to_consume =
+ std::min(frames_written / kPlaybackRate, frames_in_buffer) / 2;
SbTime new_media_time;
EXPECT_FALSE(audio_renderer_->IsEndOfStreamPlayed());
@@ -501,7 +502,7 @@
audio_renderer_->Play();
- int frames_written = FillRendererWithDecodedAudioAndWriteEOS();
+ int frames_written = FillRendererWithDecodedAudioAndWriteEOS(0);
SendDecoderOutput(new DecodedAudio);
@@ -862,7 +863,7 @@
Seek(0);
- int frames_written = FillRendererWithDecodedAudioAndWriteEOS();
+ int frames_written = FillRendererWithDecodedAudioAndWriteEOS(0);
bool is_playing;
bool is_eos_played;
@@ -907,7 +908,7 @@
EXPECT_GE(new_media_time, media_time);
Seek(seek_time);
- frames_written += FillRendererWithDecodedAudioAndWriteEOS();
+ frames_written += FillRendererWithDecodedAudioAndWriteEOS(seek_time);
EXPECT_GE(audio_renderer_->GetCurrentMediaTime(&is_playing, &is_eos_played,
&is_underflow),
@@ -946,4 +947,3 @@
} // namespace starboard
} // namespace shared
} // namespace starboard
-#endif // SB_HAS(PLAYER_FILTER_TESTS)
diff --git a/src/starboard/shared/starboard/player/filter/testing/file_cache_reader_test.cc b/src/starboard/shared/starboard/player/filter/testing/file_cache_reader_test.cc
index 323d0bb..8506b7a 100644
--- a/src/starboard/shared/starboard/player/filter/testing/file_cache_reader_test.cc
+++ b/src/starboard/shared/starboard/player/filter/testing/file_cache_reader_test.cc
@@ -21,6 +21,7 @@
#include "starboard/configuration_constants.h"
#include "starboard/file.h"
#include "starboard/memory.h"
+#include "starboard/shared/starboard/player/filter/testing/test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace starboard {
@@ -33,27 +34,6 @@
const char kTestFilename[] = "beneath_the_canopy_aac_stereo.dmp";
-std::string GetTestInputDirectory() {
- using std::string;
- const size_t kPathSize = kSbFileMaxPath + 1;
-
- std::vector<char> content_path(kPathSize);
- SB_CHECK(SbSystemGetPath(kSbSystemPathContentDirectory, content_path.data(),
- kPathSize));
- string directory_path =
- string(content_path.data()) + kSbFileSepChar + "test" + kSbFileSepChar +
- "starboard" + kSbFileSepChar + "shared" + kSbFileSepChar + "starboard" +
- kSbFileSepChar + "player" + kSbFileSepChar + "testdata";
-
- SB_CHECK(SbDirectoryCanOpen(directory_path.c_str()))
- << "Cannot open directory " << directory_path;
- return directory_path;
-}
-
-std::string ResolveTestFileName(const char* filename) {
- return GetTestInputDirectory() + kSbFileSepChar + filename;
-}
-
class FileCacheReaderTest : public ::testing::Test {
public:
FileCacheReaderTest()
diff --git a/src/starboard/shared/starboard/player/filter/testing/media_time_provider_impl_test.cc b/src/starboard/shared/starboard/player/filter/testing/media_time_provider_impl_test.cc
index 8cf4555..2c89e47 100644
--- a/src/starboard/shared/starboard/player/filter/testing/media_time_provider_impl_test.cc
+++ b/src/starboard/shared/starboard/player/filter/testing/media_time_provider_impl_test.cc
@@ -20,7 +20,6 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#if SB_HAS(PLAYER_FILTER_TESTS)
namespace starboard {
namespace shared {
namespace starboard {
@@ -250,4 +249,3 @@
} // namespace starboard
} // namespace shared
} // namespace starboard
-#endif // SB_HAS(PLAYER_FILTER_TESTS)
diff --git a/src/starboard/shared/starboard/player/filter/testing/player_filter_tests.gyp b/src/starboard/shared/starboard/player/filter/testing/player_filter_tests.gyp
index 5a81320..507bc5f 100644
--- a/src/starboard/shared/starboard/player/filter/testing/player_filter_tests.gyp
+++ b/src/starboard/shared/starboard/player/filter/testing/player_filter_tests.gyp
@@ -25,6 +25,8 @@
'<(DEPTH)/starboard/shared/starboard/player/filter/testing/audio_renderer_internal_test.cc',
'<(DEPTH)/starboard/shared/starboard/player/filter/testing/file_cache_reader_test.cc',
'<(DEPTH)/starboard/shared/starboard/player/filter/testing/media_time_provider_impl_test.cc',
+ '<(DEPTH)/starboard/shared/starboard/player/filter/testing/test_util.cc',
+ '<(DEPTH)/starboard/shared/starboard/player/filter/testing/test_util.h',
'<(DEPTH)/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc',
'<(DEPTH)/starboard/shared/starboard/player/filter/testing/video_frame_cadence_pattern_generator_test.cc',
'<(DEPTH)/starboard/shared/starboard/player/filter/testing/video_frame_rate_estimator_test.cc',
@@ -64,5 +66,45 @@
},
'includes': [ '<(DEPTH)/starboard/build/deploy.gypi' ],
},
+ {
+ 'target_name': 'player_filter_benchmarks',
+ 'type': '<(final_executable_type)',
+ 'conditions': [
+ ['gl_type != "none"', {
+ 'dependencies': [
+ # This is needed because VideoDecoderTest depends on
+ # FakeGraphicsContextProvider which depends on EGL and GLES.
+ '<(DEPTH)/starboard/egl_and_gles/egl_and_gles.gyp:egl_and_gles',
+ ],
+ }],
+ ],
+ 'defines': [
+ # This allows the benchmarks to include internal only header files.
+ 'STARBOARD_IMPLEMENTATION',
+ ],
+ 'sources': [
+ '<(DEPTH)/starboard/shared/starboard/player/filter/testing/audio_decoder_benchmark.cc',
+ '<(DEPTH)/starboard/shared/starboard/player/filter/testing/test_util.cc',
+ '<(DEPTH)/starboard/common/benchmark_main.cc',
+ ],
+ 'dependencies': [
+ '<@(cobalt_platform_dependencies)',
+ '<(DEPTH)/starboard/shared/starboard/player/player.gyp:video_dmp',
+ '<(DEPTH)/starboard/shared/starboard/player/player.gyp:player_copy_test_data',
+ '<(DEPTH)/starboard/starboard.gyp:starboard',
+ '<(DEPTH)/third_party/google_benchmark/google_benchmark.gyp:google_benchmark',
+ ],
+ },
+ {
+ 'target_name': 'player_filter_benchmarks_deploy',
+ 'type': 'none',
+ 'dependencies': [
+ 'player_filter_benchmarks',
+ ],
+ 'variables': {
+ 'executable_name': 'player_filter_benchmarks',
+ },
+ 'includes': [ '<(DEPTH)/starboard/build/deploy.gypi' ],
+ },
],
}
diff --git a/src/starboard/shared/starboard/player/filter/testing/test_util.cc b/src/starboard/shared/starboard/player/filter/testing/test_util.cc
new file mode 100644
index 0000000..0d4181e
--- /dev/null
+++ b/src/starboard/shared/starboard/player/filter/testing/test_util.cc
@@ -0,0 +1,217 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/shared/starboard/player/filter/testing/test_util.h"
+
+#include "starboard/common/log.h"
+#include "starboard/directory.h"
+#include "starboard/shared/starboard/media/media_support_internal.h"
+#include "starboard/shared/starboard/player/filter/player_components.h"
+#include "starboard/shared/starboard/player/filter/stub_player_components_factory.h"
+#include "starboard/shared/starboard/player/filter/video_decoder_internal.h"
+#include "starboard/shared/starboard/player/video_dmp_reader.h"
+#include "starboard/string.h"
+#include "starboard/system.h"
+
+namespace starboard {
+namespace shared {
+namespace starboard {
+namespace player {
+namespace filter {
+namespace testing {
+namespace {
+
+using video_dmp::VideoDmpReader;
+
+std::string GetTestInputDirectory() {
+ const size_t kPathSize = kSbFileMaxPath + 1;
+
+ std::vector<char> content_path(kPathSize);
+ SB_CHECK(SbSystemGetPath(kSbSystemPathContentDirectory, content_path.data(),
+ kPathSize));
+ std::string directory_path = std::string(content_path.data()) +
+ kSbFileSepChar + "test" + kSbFileSepChar +
+ "starboard" + kSbFileSepChar + "shared" +
+ kSbFileSepChar + "starboard" + kSbFileSepChar +
+ "player" + kSbFileSepChar + "testdata";
+
+ SB_CHECK(SbDirectoryCanOpen(directory_path.c_str()))
+ << "Cannot open directory " << directory_path;
+ return directory_path;
+}
+
+} // namespace
+
+void StubDeallocateSampleFunc(SbPlayer player,
+ void* context,
+ const void* sample_buffer) {
+ SB_UNREFERENCED_PARAMETER(player);
+ SB_UNREFERENCED_PARAMETER(context);
+ SB_UNREFERENCED_PARAMETER(sample_buffer);
+}
+
+std::string ResolveTestFileName(const char* filename) {
+ return GetTestInputDirectory() + kSbFileSepChar + filename;
+}
+
+std::vector<const char*> GetSupportedAudioTestFiles(bool include_heaac) {
+ // beneath_the_canopy_aac_stereo.dmp
+ // codec: kSbMediaAudioCodecAac
+ // sampling rate: 44.1k
+ // frames per AU: 1024
+ // beneath_the_canopy_opus_stereo.dmp
+ // codec: kSbMediaAudioCodecOpus
+ // sampling rate: 48.0k
+ // frames per AU: 960
+
+ // IMPORTANT: do not change the order of test files unless necessary. If you
+ // must change the order of these tests please make sure you update the test
+ // filters for every platform, just in case a particular test case should be
+ // disabled.
+
+ const char* kFilenames[] = {"beneath_the_canopy_aac_stereo.dmp",
+ "beneath_the_canopy_aac_5_1.dmp",
+ "beneath_the_canopy_aac_mono.dmp",
+ "beneath_the_canopy_opus_5_1.dmp",
+ "beneath_the_canopy_opus_stereo.dmp",
+ "beneath_the_canopy_opus_mono.dmp",
+ "sintel_329_ec3.dmp",
+ "sintel_381_ac3.dmp",
+ "heaac.dmp"};
+
+ static std::vector<const char*> test_params_with_heaac;
+ static std::vector<const char*> test_params_without_heaac;
+
+ std::vector<const char*>& test_params =
+ include_heaac ? test_params_with_heaac : test_params_without_heaac;
+
+ if (!test_params.empty()) {
+ return test_params;
+ }
+
+ for (auto filename : kFilenames) {
+ VideoDmpReader dmp_reader(ResolveTestFileName(filename).c_str());
+ SB_DCHECK(dmp_reader.number_of_audio_buffers() > 0);
+ if (SbMediaIsAudioSupported(dmp_reader.audio_codec(),
+#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+ "", // content_type
+#endif // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+ dmp_reader.audio_bitrate())) {
+ test_params_with_heaac.push_back(filename);
+ if (SbStringFindString(filename, "heaac") == nullptr) {
+ test_params_without_heaac.push_back(filename);
+ }
+ }
+ }
+
+ SB_DCHECK(!test_params.empty());
+ return test_params;
+}
+
+std::vector<VideoTestParam> GetSupportedVideoTests() {
+ SbPlayerOutputMode kOutputModes[] = {kSbPlayerOutputModeDecodeToTexture,
+ kSbPlayerOutputModePunchOut};
+
+ // IMPORTANT: do not change the order of test files unless necessary. If you
+ // must change the order of these tests please make sure you update the test
+ // filters for every platform, just in case a particular test case should be
+ // disabled.
+
+ const char* kFilenames[] = {"beneath_the_canopy_137_avc.dmp",
+ "beneath_the_canopy_248_vp9.dmp",
+ "sintel_399_av1.dmp",
+ "black_test_avc_1080p_30to60_fps.dmp"};
+
+ static std::vector<VideoTestParam> test_params;
+
+ if (!test_params.empty()) {
+ return test_params;
+ }
+
+ for (auto filename : kFilenames) {
+ VideoDmpReader dmp_reader(ResolveTestFileName(filename).c_str());
+ SB_DCHECK(dmp_reader.number_of_video_buffers() > 0);
+
+ for (auto output_mode : kOutputModes) {
+ if (!VideoDecoder::OutputModeSupported(
+ output_mode, dmp_reader.video_codec(), kSbDrmSystemInvalid)) {
+ continue;
+ }
+
+ const auto& video_sample_info =
+ dmp_reader.GetPlayerSampleInfo(kSbMediaTypeVideo, 0)
+ .video_sample_info;
+
+ if (SbMediaIsVideoSupported(
+ dmp_reader.video_codec(),
+#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+ "", // content_type
+#endif // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+#if SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
+ -1, -1, 8, kSbMediaPrimaryIdUnspecified,
+ kSbMediaTransferIdUnspecified, kSbMediaMatrixIdUnspecified,
+#endif // SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
+#if SB_API_VERSION >= 11
+ video_sample_info.frame_width, video_sample_info.frame_height,
+#else // SB_API_VERSION >= 11
+ video_sample_info->frame_width, video_sample_info->frame_height,
+#endif // SB_API_VERSION >= 11
+ dmp_reader.video_bitrate(), dmp_reader.video_fps(), false)) {
+ test_params.push_back({filename, output_mode});
+ }
+ }
+ }
+
+ SB_DCHECK(!test_params.empty());
+ return test_params;
+}
+
+bool CreateAudioComponents(bool using_stub_decoder,
+ SbMediaAudioCodec codec,
+ const SbMediaAudioSampleInfo& audio_sample_info,
+ scoped_ptr<AudioDecoder>* audio_decoder,
+ scoped_ptr<AudioRendererSink>* audio_renderer_sink) {
+ SB_CHECK(audio_decoder);
+ SB_CHECK(audio_renderer_sink);
+
+ audio_renderer_sink->reset();
+ audio_decoder->reset();
+
+ PlayerComponents::Factory::CreationParameters creation_parameters(
+ codec, audio_sample_info);
+
+ scoped_ptr<PlayerComponents::Factory> factory;
+ if (using_stub_decoder) {
+ factory = StubPlayerComponentsFactory::Create();
+ } else {
+ factory = PlayerComponents::Factory::Create();
+ }
+ std::string error_message;
+ if (factory->CreateSubComponents(creation_parameters, audio_decoder,
+ audio_renderer_sink, nullptr, nullptr,
+ nullptr, &error_message)) {
+ SB_CHECK(*audio_decoder);
+ return true;
+ }
+ audio_renderer_sink->reset();
+ audio_decoder->reset();
+ return false;
+}
+
+} // namespace testing
+} // namespace filter
+} // namespace player
+} // namespace starboard
+} // namespace shared
+} // namespace starboard
diff --git a/src/starboard/shared/starboard/player/filter/testing/test_util.h b/src/starboard/shared/starboard/player/filter/testing/test_util.h
new file mode 100644
index 0000000..7002bf5
--- /dev/null
+++ b/src/starboard/shared/starboard/player/filter/testing/test_util.h
@@ -0,0 +1,60 @@
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_TESTING_TEST_UTIL_H_
+#define STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_TESTING_TEST_UTIL_H_
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "starboard/player.h"
+
+#include "starboard/shared/starboard/player/filter/audio_decoder_internal.h"
+#include "starboard/shared/starboard/player/filter/audio_renderer_sink.h"
+
+namespace starboard {
+namespace shared {
+namespace starboard {
+namespace player {
+namespace filter {
+namespace testing {
+
+typedef std::pair<const char*, SbPlayerOutputMode> VideoTestParam;
+
+// The function doesn't free the buffer, it assumes that the lifetime of the
+// buffer is actually managed by other code. It can be used in the places where
+// SbPlayerDeallocateSampleFunc is expected.
+void StubDeallocateSampleFunc(SbPlayer player,
+ void* context,
+ const void* sample_buffer);
+
+std::string ResolveTestFileName(const char* filename);
+std::vector<const char*> GetSupportedAudioTestFiles(bool include_heaac);
+std::vector<VideoTestParam> GetSupportedVideoTests();
+
+bool CreateAudioComponents(bool using_stub_decoder,
+ SbMediaAudioCodec codec,
+ const SbMediaAudioSampleInfo& audio_sample_info,
+ scoped_ptr<AudioDecoder>* audio_decoder,
+ scoped_ptr<AudioRendererSink>* audio_renderer_sink);
+
+} // namespace testing
+} // namespace filter
+} // namespace player
+} // namespace starboard
+} // namespace shared
+} // namespace starboard
+
+#endif // STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_TESTING_TEST_UTIL_H_
diff --git a/src/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc b/src/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc
index 4b39170..8a51890 100644
--- a/src/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc
+++ b/src/starboard/shared/starboard/player/filter/testing/video_decoder_test.cc
@@ -28,9 +28,9 @@
#include "starboard/drm.h"
#include "starboard/media.h"
#include "starboard/memory.h"
-#include "starboard/shared/starboard/media/media_support_internal.h"
#include "starboard/shared/starboard/media/media_util.h"
#include "starboard/shared/starboard/player/filter/stub_player_components_factory.h"
+#include "starboard/shared/starboard/player/filter/testing/test_util.h"
#include "starboard/shared/starboard/player/job_queue.h"
#include "starboard/shared/starboard/player/video_dmp_reader.h"
#include "starboard/testing/fake_graphics_context_provider.h"
@@ -38,7 +38,6 @@
#include "starboard/time.h"
#include "testing/gtest/include/gtest/gtest.h"
-#if SB_HAS(PLAYER_FILTER_TESTS)
// This has to be defined in the global namespace as its instance will be used
// as SbPlayer.
struct SbPlayerPrivate {};
@@ -62,41 +61,8 @@
using ::testing::ValuesIn;
using video_dmp::VideoDmpReader;
-struct TestParam {
- SbPlayerOutputMode output_mode;
- const char* filename;
-};
-
const SbTimeMonotonic kDefaultWaitForNextEventTimeOut = 5 * kSbTimeSecond;
-std::string GetTestInputDirectory() {
- const size_t kPathSize = kSbFileMaxPath + 1;
-
- std::vector<char> content_path(kPathSize);
- EXPECT_TRUE(SbSystemGetPath(kSbSystemPathContentDirectory,
- content_path.data(), kPathSize));
- std::string directory_path =
- std::string(content_path.data()) + kSbFileSepChar + "test" +
- kSbFileSepChar + "starboard" + kSbFileSepChar + "shared" +
- kSbFileSepChar + "starboard" + kSbFileSepChar + "player" +
- kSbFileSepChar + "testdata";
-
- SB_CHECK(SbDirectoryCanOpen(directory_path.c_str())) << directory_path;
- return directory_path;
-}
-
-void DeallocateSampleFunc(SbPlayer player,
- void* context,
- const void* sample_buffer) {
- SB_UNREFERENCED_PARAMETER(player);
- SB_UNREFERENCED_PARAMETER(context);
- SB_UNREFERENCED_PARAMETER(sample_buffer);
-}
-
-std::string ResolveTestFileName(const char* filename) {
- return GetTestInputDirectory() + kSbFileSepChar + filename;
-}
-
AssertionResult AlmostEqualTime(SbTime time1, SbTime time2) {
const SbTime kEpsilon = kSbTimeSecond / 1000;
SbTime diff = time1 - time2;
@@ -129,11 +95,11 @@
#endif // SB_HAS(PLAYER_CREATION_AND_OUTPUT_MODE_QUERY_IMPROVEMENT)
class VideoDecoderTest
- : public ::testing::TestWithParam<std::tuple<TestParam, bool>> {
+ : public ::testing::TestWithParam<std::tuple<VideoTestParam, bool>> {
public:
VideoDecoderTest()
- : test_filename_(std::get<0>(GetParam()).filename),
- output_mode_(std::get<0>(GetParam()).output_mode),
+ : test_filename_(std::get<0>(GetParam()).first),
+ output_mode_(std::get<0>(GetParam()).second),
using_stub_decoder_(std::get<1>(GetParam())),
dmp_reader_(ResolveTestFileName(test_filename_).c_str()) {
SB_LOG(INFO) << "Testing " << test_filename_ << ", output mode "
@@ -454,11 +420,12 @@
auto video_sample_info =
dmp_reader_.GetPlayerSampleInfo(kSbMediaTypeVideo, index);
#if SB_API_VERSION >= 11
- auto input_buffer =
- new InputBuffer(DeallocateSampleFunc, NULL, NULL, video_sample_info);
+ auto input_buffer = new InputBuffer(StubDeallocateSampleFunc, NULL, NULL,
+ video_sample_info);
#else // SB_API_VERSION >= 11
- auto input_buffer = new InputBuffer(kSbMediaTypeVideo, DeallocateSampleFunc,
- NULL, NULL, video_sample_info, NULL);
+ auto input_buffer =
+ new InputBuffer(kSbMediaTypeVideo, StubDeallocateSampleFunc, NULL, NULL,
+ video_sample_info, NULL);
#endif // SB_API_VERSION >= 11
auto iter = invalid_inputs_.find(index);
if (iter != invalid_inputs_.end()) {
@@ -758,10 +725,11 @@
}
TEST_P(VideoDecoderTest, ResetAfterInput) {
- const size_t kMaxInputToWrite = 10;
+ const size_t max_inputs_to_write =
+ std::min<size_t>(dmp_reader_.number_of_video_buffers(), 10);
bool error_occurred = false;
WriteMultipleInputs(
- 0, kMaxInputToWrite, [&](const Event& event, bool* continue_process) {
+ 0, max_inputs_to_write, [&](const Event& event, bool* continue_process) {
if (event.status == kTimeout || event.status == kError) {
error_occurred = true;
*continue_process = false;
@@ -775,7 +743,9 @@
}
TEST_P(VideoDecoderTest, MultipleResets) {
- for (int max_inputs = 1; max_inputs < 10; ++max_inputs) {
+ const size_t max_inputs_to_write =
+ std::min<size_t>(dmp_reader_.number_of_video_buffers(), 10);
+ for (int max_inputs = 1; max_inputs < max_inputs_to_write; ++max_inputs) {
bool error_occurred = false;
WriteMultipleInputs(
0, max_inputs, [&](const Event& event, bool* continue_process) {
@@ -912,63 +882,9 @@
ASSERT_FALSE(error_occurred);
}
-std::vector<TestParam> GetSupportedTests() {
- SbPlayerOutputMode kOutputModes[] = {kSbPlayerOutputModeDecodeToTexture,
- kSbPlayerOutputModePunchOut};
-
- const char* kFilenames[] = {"beneath_the_canopy_137_avc.dmp",
- "beneath_the_canopy_248_vp9.dmp",
- "sintel_399_av1.dmp"};
-
- static std::vector<TestParam> test_params;
-
- if (!test_params.empty()) {
- return test_params;
- }
-
- for (auto filename : kFilenames) {
- VideoDmpReader dmp_reader(ResolveTestFileName(filename).c_str());
- SB_DCHECK(dmp_reader.number_of_video_buffers() > 0);
-
- for (auto output_mode : kOutputModes) {
- if (!VideoDecoder::OutputModeSupported(
- output_mode, dmp_reader.video_codec(), kSbDrmSystemInvalid)) {
- continue;
- }
-
- const auto& video_sample_info =
- dmp_reader.GetPlayerSampleInfo(kSbMediaTypeVideo, 0)
- .video_sample_info;
-
- if (SbMediaIsVideoSupported(
- dmp_reader.video_codec(),
-#if SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
- -1, -1, 8, kSbMediaPrimaryIdUnspecified,
- kSbMediaTransferIdUnspecified, kSbMediaMatrixIdUnspecified,
-#endif // SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
-#if SB_API_VERSION >= 11
- video_sample_info.frame_width, video_sample_info.frame_height,
-#else // SB_API_VERSION >= 11
- video_sample_info->frame_width, video_sample_info->frame_height,
-#endif // SB_API_VERSION >= 11
- dmp_reader.video_bitrate(), dmp_reader.video_fps()
-#if SB_API_VERSION >= 10
- ,
- false
-#endif // SB_API_VERSION >= 10
- )) {
- test_params.push_back({output_mode, filename});
- }
- }
- }
-
- SB_DCHECK(!test_params.empty());
- return test_params;
-}
-
INSTANTIATE_TEST_CASE_P(VideoDecoderTests,
VideoDecoderTest,
- Combine(ValuesIn(GetSupportedTests()), Bool()));
+ Combine(ValuesIn(GetSupportedVideoTests()), Bool()));
} // namespace
} // namespace testing
@@ -977,4 +893,3 @@
} // namespace starboard
} // namespace shared
} // namespace starboard
-#endif // SB_HAS(PLAYER_FILTER_TESTS)
diff --git a/src/starboard/shared/starboard/player/filter/testing/video_frame_cadence_pattern_generator_test.cc b/src/starboard/shared/starboard/player/filter/testing/video_frame_cadence_pattern_generator_test.cc
index 54af4be..23b2339 100644
--- a/src/starboard/shared/starboard/player/filter/testing/video_frame_cadence_pattern_generator_test.cc
+++ b/src/starboard/shared/starboard/player/filter/testing/video_frame_cadence_pattern_generator_test.cc
@@ -16,8 +16,6 @@
#include "testing/gtest/include/gtest/gtest.h"
-#if SB_HAS(PLAYER_FILTER_TESTS)
-
namespace starboard {
namespace shared {
namespace starboard {
@@ -113,5 +111,3 @@
} // namespace starboard
} // namespace shared
} // namespace starboard
-
-#endif // SB_HAS(PLAYER_FILTER_TESTS)
diff --git a/src/starboard/shared/starboard/player/filter/testing/video_frame_rate_estimator_test.cc b/src/starboard/shared/starboard/player/filter/testing/video_frame_rate_estimator_test.cc
index 52ca795..9eb1a92 100644
--- a/src/starboard/shared/starboard/player/filter/testing/video_frame_rate_estimator_test.cc
+++ b/src/starboard/shared/starboard/player/filter/testing/video_frame_rate_estimator_test.cc
@@ -23,8 +23,6 @@
#include "starboard/time.h"
#include "testing/gtest/include/gtest/gtest.h"
-#if SB_HAS(PLAYER_FILTER_TESTS)
-
namespace starboard {
namespace shared {
namespace starboard {
@@ -243,5 +241,3 @@
} // namespace starboard
} // namespace shared
} // namespace starboard
-
-#endif // SB_HAS(PLAYER_FILTER_TESTS)
diff --git a/src/starboard/shared/starboard/player/filter/tools/audio_dmp_player.cc b/src/starboard/shared/starboard/player/filter/tools/audio_dmp_player.cc
index 4fcab39..36cfe40 100644
--- a/src/starboard/shared/starboard/player/filter/tools/audio_dmp_player.cc
+++ b/src/starboard/shared/starboard/player/filter/tools/audio_dmp_player.cc
@@ -27,8 +27,6 @@
#include "starboard/shared/starboard/player/video_dmp_reader.h"
#include "starboard/system.h"
-#if SB_HAS(PLAYER_FILTER_TESTS)
-
namespace {
using starboard::shared::starboard::player::video_dmp::VideoDmpReader;
@@ -121,7 +119,7 @@
void PrerolledCB() {
SB_LOG(INFO) << "Playback started.";
- s_player_components->GetAudioRenderer()->Play();
+ s_player_components->GetMediaTimeProvider()->Play();
}
void EndedCB() {
@@ -151,9 +149,9 @@
s_player_components->GetAudioRenderer()->Initialize(
std::bind(ErrorCB, _1, _2), std::bind(PrerolledCB), std::bind(EndedCB));
- s_player_components->GetAudioRenderer()->SetPlaybackRate(1.0);
+ s_player_components->GetMediaTimeProvider()->SetPlaybackRate(1.0);
s_player_components->GetAudioRenderer()->SetVolume(1.0);
- s_player_components->GetAudioRenderer()->Seek(0);
+ s_player_components->GetMediaTimeProvider()->Seek(0);
s_job_thread->job_queue()->Schedule(std::bind(OnTimer));
}
@@ -188,20 +186,3 @@
break;
}
}
-
-#else // SB_HAS(PLAYER_FILTER_TESTS)
-
-void SbEventHandle(const SbEvent* event) {
- switch (event->type) {
- case kSbEventTypeStart:
- SB_LOG(INFO) << "\"audio_dmp_player\" is only support in SB_API_VERSION"
- << " 10 or later, or when SB_HAS_PLAYER_FILTER_TESTS is"
- << " defined.";
- SbSystemRequestStop(0);
- break;
- default:
- break;
- }
-}
-
-#endif // SB_HAS(PLAYER_FILTER_TESTS)
diff --git a/src/starboard/shared/starboard/player/filter/video_render_algorithm_impl.cc b/src/starboard/shared/starboard/player/filter/video_render_algorithm_impl.cc
index 4877292..78b6486 100644
--- a/src/starboard/shared/starboard/player/filter/video_render_algorithm_impl.cc
+++ b/src/starboard/shared/starboard/player/filter/video_render_algorithm_impl.cc
@@ -114,7 +114,7 @@
if (is_audio_eos_played) {
while (frames->size() > 1) {
- frames->pop_back();
+ frames->pop_front();
}
}
@@ -170,13 +170,6 @@
while (frames->size() > 1 && !frames->front()->is_end_of_stream() &&
frames->front()->timestamp() < media_time) {
- frame_rate_estimate_.Update(*frames);
- auto frame_rate = frame_rate_estimate_.frame_rate();
- SB_DCHECK(frame_rate != VideoFrameRateEstimator::kInvalidFrameRate);
- cadence_pattern_generator_.UpdateRefreshRateAndMaybeReset(refresh_rate);
- cadence_pattern_generator_.UpdateFrameRate(frame_rate);
- SB_DCHECK(cadence_pattern_generator_.has_cadence());
-
auto second_iter = frames->begin();
++second_iter;
@@ -184,6 +177,13 @@
break;
}
+ frame_rate_estimate_.Update(*frames);
+ auto frame_rate = frame_rate_estimate_.frame_rate();
+ SB_DCHECK(frame_rate != VideoFrameRateEstimator::kInvalidFrameRate);
+ cadence_pattern_generator_.UpdateRefreshRateAndMaybeReset(refresh_rate);
+ cadence_pattern_generator_.UpdateFrameRate(frame_rate);
+ SB_DCHECK(cadence_pattern_generator_.has_cadence());
+
auto frame_duration =
static_cast<SbTime>(kSbTimeSecond / refresh_rate);
@@ -245,7 +245,23 @@
if (is_audio_eos_played) {
while (frames->size() > 1) {
- frames->pop_back();
+ frames->pop_front();
+ }
+ }
+
+ if (frames->size() == 2) {
+ // When there are only two frames and the second one is end of stream, we
+ // want to advance to it explicitly if the current media time is later than
+ // the timestamp of the first frame, and the first frame has been displayed.
+ // This ensures that the video can be properly ended when there is no audio
+ // stream, where |is_audio_eos_played| will never be true.
+ auto second_iter = frames->begin();
+ ++second_iter;
+
+ if ((*second_iter)->is_end_of_stream() &&
+ media_time >= frames->front()->timestamp() &&
+ current_frame_rendered_times_ > 0) {
+ frames->pop_front();
}
}
diff --git a/src/starboard/shared/starboard/player/filter/video_renderer_internal.h b/src/starboard/shared/starboard/player/filter/video_renderer_internal.h
index 0e1c85f..471dfc7 100644
--- a/src/starboard/shared/starboard/player/filter/video_renderer_internal.h
+++ b/src/starboard/shared/starboard/player/filter/video_renderer_internal.h
@@ -1,4 +1,4 @@
-// Copyright 2016 The Cobalt Authors. All Rights Reserved.
+// Copyright 2020 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -15,25 +15,11 @@
#ifndef STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_VIDEO_RENDERER_INTERNAL_H_
#define STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_VIDEO_RENDERER_INTERNAL_H_
-#include <list>
-
-#include "starboard/atomic.h"
-#include "starboard/common/log.h"
-#include "starboard/common/mutex.h"
-#include "starboard/common/optional.h"
#include "starboard/common/ref_counted.h"
#include "starboard/common/scoped_ptr.h"
-#include "starboard/media.h"
#include "starboard/shared/internal_only.h"
#include "starboard/shared/starboard/player/filter/common.h"
-#include "starboard/shared/starboard/player/filter/media_time_provider.h"
-#include "starboard/shared/starboard/player/filter/video_decoder_internal.h"
-#include "starboard/shared/starboard/player/filter/video_frame_internal.h"
-#include "starboard/shared/starboard/player/filter/video_render_algorithm.h"
-#include "starboard/shared/starboard/player/filter/video_renderer_internal.h"
-#include "starboard/shared/starboard/player/filter/video_renderer_sink.h"
#include "starboard/shared/starboard/player/input_buffer_internal.h"
-#include "starboard/shared/starboard/player/job_queue.h"
#include "starboard/time.h"
namespace starboard {
@@ -42,110 +28,28 @@
namespace player {
namespace filter {
-// A class that sits in between the video decoder, the video sink and the
-// pipeline to coordinate data transfer between these parties.
-class VideoRenderer : JobQueue::JobOwner {
+class VideoRenderer {
public:
// All of the functions are called on the PlayerWorker thread unless marked
// otherwise.
- VideoRenderer(scoped_ptr<VideoDecoder> decoder,
- MediaTimeProvider* media_time_provider,
- scoped_ptr<VideoRenderAlgorithm> algorithm,
- scoped_refptr<VideoRendererSink> sink);
- ~VideoRenderer();
+ virtual ~VideoRenderer() {}
- void Initialize(const ErrorCB& error_cb,
- const PrerolledCB& prerolled_cb,
- const EndedCB& ended_cb);
- int GetDroppedFrames() const { return algorithm_->GetDroppedFrames(); }
+ virtual void Initialize(const ErrorCB& error_cb,
+ const PrerolledCB& prerolled_cb,
+ const EndedCB& ended_cb) = 0;
+ virtual int GetDroppedFrames() const = 0;
- void WriteSample(const scoped_refptr<InputBuffer>& input_buffer);
- void WriteEndOfStream();
+ virtual void WriteSample(const scoped_refptr<InputBuffer>& input_buffer) = 0;
+ virtual void WriteEndOfStream() = 0;
- void Seek(SbTime seek_to_time);
+ virtual void Seek(SbTime seek_to_time) = 0;
- bool IsEndOfStreamWritten() const { return end_of_stream_written_.load(); }
- bool CanAcceptMoreData() const;
+ virtual bool IsEndOfStreamWritten() const = 0;
+ virtual bool CanAcceptMoreData() const = 0;
// Both of the following two functions can be called on any threads.
- void SetBounds(int z_index, int x, int y, int width, int height);
- SbDecodeTarget GetCurrentDecodeTarget();
-
- private:
- typedef std::list<scoped_refptr<VideoFrame>> Frames;
-
- // Both of the following two functions can be called on any threads.
- void OnDecoderStatus(VideoDecoder::Status status,
- const scoped_refptr<VideoFrame>& frame);
- void Render(VideoRendererSink::DrawFrameCB draw_frame_cb);
- void OnSeekTimeout();
-
- MediaTimeProvider* const media_time_provider_;
- scoped_ptr<VideoRenderAlgorithm> algorithm_;
- scoped_refptr<VideoRendererSink> sink_;
- scoped_ptr<VideoDecoder> decoder_;
-
- PrerolledCB prerolled_cb_;
- EndedCB ended_cb_;
-
- SbTimeMonotonic absolute_time_of_first_input_ = 0;
- // Our owner will attempt to seek to time 0 when playback begins. In
- // general, seeking could require a full reset of the underlying decoder on
- // some platforms, so we make an effort to improve playback startup
- // performance by keeping track of whether we already have a fresh decoder,
- // and can thus avoid doing a full reset.
- bool first_input_written_ = false;
- atomic_bool end_of_stream_written_;
- atomic_bool ended_cb_called_;
-
- atomic_bool need_more_input_;
- atomic_bool seeking_;
- SbTime seeking_to_time_ = 0;
-
- // |number_of_frames_| = decoder_frames_.size() + sink_frames_.size()
- atomic_int32_t number_of_frames_;
- // |sink_frames_| is locked inside VideoRenderer::Render() when calling
- // algorithm_->Render(). So OnDecoderStatus() won't try to lock and append
- // the decoded frames to |sink_frames_| directly to avoid being blocked. It
- // will append newly decoded frames to |decoder_frames_| instead. Note that
- // both |decoder_frames_| and |sink_frames_| can be used on multiple threads.
- // When they are being modified at the same time, |decoder_frames_mutex_|
- // should always be locked before |sink_frames_mutex_| to avoid deadlock.
- Mutex decoder_frames_mutex_;
- Frames decoder_frames_;
- Mutex sink_frames_mutex_;
- Frames sink_frames_;
-
-#if SB_PLAYER_FILTER_ENABLE_STATE_CHECK
- enum BufferingState {
- kWaitForBuffer,
- kWaitForConsumption,
- };
-
- static const SbTimeMonotonic kCheckBufferingStateInterval = kSbTimeSecond;
- static const SbTimeMonotonic kDelayBeforeWarning = 2 * kSbTimeSecond;
- static const SbTimeMonotonic kMinLagWarningInterval = 10 * kSbTimeSecond;
-
- static const SbTimeMonotonic kMaxRenderIntervalBeforeWarning =
- 66 * kSbTimeMillisecond;
- static const SbTimeMonotonic kMaxGetCurrentDecodeTargetDuration =
- 16 * kSbTimeMillisecond;
-
- void CheckBufferingState();
- void CheckForFrameLag(SbTime last_decoded_frame_timestamp);
-
- volatile BufferingState buffering_state_ = kWaitForBuffer;
- volatile SbTimeMonotonic last_buffering_state_update_ = 0;
- volatile SbTimeMonotonic last_output_ = 0;
- mutable volatile SbTime last_can_accept_more_data = 0;
- atomic_bool end_of_stream_decoded_;
-
- SbTimeMonotonic time_of_last_lag_warning_;
-
- SbTimeMonotonic time_of_last_render_call_ = -1;
-
- SbTimeMonotonic first_input_written_at_ = 0;
-#endif // SB_PLAYER_FILTER_ENABLE_STATE_CHECK
+ virtual void SetBounds(int z_index, int x, int y, int width, int height) = 0;
+ virtual SbDecodeTarget GetCurrentDecodeTarget() = 0;
};
} // namespace filter
diff --git a/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc b/src/starboard/shared/starboard/player/filter/video_renderer_internal_impl.cc
similarity index 86%
rename from src/starboard/shared/starboard/player/filter/video_renderer_internal.cc
rename to src/starboard/shared/starboard/player/filter/video_renderer_internal_impl.cc
index 0eae09d..14b442c 100644
--- a/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc
+++ b/src/starboard/shared/starboard/player/filter/video_renderer_internal_impl.cc
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "starboard/shared/starboard/player/filter/video_renderer_internal.h"
+#include "starboard/shared/starboard/player/filter/video_renderer_internal_impl.h"
#include <algorithm>
#include <functional>
@@ -32,10 +32,10 @@
} // namespace
-VideoRenderer::VideoRenderer(scoped_ptr<VideoDecoder> decoder,
- MediaTimeProvider* media_time_provider,
- scoped_ptr<VideoRenderAlgorithm> algorithm,
- scoped_refptr<VideoRendererSink> sink)
+VideoRendererImpl::VideoRendererImpl(scoped_ptr<VideoDecoder> decoder,
+ MediaTimeProvider* media_time_provider,
+ scoped_ptr<VideoRenderAlgorithm> algorithm,
+ scoped_refptr<VideoRendererSink> sink)
: media_time_provider_(media_time_provider),
algorithm_(algorithm.Pass()),
sink_(sink),
@@ -57,13 +57,13 @@
last_buffering_state_update_ = SbTimeGetMonotonicNow();
last_output_ = last_buffering_state_update_;
last_can_accept_more_data = last_buffering_state_update_;
- Schedule(std::bind(&VideoRenderer::CheckBufferingState, this),
+ Schedule(std::bind(&VideoRendererImpl::CheckBufferingState, this),
kCheckBufferingStateInterval);
time_of_last_lag_warning_ = SbTimeGetMonotonicNow() - kMinLagWarningInterval;
#endif // SB_PLAYER_FILTER_ENABLE_STATE_CHECK
}
-VideoRenderer::~VideoRenderer() {
+VideoRendererImpl::~VideoRendererImpl() {
SB_DCHECK(BelongsToCurrentThread());
sink_ = NULL;
@@ -82,9 +82,9 @@
decoder_.reset();
}
-void VideoRenderer::Initialize(const ErrorCB& error_cb,
- const PrerolledCB& prerolled_cb,
- const EndedCB& ended_cb) {
+void VideoRendererImpl::Initialize(const ErrorCB& error_cb,
+ const PrerolledCB& prerolled_cb,
+ const EndedCB& ended_cb) {
SB_DCHECK(BelongsToCurrentThread());
SB_DCHECK(prerolled_cb);
SB_DCHECK(ended_cb);
@@ -94,14 +94,14 @@
prerolled_cb_ = prerolled_cb;
ended_cb_ = ended_cb;
- decoder_->Initialize(std::bind(&VideoRenderer::OnDecoderStatus, this, _1, _2),
- error_cb);
+ decoder_->Initialize(
+ std::bind(&VideoRendererImpl::OnDecoderStatus, this, _1, _2), error_cb);
if (sink_) {
- sink_->SetRenderCB(std::bind(&VideoRenderer::Render, this, _1));
+ sink_->SetRenderCB(std::bind(&VideoRendererImpl::Render, this, _1));
}
}
-void VideoRenderer::WriteSample(
+void VideoRendererImpl::WriteSample(
const scoped_refptr<InputBuffer>& input_buffer) {
SB_DCHECK(BelongsToCurrentThread());
SB_DCHECK(input_buffer);
@@ -131,7 +131,7 @@
decoder_->WriteInputBuffer(input_buffer);
}
-void VideoRenderer::WriteEndOfStream() {
+void VideoRendererImpl::WriteEndOfStream() {
SB_DCHECK(BelongsToCurrentThread());
SB_LOG_IF(WARNING, end_of_stream_written_.load())
@@ -148,7 +148,7 @@
decoder_->WriteEndOfStream();
}
-void VideoRenderer::Seek(SbTime seek_to_time) {
+void VideoRendererImpl::Seek(SbTime seek_to_time) {
SB_DCHECK(BelongsToCurrentThread());
SB_DCHECK(seek_to_time >= 0);
@@ -169,7 +169,8 @@
auto preroll_timeout = decoder_->GetPrerollTimeout();
if (preroll_timeout != kSbTimeMax) {
- Schedule(std::bind(&VideoRenderer::OnSeekTimeout, this), preroll_timeout);
+ Schedule(std::bind(&VideoRendererImpl::OnSeekTimeout, this),
+ preroll_timeout);
}
ScopedLock scoped_lock_decoder_frames(decoder_frames_mutex_);
@@ -186,7 +187,7 @@
algorithm_->Reset(); // This is also guarded by sink_frames_mutex_.
}
-bool VideoRenderer::CanAcceptMoreData() const {
+bool VideoRendererImpl::CanAcceptMoreData() const {
SB_DCHECK(BelongsToCurrentThread());
bool can_accept_more_data =
number_of_frames_.load() <
@@ -200,17 +201,17 @@
return can_accept_more_data;
}
-void VideoRenderer::SetBounds(int z_index,
- int x,
- int y,
- int width,
- int height) {
+void VideoRendererImpl::SetBounds(int z_index,
+ int x,
+ int y,
+ int width,
+ int height) {
if (sink_) {
sink_->SetBounds(z_index, x, y, width, height);
}
}
-SbDecodeTarget VideoRenderer::GetCurrentDecodeTarget() {
+SbDecodeTarget VideoRendererImpl::GetCurrentDecodeTarget() {
// FilterBasedPlayerWorkerHandler::Stop() ensures that this function won't be
// called right before VideoRenderer dtor is called and |decoder_| is set to
// NULL inside the dtor.
@@ -231,15 +232,16 @@
#if SB_PLAYER_FILTER_ENABLE_STATE_CHECK
auto end = SbTimeGetMonotonicNow();
if (end - start > kMaxGetCurrentDecodeTargetDuration) {
- SB_LOG(WARNING) << "VideoRenderer::GetCurrentDecodeTarget() takes "
+ SB_LOG(WARNING) << "VideoRendererImpl::GetCurrentDecodeTarget() takes "
<< end - start << " microseconds.";
}
#endif // SB_PLAYER_FILTER_ENABLE_STATE_CHECK
return decode_target;
}
-void VideoRenderer::OnDecoderStatus(VideoDecoder::Status status,
- const scoped_refptr<VideoFrame>& frame) {
+void VideoRendererImpl::OnDecoderStatus(
+ VideoDecoder::Status status,
+ const scoped_refptr<VideoFrame>& frame) {
if (status == VideoDecoder::kReleaseAllFrames) {
ScopedLock scoped_lock_decoder_frames(decoder_frames_mutex_);
ScopedLock scoped_lock_sink_frames(sink_frames_mutex_);
@@ -304,7 +306,7 @@
need_more_input_.store(status == VideoDecoder::kNeedMoreInput);
}
-void VideoRenderer::Render(VideoRendererSink::DrawFrameCB draw_frame_cb) {
+void VideoRendererImpl::Render(VideoRendererSink::DrawFrameCB draw_frame_cb) {
#if SB_PLAYER_FILTER_ENABLE_STATE_CHECK
auto now = SbTimeGetMonotonicNow();
if (time_of_last_render_call_ != -1) {
@@ -351,20 +353,20 @@
#endif // SB_PLAYER_FILTER_ENABLE_STATE_CHECK
}
-void VideoRenderer::OnSeekTimeout() {
+void VideoRendererImpl::OnSeekTimeout() {
SB_DCHECK(BelongsToCurrentThread());
if (number_of_frames_.load() > 0) {
if (seeking_.exchange(false)) {
Schedule(prerolled_cb_);
}
} else if (seeking_.load()) {
- Schedule(std::bind(&VideoRenderer::OnSeekTimeout, this),
+ Schedule(std::bind(&VideoRendererImpl::OnSeekTimeout, this),
kSeekTimeoutRetryInterval);
}
}
#if SB_PLAYER_FILTER_ENABLE_STATE_CHECK
-void VideoRenderer::CheckBufferingState() {
+void VideoRendererImpl::CheckBufferingState() {
if (end_of_stream_decoded_.load()) {
return;
}
@@ -392,11 +394,11 @@
auto elasped = now - last_output_;
SB_LOG_IF(ERROR, elasped > kDelayBeforeWarning)
<< "Haven't received any output for " << elasped << " microseconds.";
- Schedule(std::bind(&VideoRenderer::CheckBufferingState, this),
+ Schedule(std::bind(&VideoRendererImpl::CheckBufferingState, this),
kCheckBufferingStateInterval);
}
-void VideoRenderer::CheckForFrameLag(SbTime last_decoded_frame_timestamp) {
+void VideoRendererImpl::CheckForFrameLag(SbTime last_decoded_frame_timestamp) {
SbTimeMonotonic now = SbTimeGetMonotonicNow();
// Limit check frequency to minimize call to GetCurrentMediaTime().
if (now - time_of_last_lag_warning_ < kMinLagWarningInterval) {
diff --git a/src/starboard/shared/starboard/player/filter/video_renderer_internal_impl.h b/src/starboard/shared/starboard/player/filter/video_renderer_internal_impl.h
new file mode 100644
index 0000000..d8c0648
--- /dev/null
+++ b/src/starboard/shared/starboard/player/filter/video_renderer_internal_impl.h
@@ -0,0 +1,161 @@
+// Copyright 2016 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_VIDEO_RENDERER_INTERNAL_IMPL_H_
+#define STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_VIDEO_RENDERER_INTERNAL_IMPL_H_
+
+#include <list>
+
+#include "starboard/atomic.h"
+#include "starboard/common/log.h"
+#include "starboard/common/mutex.h"
+#include "starboard/common/optional.h"
+#include "starboard/common/ref_counted.h"
+#include "starboard/common/scoped_ptr.h"
+#include "starboard/media.h"
+#include "starboard/shared/internal_only.h"
+#include "starboard/shared/starboard/player/filter/common.h"
+#include "starboard/shared/starboard/player/filter/media_time_provider.h"
+#include "starboard/shared/starboard/player/filter/video_decoder_internal.h"
+#include "starboard/shared/starboard/player/filter/video_frame_internal.h"
+#include "starboard/shared/starboard/player/filter/video_render_algorithm.h"
+#include "starboard/shared/starboard/player/filter/video_renderer_internal.h"
+#include "starboard/shared/starboard/player/filter/video_renderer_sink.h"
+#include "starboard/shared/starboard/player/input_buffer_internal.h"
+#include "starboard/shared/starboard/player/job_queue.h"
+#include "starboard/time.h"
+
+namespace starboard {
+namespace shared {
+namespace starboard {
+namespace player {
+namespace filter {
+
+// A class that sits in between the video decoder, the video sink and the
+// pipeline to coordinate data transfer between these parties.
+class VideoRendererImpl : public VideoRenderer, private JobQueue::JobOwner {
+ public:
+ // All of the functions are called on the PlayerWorker thread unless marked
+ // otherwise.
+ VideoRendererImpl(scoped_ptr<VideoDecoder> decoder,
+ MediaTimeProvider* media_time_provider,
+ scoped_ptr<VideoRenderAlgorithm> algorithm,
+ scoped_refptr<VideoRendererSink> sink);
+ ~VideoRendererImpl() override;
+
+ void Initialize(const ErrorCB& error_cb,
+ const PrerolledCB& prerolled_cb,
+ const EndedCB& ended_cb) override;
+ int GetDroppedFrames() const override {
+ return algorithm_->GetDroppedFrames();
+ }
+
+ void WriteSample(const scoped_refptr<InputBuffer>& input_buffer) override;
+ void WriteEndOfStream() override;
+
+ void Seek(SbTime seek_to_time) override;
+
+ bool IsEndOfStreamWritten() const override {
+ return end_of_stream_written_.load();
+ }
+ bool CanAcceptMoreData() const override;
+
+ // Both of the following two functions can be called on any threads.
+ void SetBounds(int z_index, int x, int y, int width, int height) override;
+ SbDecodeTarget GetCurrentDecodeTarget() override;
+
+ private:
+ typedef std::list<scoped_refptr<VideoFrame>> Frames;
+
+ // Both of the following two functions can be called on any threads.
+ void OnDecoderStatus(VideoDecoder::Status status,
+ const scoped_refptr<VideoFrame>& frame);
+ void Render(VideoRendererSink::DrawFrameCB draw_frame_cb);
+ void OnSeekTimeout();
+
+ MediaTimeProvider* const media_time_provider_;
+ scoped_ptr<VideoRenderAlgorithm> algorithm_;
+ scoped_refptr<VideoRendererSink> sink_;
+ scoped_ptr<VideoDecoder> decoder_;
+
+ PrerolledCB prerolled_cb_;
+ EndedCB ended_cb_;
+
+ SbTimeMonotonic absolute_time_of_first_input_ = 0;
+ // Our owner will attempt to seek to time 0 when playback begins. In
+ // general, seeking could require a full reset of the underlying decoder on
+ // some platforms, so we make an effort to improve playback startup
+ // performance by keeping track of whether we already have a fresh decoder,
+ // and can thus avoid doing a full reset.
+ bool first_input_written_ = false;
+ atomic_bool end_of_stream_written_;
+ atomic_bool ended_cb_called_;
+
+ atomic_bool need_more_input_;
+ atomic_bool seeking_;
+ SbTime seeking_to_time_ = 0;
+
+ // |number_of_frames_| = decoder_frames_.size() + sink_frames_.size()
+ atomic_int32_t number_of_frames_;
+ // |sink_frames_| is locked inside VideoRenderer::Render() when calling
+ // algorithm_->Render(). So OnDecoderStatus() won't try to lock and append
+ // the decoded frames to |sink_frames_| directly to avoid being blocked. It
+ // will append newly decoded frames to |decoder_frames_| instead. Note that
+ // both |decoder_frames_| and |sink_frames_| can be used on multiple threads.
+ // When they are being modified at the same time, |decoder_frames_mutex_|
+ // should always be locked before |sink_frames_mutex_| to avoid deadlock.
+ Mutex decoder_frames_mutex_;
+ Frames decoder_frames_;
+ Mutex sink_frames_mutex_;
+ Frames sink_frames_;
+
+#if SB_PLAYER_FILTER_ENABLE_STATE_CHECK
+ enum BufferingState {
+ kWaitForBuffer,
+ kWaitForConsumption,
+ };
+
+ static const SbTimeMonotonic kCheckBufferingStateInterval = kSbTimeSecond;
+ static const SbTimeMonotonic kDelayBeforeWarning = 2 * kSbTimeSecond;
+ static const SbTimeMonotonic kMinLagWarningInterval = 10 * kSbTimeSecond;
+
+ static const SbTimeMonotonic kMaxRenderIntervalBeforeWarning =
+ 66 * kSbTimeMillisecond;
+ static const SbTimeMonotonic kMaxGetCurrentDecodeTargetDuration =
+ 16 * kSbTimeMillisecond;
+
+ void CheckBufferingState();
+ void CheckForFrameLag(SbTime last_decoded_frame_timestamp);
+
+ volatile BufferingState buffering_state_ = kWaitForBuffer;
+ volatile SbTimeMonotonic last_buffering_state_update_ = 0;
+ volatile SbTimeMonotonic last_output_ = 0;
+ mutable volatile SbTime last_can_accept_more_data = 0;
+ atomic_bool end_of_stream_decoded_;
+
+ SbTimeMonotonic time_of_last_lag_warning_;
+
+ SbTimeMonotonic time_of_last_render_call_ = -1;
+
+ SbTimeMonotonic first_input_written_at_ = 0;
+#endif // SB_PLAYER_FILTER_ENABLE_STATE_CHECK
+};
+
+} // namespace filter
+} // namespace player
+} // namespace starboard
+} // namespace shared
+} // namespace starboard
+
+#endif // STARBOARD_SHARED_STARBOARD_PLAYER_FILTER_VIDEO_RENDERER_INTERNAL_IMPL_H_
diff --git a/src/starboard/shared/starboard/player/player_create.cc b/src/starboard/shared/starboard/player/player_create.cc
index f124449..e34b530 100644
--- a/src/starboard/shared/starboard/player/player_create.cc
+++ b/src/starboard/shared/starboard/player/player_create.cc
@@ -22,9 +22,9 @@
#include "starboard/shared/starboard/player/filter/filter_based_player_worker_handler.h"
#include "starboard/shared/starboard/player/player_internal.h"
#include "starboard/shared/starboard/player/player_worker.h"
-#if SB_PLAYER_ENABLE_VIDEO_DUMPER && SB_HAS(PLAYER_FILTER_TESTS)
+#if SB_PLAYER_ENABLE_VIDEO_DUMPER
#include "starboard/shared/starboard/player/video_dmp_writer.h"
-#endif // SB_PLAYER_ENABLE_VIDEO_DUMPER && SB_HAS(PLAYER_FILTER_TESTS)
+#endif // SB_PLAYER_ENABLE_VIDEO_DUMPER
using starboard::shared::media_session::
UpdateActiveSessionPlatformPlaybackState;
@@ -81,9 +81,9 @@
SbMediaAudioCodec audio_codec = creation_param->audio_sample_info.codec;
SbMediaVideoCodec video_codec = creation_param->video_sample_info.codec;
-#if SB_PLAYER_ENABLE_VIDEO_DUMPER && SB_HAS(PLAYER_FILTER_TESTS)
+#if SB_PLAYER_ENABLE_VIDEO_DUMPER
SbDrmSystem drm_system = creation_param->drm_system;
-#endif // SB_PLAYER_ENABLE_VIDEO_DUMPER && SB_HAS(PLAYER_FILTER_TESTS)
+#endif // SB_PLAYER_ENABLE_VIDEO_DUMPER
const SbMediaAudioSampleInfo* audio_sample_info =
&creation_param->audio_sample_info;
const auto output_mode = creation_param->output_mode;
@@ -93,9 +93,6 @@
SbPlayer SbPlayerCreate(SbWindow window,
SbMediaVideoCodec video_codec,
SbMediaAudioCodec audio_codec,
-#if SB_API_VERSION < 10
- SbMediaTime duration_pts,
-#endif // SB_API_VERSION < 10
SbDrmSystem drm_system,
const SbMediaAudioSampleInfo* audio_sample_info,
#if SB_API_VERSION >= 11
@@ -104,9 +101,7 @@
SbPlayerDeallocateSampleFunc sample_deallocate_func,
SbPlayerDecoderStatusFunc decoder_status_func,
SbPlayerStatusFunc player_status_func,
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
SbPlayerErrorFunc player_error_func,
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
void* context,
SbPlayerOutputMode output_mode,
SbDecodeTargetGraphicsContextProvider* provider) {
@@ -116,9 +111,6 @@
#if SB_API_VERSION >= 11
SB_UNREFERENCED_PARAMETER(max_video_capabilities);
#endif // SB_API_VERSION >= 11
-#if SB_API_VERSION < 10
- SB_UNREFERENCED_PARAMETER(duration_pts);
-#endif // SB_API_VERSION < 10
#if SB_API_VERSION >= 11
if (audio_sample_info) {
SB_DCHECK(audio_sample_info->codec == audio_codec);
@@ -126,16 +118,18 @@
#endif // SB_API_VERSION >= 11
if (!sample_deallocate_func || !decoder_status_func || !player_status_func
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
|| !player_error_func
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
) {
return kSbPlayerInvalid;
}
const int64_t kDefaultBitRate = 0;
if (audio_codec != kSbMediaAudioCodecNone &&
- !SbMediaIsAudioSupported(audio_codec, kDefaultBitRate)) {
+ !SbMediaIsAudioSupported(audio_codec,
+#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+ audio_mime,
+#endif // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+ kDefaultBitRate)) {
SB_LOG(ERROR) << "Unsupported audio codec " << audio_codec;
return kSbPlayerInvalid;
}
@@ -147,20 +141,19 @@
const int kDefaultFrameHeight = 0;
const int kDefaultFrameRate = 0;
if (video_codec != kSbMediaVideoCodecNone &&
- !SbMediaIsVideoSupported(video_codec,
+ !SbMediaIsVideoSupported(
+ video_codec,
+#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+ video_mime,
+#endif // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
#if SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
- kDefaultProfile, kDefaultLevel,
- kDefaultColorDepth, kSbMediaPrimaryIdUnspecified,
- kSbMediaTransferIdUnspecified,
- kSbMediaMatrixIdUnspecified,
+ kDefaultProfile, kDefaultLevel, kDefaultColorDepth,
+ kSbMediaPrimaryIdUnspecified, kSbMediaTransferIdUnspecified,
+ kSbMediaMatrixIdUnspecified,
#endif // SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
- kDefaultFrameWidth, kDefaultFrameHeight,
- kDefaultBitRate, kDefaultFrameRate
-#if SB_API_VERSION >= 10
- ,
- output_mode == kSbPlayerOutputModeDecodeToTexture
-#endif
- )) {
+ kDefaultFrameWidth, kDefaultFrameHeight, kDefaultBitRate,
+ kDefaultFrameRate,
+ output_mode == kSbPlayerOutputModeDecodeToTexture)) {
SB_LOG(ERROR) << "Unsupported video codec " << video_codec;
return kSbPlayerInvalid;
}
@@ -206,16 +199,14 @@
SbPlayer player = SbPlayerPrivate::CreateInstance(
audio_codec, video_codec, audio_sample_info, sample_deallocate_func,
decoder_status_func, player_status_func,
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
player_error_func,
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
context, handler.Pass());
-#if SB_PLAYER_ENABLE_VIDEO_DUMPER && SB_HAS(PLAYER_FILTER_TESTS)
+#if SB_PLAYER_ENABLE_VIDEO_DUMPER
using ::starboard::shared::starboard::player::video_dmp::VideoDmpWriter;
VideoDmpWriter::OnPlayerCreate(player, audio_codec, video_codec, drm_system,
audio_sample_info);
-#endif // SB_PLAYER_ENABLE_VIDEO_DUMPER && SB_HAS(PLAYER_FILTER_TESTS)
+#endif // SB_PLAYER_ENABLE_VIDEO_DUMPER
return player;
}
diff --git a/src/starboard/shared/starboard/player/player_destroy.cc b/src/starboard/shared/starboard/player/player_destroy.cc
index f7e2660..7e75eb0 100644
--- a/src/starboard/shared/starboard/player/player_destroy.cc
+++ b/src/starboard/shared/starboard/player/player_destroy.cc
@@ -16,9 +16,9 @@
#include "starboard/shared/media_session/playback_state.h"
#include "starboard/shared/starboard/player/player_internal.h"
-#if SB_PLAYER_ENABLE_VIDEO_DUMPER && SB_HAS(PLAYER_FILTER_TESTS)
+#if SB_PLAYER_ENABLE_VIDEO_DUMPER
#include "starboard/shared/starboard/player/video_dmp_writer.h"
-#endif // SB_PLAYER_ENABLE_VIDEO_DUMPER && SB_HAS(PLAYER_FILTER_TESTS)
+#endif // SB_PLAYER_ENABLE_VIDEO_DUMPER
using starboard::shared::media_session::kNone;
using starboard::shared::media_session::
@@ -30,10 +30,10 @@
}
UpdateActiveSessionPlatformPlaybackState(kNone);
-#if SB_PLAYER_ENABLE_VIDEO_DUMPER && SB_HAS(PLAYER_FILTER_TESTS)
+#if SB_PLAYER_ENABLE_VIDEO_DUMPER
using ::starboard::shared::starboard::player::video_dmp::VideoDmpWriter;
VideoDmpWriter::OnPlayerDestroy(player);
-#endif // SB_PLAYER_ENABLE_VIDEO_DUMPER && SB_HAS(PLAYER_FILTER_TESTS)
+#endif // SB_PLAYER_ENABLE_VIDEO_DUMPER
delete player;
}
diff --git a/src/starboard/shared/starboard/player/player_get_info.cc b/src/starboard/shared/starboard/player/player_get_info.cc
deleted file mode 100644
index 76677da..0000000
--- a/src/starboard/shared/starboard/player/player_get_info.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2016 The Cobalt Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "starboard/player.h"
-
-#include "starboard/common/log.h"
-#include "starboard/shared/starboard/player/player_internal.h"
-
-#if SB_API_VERSION < 10
-void SbPlayerGetInfo(SbPlayer player, SbPlayerInfo* out_player_info) {
- if (!SbPlayerIsValid(player)) {
- SB_DLOG(WARNING) << "player is invalid.";
- return;
- }
-
- if (out_player_info == NULL) {
- SB_DLOG(WARNING) << "out_player_info is NULL.";
- return;
- }
-
- player->GetInfo(out_player_info);
-}
-#endif // SB_API_VERSION < 10
diff --git a/src/starboard/shared/starboard/player/player_get_info2.cc b/src/starboard/shared/starboard/player/player_get_info2.cc
index d73f921..528b124 100644
--- a/src/starboard/shared/starboard/player/player_get_info2.cc
+++ b/src/starboard/shared/starboard/player/player_get_info2.cc
@@ -17,7 +17,6 @@
#include "starboard/common/log.h"
#include "starboard/shared/starboard/player/player_internal.h"
-#if SB_API_VERSION >= 10
void SbPlayerGetInfo2(SbPlayer player, SbPlayerInfo2* out_player_info) {
if (!SbPlayerIsValid(player)) {
SB_DLOG(WARNING) << "player is invalid.";
@@ -31,4 +30,3 @@
player->GetInfo(out_player_info);
}
-#endif // SB_API_VERSION >= 10
diff --git a/src/starboard/shared/starboard/player/player_get_maximum_number_of_samples_per_write.cc b/src/starboard/shared/starboard/player/player_get_maximum_number_of_samples_per_write.cc
index f053425..f704486 100644
--- a/src/starboard/shared/starboard/player/player_get_maximum_number_of_samples_per_write.cc
+++ b/src/starboard/shared/starboard/player/player_get_maximum_number_of_samples_per_write.cc
@@ -14,9 +14,7 @@
#include "starboard/player.h"
-#if SB_API_VERSION >= 10
int SbPlayerGetMaximumNumberOfSamplesPerWrite(SbPlayer /*player*/,
SbMediaType /*sample_type*/) {
return 1;
}
-#endif // SB_API_VERSION >= 10
diff --git a/src/starboard/shared/starboard/player/player_internal.cc b/src/starboard/shared/starboard/player/player_internal.cc
index 924de76..c273223 100644
--- a/src/starboard/shared/starboard/player/player_internal.cc
+++ b/src/starboard/shared/starboard/player/player_internal.cc
@@ -17,9 +17,9 @@
#include <functional>
#include "starboard/common/log.h"
-#if SB_PLAYER_ENABLE_VIDEO_DUMPER && SB_HAS(PLAYER_FILTER_TESTS)
+#if SB_PLAYER_ENABLE_VIDEO_DUMPER
#include "starboard/shared/starboard/player/video_dmp_writer.h"
-#endif // SB_PLAYER_ENABLE_VIDEO_DUMPER && SB_HAS(PLAYER_FILTER_TESTS)
+#endif // SB_PLAYER_ENABLE_VIDEO_DUMPER
namespace {
@@ -47,9 +47,7 @@
SbPlayerDeallocateSampleFunc sample_deallocate_func,
SbPlayerDecoderStatusFunc decoder_status_func,
SbPlayerStatusFunc player_status_func,
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
SbPlayerErrorFunc player_error_func,
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
void* context,
starboard::scoped_ptr<PlayerWorker::Handler> player_worker_handler)
: sample_deallocate_func_(sample_deallocate_func),
@@ -64,9 +62,7 @@
audio_codec, video_codec, player_worker_handler.Pass(),
std::bind(&SbPlayerPrivate::UpdateMediaInfo, this, _1, _2, _3, _4),
decoder_status_func, player_status_func,
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
player_error_func,
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
this, context));
++number_of_players_;
@@ -82,17 +78,13 @@
SbPlayerDeallocateSampleFunc sample_deallocate_func,
SbPlayerDecoderStatusFunc decoder_status_func,
SbPlayerStatusFunc player_status_func,
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
SbPlayerErrorFunc player_error_func,
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
void* context,
starboard::scoped_ptr<PlayerWorker::Handler> player_worker_handler) {
SbPlayerPrivate* ret = new SbPlayerPrivate(
audio_codec, video_codec, audio_sample_info, sample_deallocate_func,
decoder_status_func, player_status_func,
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
player_error_func,
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
context, player_worker_handler.Pass());
if (ret && ret->worker_) {
@@ -123,10 +115,10 @@
}
starboard::scoped_refptr<InputBuffer> input_buffer =
new InputBuffer(sample_deallocate_func_, this, context_, sample_info);
-#if SB_PLAYER_ENABLE_VIDEO_DUMPER && SB_HAS(PLAYER_FILTER_TESTS)
+#if SB_PLAYER_ENABLE_VIDEO_DUMPER
using ::starboard::shared::starboard::player::video_dmp::VideoDmpWriter;
VideoDmpWriter::OnPlayerWriteSample(this, input_buffer);
-#endif // SB_PLAYER_ENABLE_VIDEO_DUMPER && SB_HAS(PLAYER_FILTER_TESTS)
+#endif // SB_PLAYER_ENABLE_VIDEO_DUMPER
worker_->WriteSample(input_buffer);
}
#else // SB_API_VERSION >= 11
@@ -140,10 +132,10 @@
starboard::scoped_refptr<InputBuffer> input_buffer =
new InputBuffer(sample_type, sample_deallocate_func_, this, context_,
sample_info, &audio_sample_info_);
-#if SB_PLAYER_ENABLE_VIDEO_DUMPER && SB_HAS(PLAYER_FILTER_TESTS)
+#if SB_PLAYER_ENABLE_VIDEO_DUMPER
using ::starboard::shared::starboard::player::video_dmp::VideoDmpWriter;
VideoDmpWriter::OnPlayerWriteSample(this, input_buffer);
-#endif // SB_PLAYER_ENABLE_VIDEO_DUMPER && SB_HAS(PLAYER_FILTER_TESTS)
+#endif // SB_PLAYER_ENABLE_VIDEO_DUMPER
worker_->WriteSample(input_buffer);
}
#endif // SB_API_VERSION >= 11
@@ -162,23 +154,10 @@
// TODO: Wait until a frame is rendered with the updated bounds.
}
-#if SB_API_VERSION < 10
-void SbPlayerPrivate::GetInfo(SbPlayerInfo* out_player_info) {
-#else // SB_API_VERSION < 10
void SbPlayerPrivate::GetInfo(SbPlayerInfo2* out_player_info) {
-#endif // SB_API_VERSION < 10
SB_DCHECK(out_player_info != NULL);
starboard::ScopedLock lock(mutex_);
-#if SB_API_VERSION < 10
- out_player_info->duration_pts = SB_PLAYER_NO_DURATION;
- if (is_paused_ || underflow_) {
- out_player_info->current_media_pts = SB_TIME_TO_SB_MEDIA_TIME(media_time_);
- } else {
- out_player_info->current_media_pts = SB_TIME_TO_SB_MEDIA_TIME(
- GetMediaTime(media_time_, media_time_updated_at_, playback_rate_));
- }
-#else // SB_API_VERSION < 10
out_player_info->duration = SB_PLAYER_NO_DURATION;
if (is_paused_ || underflow_) {
out_player_info->current_media_timestamp = media_time_;
@@ -186,7 +165,6 @@
out_player_info->current_media_timestamp =
GetMediaTime(media_time_, media_time_updated_at_, playback_rate_);
}
-#endif // SB_API_VERSION < 10
out_player_info->frame_width = frame_width_;
out_player_info->frame_height = frame_height_;
diff --git a/src/starboard/shared/starboard/player/player_internal.h b/src/starboard/shared/starboard/player/player_internal.h
index d030869..da69e23 100644
--- a/src/starboard/shared/starboard/player/player_internal.h
+++ b/src/starboard/shared/starboard/player/player_internal.h
@@ -37,9 +37,7 @@
SbPlayerDeallocateSampleFunc sample_deallocate_func,
SbPlayerDecoderStatusFunc decoder_status_func,
SbPlayerStatusFunc player_status_func,
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
SbPlayerErrorFunc player_error_func,
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
void* context,
starboard::scoped_ptr<PlayerWorker::Handler> player_worker_handler);
@@ -53,11 +51,7 @@
void WriteEndOfStream(SbMediaType stream_type);
void SetBounds(int z_index, int x, int y, int width, int height);
-#if SB_API_VERSION < 10
- void GetInfo(SbPlayerInfo* out_player_info);
-#else // SB_API_VERSION < 10
void GetInfo(SbPlayerInfo2* out_player_info);
-#endif // SB_API_VERSION < 10
void SetPause(bool pause);
void SetPlaybackRate(double playback_rate);
void SetVolume(double volume);
@@ -70,8 +64,6 @@
<< number_of_players_ << " players.";
}
- static int number_of_players() { return number_of_players_; }
-
private:
SbPlayerPrivate(
SbMediaAudioCodec audio_codec,
@@ -80,9 +72,7 @@
SbPlayerDeallocateSampleFunc sample_deallocate_func,
SbPlayerDecoderStatusFunc decoder_status_func,
SbPlayerStatusFunc player_status_func,
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
SbPlayerErrorFunc player_error_func,
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
void* context,
starboard::scoped_ptr<PlayerWorker::Handler> player_worker_handler);
diff --git a/src/starboard/shared/starboard/player/player_seek.cc b/src/starboard/shared/starboard/player/player_seek.cc
deleted file mode 100644
index b2ae194..0000000
--- a/src/starboard/shared/starboard/player/player_seek.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2016 The Cobalt Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "starboard/player.h"
-
-#include "starboard/common/log.h"
-#include "starboard/shared/starboard/player/player_internal.h"
-
-#if SB_API_VERSION < 10
-void SbPlayerSeek(SbPlayer player, SbMediaTime seek_to_pts, int ticket) {
- if (!SbPlayerIsValid(player)) {
- SB_DLOG(WARNING) << "player is invalid.";
- return;
- }
-
- player->Seek(SB_MEDIA_TIME_TO_SB_TIME(seek_to_pts), ticket);
-}
-#endif // SB_API_VERSION < 10
diff --git a/src/starboard/shared/starboard/player/player_seek2.cc b/src/starboard/shared/starboard/player/player_seek2.cc
index 2605d99..f34ae55 100644
--- a/src/starboard/shared/starboard/player/player_seek2.cc
+++ b/src/starboard/shared/starboard/player/player_seek2.cc
@@ -17,7 +17,6 @@
#include "starboard/common/log.h"
#include "starboard/shared/starboard/player/player_internal.h"
-#if SB_API_VERSION >= 10
void SbPlayerSeek2(SbPlayer player, SbTime seek_to_timestamp, int ticket) {
if (!SbPlayerIsValid(player)) {
SB_DLOG(WARNING) << "player is invalid.";
@@ -26,4 +25,3 @@
player->Seek(seek_to_timestamp, ticket);
}
-#endif // SB_API_VERSION >= 10
diff --git a/src/starboard/shared/starboard/player/player_worker.cc b/src/starboard/shared/starboard/player/player_worker.cc
index 4d1ab24..07a3f8e 100644
--- a/src/starboard/shared/starboard/player/player_worker.cc
+++ b/src/starboard/shared/starboard/player/player_worker.cc
@@ -65,18 +65,14 @@
UpdateMediaInfoCB update_media_info_cb,
SbPlayerDecoderStatusFunc decoder_status_func,
SbPlayerStatusFunc player_status_func,
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
SbPlayerErrorFunc player_error_func,
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
SbPlayer player,
void* context) {
PlayerWorker* ret = new PlayerWorker(audio_codec, video_codec, handler.Pass(),
update_media_info_cb,
decoder_status_func, player_status_func,
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
player_error_func,
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
player, context);
if (ret && SbThreadIsValid(ret->thread_)) {
@@ -106,9 +102,7 @@
UpdateMediaInfoCB update_media_info_cb,
SbPlayerDecoderStatusFunc decoder_status_func,
SbPlayerStatusFunc player_status_func,
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
SbPlayerErrorFunc player_error_func,
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
SbPlayer player,
void* context)
: thread_(kSbThreadInvalid),
@@ -118,9 +112,7 @@
update_media_info_cb_(update_media_info_cb),
decoder_status_func_(decoder_status_func),
player_status_func_(player_status_func),
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
player_error_func_(player_error_func),
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
player_(player),
context_(context),
ticket_(SB_PLAYER_INITIAL_TICKET),
@@ -152,18 +144,10 @@
}
void PlayerWorker::UpdatePlayerState(SbPlayerState player_state) {
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
if (error_occurred_) {
SB_LOG(WARNING) << "Player state is updated after an error.";
return;
}
-#else // SB_HAS(PLAYER_ERROR_MESSAGE)
- SB_DCHECK(error_occurred_ == (player_state == kSbPlayerStateError))
- << "Player state error if and only if error occurred.";
- if (error_occurred_ && (player_state != kSbPlayerStateError)) {
- return;
- }
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
player_state_ = player_state;
if (!player_status_func_) {
@@ -173,7 +157,6 @@
player_status_func_(player_, context_, player_state_, ticket_);
}
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
void PlayerWorker::UpdatePlayerError(SbPlayerError error,
const std::string& error_message) {
error_occurred_ = true;
@@ -186,13 +169,6 @@
player_error_func_(player_, context_, error, error_message.c_str());
}
-#else // SB_HAS(PLAYER_ERROR_MESSAGE)
-void PlayerWorker::UpdatePlayerError(const std::string& message) {
- SB_LOG(WARNING) << "encountered player error: " << message;
-
- UpdatePlayerState(kSbPlayerStateError);
-}
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
// static
void* PlayerWorker::ThreadEntryPoint(void* context) {
@@ -220,10 +196,8 @@
SB_DCHECK(job_queue_->BelongsToCurrentThread());
Handler::UpdatePlayerErrorCB update_player_error_cb;
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
update_player_error_cb =
std::bind(&PlayerWorker::UpdatePlayerError, this, _1, _2);
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
std::string error_message;
if (handler_->Init(
player_, std::bind(&PlayerWorker::UpdateMediaInfo, this, _1, _2, _3),
@@ -232,14 +206,9 @@
update_player_error_cb, &error_message)) {
UpdatePlayerState(kSbPlayerStateInitialized);
} else {
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
UpdatePlayerError(
kSbPlayerErrorDecode,
"Failed to initialize PlayerWorker with error " + error_message);
-#else // SB_HAS(PLAYER_ERROR_MESSAGE)
- UpdatePlayerError("Failed to initialize PlayerWorker with error " +
- error_message);
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
}
}
@@ -260,11 +229,7 @@
pending_video_buffer_ = NULL;
if (!handler_->Seek(seek_to_time, ticket)) {
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
UpdatePlayerError(kSbPlayerErrorDecode, "Failed seek.");
-#else // SB_HAS(PLAYER_ERROR_MESSAGE)
- UpdatePlayerError("Failed seek.");
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
return;
}
@@ -306,11 +271,7 @@
bool written;
bool result = handler_->WriteSample(input_buffer, &written);
if (!result) {
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
UpdatePlayerError(kSbPlayerErrorDecode, "Failed to write sample.");
-#else // SB_HAS(PLAYER_ERROR_MESSAGE)
- UpdatePlayerError("Failed to write sample.");
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
return;
}
if (written) {
@@ -370,22 +331,14 @@
}
if (!handler_->WriteEndOfStream(sample_type)) {
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
UpdatePlayerError(kSbPlayerErrorDecode, "Failed to write end of stream.");
-#else // SB_HAS(PLAYER_ERROR_MESSAGE)
- UpdatePlayerError("Failed to write end of stream.");
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
}
}
void PlayerWorker::DoSetBounds(Bounds bounds) {
SB_DCHECK(job_queue_->BelongsToCurrentThread());
if (!handler_->SetBounds(bounds)) {
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
UpdatePlayerError(kSbPlayerErrorDecode, "Failed to set bounds");
-#else // SB_HAS(PLAYER_ERROR_MESSAGE)
- UpdatePlayerError("Failed to set bounds");
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
}
}
@@ -393,11 +346,7 @@
SB_DCHECK(job_queue_->BelongsToCurrentThread());
if (!handler_->SetPause(pause)) {
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
UpdatePlayerError(kSbPlayerErrorDecode, "Failed to set pause.");
-#else // SB_HAS(PLAYER_ERROR_MESSAGE)
- UpdatePlayerError("Failed to set pause.");
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
}
}
@@ -405,11 +354,7 @@
SB_DCHECK(job_queue_->BelongsToCurrentThread());
if (!handler_->SetPlaybackRate(playback_rate)) {
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
UpdatePlayerError(kSbPlayerErrorDecode, "Failed to set playback rate.");
-#else // SB_HAS(PLAYER_ERROR_MESSAGE)
- UpdatePlayerError("Failed to set playback rate.");
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
}
}
diff --git a/src/starboard/shared/starboard/player/player_worker.h b/src/starboard/shared/starboard/player/player_worker.h
index 49d7042..936756e 100644
--- a/src/starboard/shared/starboard/player/player_worker.h
+++ b/src/starboard/shared/starboard/player/player_worker.h
@@ -65,13 +65,9 @@
UpdateMediaInfoCB;
typedef std::function<SbPlayerState()> GetPlayerStateCB;
typedef std::function<void(SbPlayerState player_state)> UpdatePlayerStateCB;
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
typedef std::function<void(SbPlayerError error,
const std::string& error_message)>
UpdatePlayerErrorCB;
-#else // SB_HAS(PLAYER_ERROR_MESSAGE)
- typedef std::function<void()> UpdatePlayerErrorCB;
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
virtual ~Handler() {}
// All the following functions return false to signal a fatal error. The
@@ -107,9 +103,7 @@
UpdateMediaInfoCB update_media_info_cb,
SbPlayerDecoderStatusFunc decoder_status_func,
SbPlayerStatusFunc player_status_func,
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
SbPlayerErrorFunc player_error_func,
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
SbPlayer player,
void* context);
@@ -170,9 +164,7 @@
UpdateMediaInfoCB update_media_info_cb,
SbPlayerDecoderStatusFunc decoder_status_func,
SbPlayerStatusFunc player_status_func,
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
SbPlayerErrorFunc player_error_func,
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
SbPlayer player,
void* context);
@@ -180,11 +172,7 @@
SbPlayerState player_state() const { return player_state_; }
void UpdatePlayerState(SbPlayerState player_state);
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
void UpdatePlayerError(SbPlayerError error, const std::string& message);
-#else // SB_HAS(PLAYER_ERROR_MESSAGE)
- void UpdatePlayerError(const std::string& message);
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
static void* ThreadEntryPoint(void* context);
void RunLoop();
@@ -211,9 +199,7 @@
SbPlayerDecoderStatusFunc decoder_status_func_;
SbPlayerStatusFunc player_status_func_;
-#if SB_HAS(PLAYER_ERROR_MESSAGE)
SbPlayerErrorFunc player_error_func_;
-#endif // SB_HAS(PLAYER_ERROR_MESSAGE)
bool error_occurred_ = false;
SbPlayer player_;
void* context_;
diff --git a/src/starboard/shared/starboard/player/player_write_sample.cc b/src/starboard/shared/starboard/player/player_write_sample.cc
deleted file mode 100644
index ca67484..0000000
--- a/src/starboard/shared/starboard/player/player_write_sample.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2016 The Cobalt Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "starboard/player.h"
-
-#include "starboard/common/log.h"
-#include "starboard/shared/starboard/player/player_internal.h"
-
-#if SB_API_VERSION < 10
-void SbPlayerWriteSample(SbPlayer player,
- SbMediaType sample_type,
- const void* const* sample_buffers,
- const int* sample_buffer_sizes,
- int number_of_sample_buffers,
- SbMediaTime sample_pts,
- const SbMediaVideoSampleInfo* video_sample_info,
- const SbDrmSampleInfo* sample_drm_info) {
- if (!SbPlayerIsValid(player)) {
- SB_DLOG(WARNING) << "player is invalid.";
- return;
- }
-
- if (number_of_sample_buffers < 1) {
- SB_DLOG(WARNING) << "SbPlayerWriteSample() doesn't support"
- << " |number_of_sample_buffers| less than one.";
- return;
- }
-
- SB_DCHECK(number_of_sample_buffers == 1);
-
- if (number_of_sample_buffers > 1) {
- SB_DLOG(WARNING) << "SbPlayerWriteSample() doesn't support"
- << " |number_of_sample_buffers| greater than one.";
- return;
- }
-
- if (sample_buffers == NULL) {
- SB_DLOG(WARNING) << "|sample_buffers| cannot be NULL";
- return;
- }
-
- if (sample_buffer_sizes == NULL) {
- SB_DLOG(WARNING) << "|sample_buffer_sizes| cannot be NULL";
- return;
- }
-
- SbTime sample_timestamp = SB_MEDIA_TIME_TO_SB_TIME(sample_pts);
-
- SbPlayerSampleInfo sample_info = {
- sample_buffers[0], sample_buffer_sizes[0], sample_timestamp,
- video_sample_info ? video_sample_info : NULL,
- sample_drm_info ? sample_drm_info : NULL};
- player->WriteSample(sample_type, sample_info);
-}
-#endif // SB_API_VERSION < 10
diff --git a/src/starboard/shared/starboard/player/player_write_sample2.cc b/src/starboard/shared/starboard/player/player_write_sample2.cc
index 9bb9f3e..bec8b26 100644
--- a/src/starboard/shared/starboard/player/player_write_sample2.cc
+++ b/src/starboard/shared/starboard/player/player_write_sample2.cc
@@ -17,7 +17,6 @@
#include "starboard/common/log.h"
#include "starboard/shared/starboard/player/player_internal.h"
-#if SB_API_VERSION >= 10
void SbPlayerWriteSample2(SbPlayer player,
SbMediaType sample_type,
const SbPlayerSampleInfo* sample_infos,
@@ -35,4 +34,3 @@
player->WriteSample(sample_type, *sample_infos);
#endif // SB_API_VERSION >= 11
}
-#endif // SB_API_VERSION >= 10
diff --git a/src/starboard/shared/starboard/player/testdata/black_test_avc_1080p_30to60_fps.dmp.sha1 b/src/starboard/shared/starboard/player/testdata/black_test_avc_1080p_30to60_fps.dmp.sha1
new file mode 100644
index 0000000..e70a0d0
--- /dev/null
+++ b/src/starboard/shared/starboard/player/testdata/black_test_avc_1080p_30to60_fps.dmp.sha1
@@ -0,0 +1 @@
+eba2d4b5be46a273811f4fcbe9c3bae72bd65b37
\ No newline at end of file
diff --git a/src/starboard/shared/starboard/player/video_dmp_common.cc b/src/starboard/shared/starboard/player/video_dmp_common.cc
index 35b8e07..b7de2de 100644
--- a/src/starboard/shared/starboard/player/video_dmp_common.cc
+++ b/src/starboard/shared/starboard/player/video_dmp_common.cc
@@ -16,7 +16,6 @@
#include <limits>
-#if SB_HAS(PLAYER_FILTER_TESTS)
namespace starboard {
namespace shared {
namespace starboard {
@@ -289,4 +288,3 @@
} // namespace starboard
} // namespace shared
} // namespace starboard
-#endif // SB_HAS(PLAYER_FILTER_TESTS)
diff --git a/src/starboard/shared/starboard/player/video_dmp_common.h b/src/starboard/shared/starboard/player/video_dmp_common.h
index d1aa8fd..1353c6b 100644
--- a/src/starboard/shared/starboard/player/video_dmp_common.h
+++ b/src/starboard/shared/starboard/player/video_dmp_common.h
@@ -24,7 +24,6 @@
#include "starboard/memory.h"
#include "starboard/shared/internal_only.h"
-#if SB_HAS(PLAYER_FILTER_TESTS)
namespace starboard {
namespace shared {
namespace starboard {
@@ -174,5 +173,4 @@
} // namespace shared
} // namespace starboard
-#endif // SB_HAS(PLAYER_FILTER_TESTS)
#endif // STARBOARD_SHARED_STARBOARD_PLAYER_VIDEO_DMP_COMMON_H_
diff --git a/src/starboard/shared/starboard/player/video_dmp_reader.cc b/src/starboard/shared/starboard/player/video_dmp_reader.cc
index e4f1107..e8d3306 100644
--- a/src/starboard/shared/starboard/player/video_dmp_reader.cc
+++ b/src/starboard/shared/starboard/player/video_dmp_reader.cc
@@ -19,7 +19,6 @@
#include "starboard/shared/starboard/player/file_cache_reader.h"
-#if SB_HAS(PLAYER_FILTER_TESTS)
namespace starboard {
namespace shared {
namespace starboard {
@@ -262,4 +261,3 @@
} // namespace starboard
} // namespace shared
} // namespace starboard
-#endif // SB_HAS(PLAYER_FILTER_TESTS)
diff --git a/src/starboard/shared/starboard/player/video_dmp_reader.h b/src/starboard/shared/starboard/player/video_dmp_reader.h
index 563e03a..7333b8f 100644
--- a/src/starboard/shared/starboard/player/video_dmp_reader.h
+++ b/src/starboard/shared/starboard/player/video_dmp_reader.h
@@ -25,7 +25,6 @@
#include "starboard/shared/internal_only.h"
#include "starboard/shared/starboard/player/video_dmp_common.h"
-#if SB_HAS(PLAYER_FILTER_TESTS)
namespace starboard {
namespace shared {
namespace starboard {
@@ -141,5 +140,4 @@
} // namespace shared
} // namespace starboard
-#endif // SB_HAS(PLAYER_FILTER_TESTS)
#endif // STARBOARD_SHARED_STARBOARD_PLAYER_VIDEO_DMP_READER_H_
diff --git a/src/starboard/shared/starboard/player/video_dmp_writer.cc b/src/starboard/shared/starboard/player/video_dmp_writer.cc
index 4119604..22c89f4 100644
--- a/src/starboard/shared/starboard/player/video_dmp_writer.cc
+++ b/src/starboard/shared/starboard/player/video_dmp_writer.cc
@@ -24,7 +24,6 @@
#include "starboard/once.h"
#include "starboard/shared/starboard/application.h"
-#if SB_HAS(PLAYER_FILTER_TESTS)
namespace starboard {
namespace shared {
namespace starboard {
@@ -211,4 +210,3 @@
} // namespace starboard
} // namespace shared
} // namespace starboard
-#endif // SB_HAS(PLAYER_FILTER_TESTS)
diff --git a/src/starboard/shared/starboard/player/video_dmp_writer.h b/src/starboard/shared/starboard/player/video_dmp_writer.h
index 3255b68..fef0e10 100644
--- a/src/starboard/shared/starboard/player/video_dmp_writer.h
+++ b/src/starboard/shared/starboard/player/video_dmp_writer.h
@@ -22,7 +22,6 @@
#include "starboard/shared/starboard/player/input_buffer_internal.h"
#include "starboard/shared/starboard/player/video_dmp_common.h"
-#if SB_HAS(PLAYER_FILTER_TESTS)
namespace starboard {
namespace shared {
namespace starboard {
@@ -67,5 +66,4 @@
} // namespace shared
} // namespace starboard
-#endif // SB_HAS(PLAYER_FILTER_TESTS)
#endif // STARBOARD_SHARED_STARBOARD_PLAYER_VIDEO_DMP_WRITER_H_
diff --git a/src/starboard/shared/starboard/system_supports_resume.cc b/src/starboard/shared/starboard/system_supports_resume.cc
index d0dc340..822f960 100644
--- a/src/starboard/shared/starboard/system_supports_resume.cc
+++ b/src/starboard/shared/starboard/system_supports_resume.cc
@@ -14,10 +14,6 @@
#include "starboard/system.h"
-#if SB_API_VERSION >= 10
-
bool SbSystemSupportsResume() {
return true;
}
-
-#endif // SB_API_VERSION >= 10
diff --git a/src/starboard/shared/stub/atomic_public.h b/src/starboard/shared/stub/atomic_public.h
index ab97c05..68b5857 100644
--- a/src/starboard/shared/stub/atomic_public.h
+++ b/src/starboard/shared/stub/atomic_public.h
@@ -110,7 +110,6 @@
return 0;
}
-#if SB_API_VERSION >= 10
SB_C_FORCE_INLINE SbAtomic8
SbAtomicRelease_CompareAndSwap8(volatile SbAtomic8* ptr,
SbAtomic8 old_value,
@@ -132,7 +131,6 @@
SB_UNREFERENCED_PARAMETER(ptr);
return 0;
}
-#endif // SB_API_VERSION >= 10
// 64-bit atomic operations (only available on 64-bit processors).
#if SB_HAS(64_BIT_ATOMICS)
diff --git a/src/starboard/shared/stub/cryptography_create_transformer.cc b/src/starboard/shared/stub/cryptography_create_transformer.cc
index a0e64ab..ee81941 100644
--- a/src/starboard/shared/stub/cryptography_create_transformer.cc
+++ b/src/starboard/shared/stub/cryptography_create_transformer.cc
@@ -13,6 +13,9 @@
// limitations under the License.
#include "starboard/configuration.h"
+
+#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+
#include "starboard/cryptography.h"
SbCryptographyTransformer SbCryptographyCreateTransformer(
@@ -34,3 +37,5 @@
SB_UNREFERENCED_PARAMETER(key_size);
return kSbCryptographyInvalidTransformer;
}
+
+#endif // SB_CRYPTOAPI_DEPRECATED_VERSION
diff --git a/src/starboard/shared/stub/cryptography_destroy_transformer.cc b/src/starboard/shared/stub/cryptography_destroy_transformer.cc
index bfc9bea..79680c5 100644
--- a/src/starboard/shared/stub/cryptography_destroy_transformer.cc
+++ b/src/starboard/shared/stub/cryptography_destroy_transformer.cc
@@ -13,8 +13,13 @@
// limitations under the License.
#include "starboard/configuration.h"
+
+#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+
#include "starboard/cryptography.h"
void SbCryptographyDestroyTransformer(SbCryptographyTransformer transformer) {
SB_UNREFERENCED_PARAMETER(transformer);
}
+
+#endif // SB_CRYPTOAPI_DEPRECATED_VERSION
diff --git a/src/starboard/shared/stub/cryptography_get_tag.cc b/src/starboard/shared/stub/cryptography_get_tag.cc
index 13fb677..ff75ba3 100644
--- a/src/starboard/shared/stub/cryptography_get_tag.cc
+++ b/src/starboard/shared/stub/cryptography_get_tag.cc
@@ -13,6 +13,9 @@
// limitations under the License.
#include "starboard/configuration.h"
+
+#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+
#include "starboard/cryptography.h"
bool SbCryptographyGetTag(
@@ -24,3 +27,5 @@
SB_UNREFERENCED_PARAMETER(out_tag_size);
return false;
}
+
+#endif // SB_CRYPTOAPI_DEPRECATED_VERSION
diff --git a/src/starboard/shared/stub/cryptography_set_authenticated_data.cc b/src/starboard/shared/stub/cryptography_set_authenticated_data.cc
index e47ebe7..b6df57e 100644
--- a/src/starboard/shared/stub/cryptography_set_authenticated_data.cc
+++ b/src/starboard/shared/stub/cryptography_set_authenticated_data.cc
@@ -13,6 +13,9 @@
// limitations under the License.
#include "starboard/configuration.h"
+
+#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+
#include "starboard/cryptography.h"
bool SbCryptographySetAuthenticatedData(
@@ -24,3 +27,5 @@
SB_UNREFERENCED_PARAMETER(data_size);
return false;
}
+
+#endif // SB_CRYPTOAPI_DEPRECATED_VERSION
diff --git a/src/starboard/shared/stub/cryptography_set_initialization_vector.cc b/src/starboard/shared/stub/cryptography_set_initialization_vector.cc
index 36a7bfd..94c2485 100644
--- a/src/starboard/shared/stub/cryptography_set_initialization_vector.cc
+++ b/src/starboard/shared/stub/cryptography_set_initialization_vector.cc
@@ -13,6 +13,9 @@
// limitations under the License.
#include "starboard/configuration.h"
+
+#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+
#include "starboard/cryptography.h"
void SbCryptographySetInitializationVector(
@@ -23,3 +26,5 @@
SB_UNREFERENCED_PARAMETER(initialization_vector);
SB_UNREFERENCED_PARAMETER(initialization_vector_size);
}
+
+#endif // SB_CRYPTOAPI_DEPRECATED_VERSION
diff --git a/src/starboard/shared/stub/cryptography_transform.cc b/src/starboard/shared/stub/cryptography_transform.cc
index a96e40a..b6266e2 100644
--- a/src/starboard/shared/stub/cryptography_transform.cc
+++ b/src/starboard/shared/stub/cryptography_transform.cc
@@ -13,6 +13,9 @@
// limitations under the License.
#include "starboard/configuration.h"
+
+#if SB_API_VERSION < SB_CRYPTOAPI_DEPRECATED_VERSION
+
#include "starboard/cryptography.h"
int SbCryptographyTransform(SbCryptographyTransformer transformer,
@@ -25,3 +28,5 @@
SB_UNREFERENCED_PARAMETER(out_data);
return 0;
}
+
+#endif // SB_CRYPTOAPI_DEPRECATED_VERSION
diff --git a/src/starboard/shared/stub/drm_create_system.cc b/src/starboard/shared/stub/drm_create_system.cc
index 5d8628f..67cdc93 100644
--- a/src/starboard/shared/stub/drm_create_system.cc
+++ b/src/starboard/shared/stub/drm_create_system.cc
@@ -14,8 +14,6 @@
#include "starboard/drm.h"
-#if SB_API_VERSION >= 10
-
SbDrmSystem SbDrmCreateSystem(
const char* key_system,
void* context,
@@ -33,39 +31,3 @@
SB_UNREFERENCED_PARAMETER(session_closed_callback);
return kSbDrmSystemInvalid;
}
-
-#elif SB_HAS(DRM_SESSION_CLOSED)
-
-SbDrmSystem SbDrmCreateSystem(
- const char* key_system,
- void* context,
- SbDrmSessionUpdateRequestFunc update_request_callback,
- SbDrmSessionUpdatedFunc session_updated_callback,
- SbDrmSessionKeyStatusesChangedFunc key_statuses_changed_callback,
- SbDrmSessionClosedFunc session_closed_callback) {
- SB_UNREFERENCED_PARAMETER(context);
- SB_UNREFERENCED_PARAMETER(key_system);
- SB_UNREFERENCED_PARAMETER(update_request_callback);
- SB_UNREFERENCED_PARAMETER(session_updated_callback);
- SB_UNREFERENCED_PARAMETER(key_statuses_changed_callback);
- SB_UNREFERENCED_PARAMETER(session_closed_callback);
- return kSbDrmSystemInvalid;
-}
-
-#else // SB_HAS(DRM_SESSION_CLOSED)
-
-SbDrmSystem SbDrmCreateSystem(
- const char* key_system,
- void* context,
- SbDrmSessionUpdateRequestFunc update_request_callback,
- SbDrmSessionUpdatedFunc session_updated_callback,
- SbDrmSessionKeyStatusesChangedFunc key_statuses_changed_callback) {
- SB_UNREFERENCED_PARAMETER(context);
- SB_UNREFERENCED_PARAMETER(key_system);
- SB_UNREFERENCED_PARAMETER(update_request_callback);
- SB_UNREFERENCED_PARAMETER(session_updated_callback);
- SB_UNREFERENCED_PARAMETER(key_statuses_changed_callback);
- return kSbDrmSystemInvalid;
-}
-
-#endif // SB_HAS(DRM_SESSION_CLOSED)
diff --git a/src/starboard/shared/stub/drm_is_server_certificate_updatable.cc b/src/starboard/shared/stub/drm_is_server_certificate_updatable.cc
index 5e17c55..8169bd6 100644
--- a/src/starboard/shared/stub/drm_is_server_certificate_updatable.cc
+++ b/src/starboard/shared/stub/drm_is_server_certificate_updatable.cc
@@ -14,12 +14,8 @@
#include "starboard/drm.h"
-#if SB_API_VERSION >= 10
-
bool SbDrmIsServerCertificateUpdatable(SbDrmSystem drm_system) {
SB_UNREFERENCED_PARAMETER(drm_system);
return false;
}
-
-#endif // SB_API_VERSION >= 10
diff --git a/src/starboard/shared/stub/drm_update_server_certificate.cc b/src/starboard/shared/stub/drm_update_server_certificate.cc
index 3d25cd8..635b6ef 100644
--- a/src/starboard/shared/stub/drm_update_server_certificate.cc
+++ b/src/starboard/shared/stub/drm_update_server_certificate.cc
@@ -14,8 +14,6 @@
#include "starboard/drm.h"
-#if SB_API_VERSION >= 10
-
void SbDrmUpdateServerCertificate(SbDrmSystem drm_system,
int ticket,
const void* certificate,
@@ -25,5 +23,3 @@
SB_UNREFERENCED_PARAMETER(certificate);
SB_UNREFERENCED_PARAMETER(certificate_size);
}
-
-#endif // SB_API_VERSION >= 10
diff --git a/src/starboard/shared/stub/media_is_audio_supported.cc b/src/starboard/shared/stub/media_is_audio_supported.cc
index c8a199b..c180d4f 100644
--- a/src/starboard/shared/stub/media_is_audio_supported.cc
+++ b/src/starboard/shared/stub/media_is_audio_supported.cc
@@ -17,6 +17,9 @@
#include "starboard/media.h"
bool SbMediaIsAudioSupported(SbMediaAudioCodec /*audio_codec*/,
+#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+ const char* /*content_type*/,
+#endif // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
int64_t /*bitrate*/) {
return false;
}
diff --git a/src/starboard/shared/stub/media_is_video_supported.cc b/src/starboard/shared/stub/media_is_video_supported.cc
index 4ceead5..eaeb8ad 100644
--- a/src/starboard/shared/stub/media_is_video_supported.cc
+++ b/src/starboard/shared/stub/media_is_video_supported.cc
@@ -17,6 +17,9 @@
#include "starboard/media.h"
bool SbMediaIsVideoSupported(SbMediaVideoCodec /*video_codec*/,
+#if SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
+ const char* /*content_type*/,
+#endif // SB_API_VERSION >= SB_MEDIA_SUPPORT_QUERY_WITH_CONTENT_TYPE_VERSION
#if SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
int /*profile*/,
int /*level*/,
@@ -28,11 +31,7 @@
int /*frame_width*/,
int /*frame_height*/,
int64_t /*bitrate*/,
- int /*fps*/
-#if SB_API_VERSION >= 10
- ,
- bool /*decode_to_texture_required*/
-#endif // SB_API_VERSION >= 10
- ) {
+ int /*fps*/,
+ bool /*decode_to_texture_required*/) {
return false;
}
diff --git a/src/starboard/shared/stub/memory_protect.cc b/src/starboard/shared/stub/memory_protect.cc
index 036b8fb..99ca1e9 100644
--- a/src/starboard/shared/stub/memory_protect.cc
+++ b/src/starboard/shared/stub/memory_protect.cc
@@ -15,10 +15,8 @@
#include "starboard/configuration.h"
#include "starboard/memory.h"
-#if SB_API_VERSION >= 10
bool SbMemoryProtect(void* /*virtual_address*/,
int64_t /*size_bytes*/,
int /*flags*/) {
return false;
}
-#endif
diff --git a/src/starboard/shared/stub/player_create.cc b/src/starboard/shared/stub/player_create.cc
index ff11851..a5a905f 100644
--- a/src/starboard/shared/stub/player_create.cc
+++ b/src/starboard/shared/stub/player_create.cc
@@ -35,9 +35,6 @@
SbPlayer SbPlayerCreate(SbWindow /*window*/,
SbMediaVideoCodec /*video_codec*/,
SbMediaAudioCodec /*audio_codec*/,
-#if SB_API_VERSION < 10
- SbMediaTime /*duration_pts*/,
-#endif // SB_API_VERSION < 10
SbDrmSystem /*drm_system*/,
const SbMediaAudioSampleInfo* /*audio_sample_info*/,
#if SB_API_VERSION >= 11
diff --git a/src/starboard/shared/stub/player_get_info.cc b/src/starboard/shared/stub/player_get_info.cc
deleted file mode 100644
index 6f07066..0000000
--- a/src/starboard/shared/stub/player_get_info.cc
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2016 The Cobalt Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "starboard/player.h"
-
-#if SB_API_VERSION < 10
-void SbPlayerGetInfo(SbPlayer /*player*/, SbPlayerInfo* /*out_player_info*/) {}
-#endif // SB_API_VERSION < 10
diff --git a/src/starboard/shared/stub/player_get_info2.cc b/src/starboard/shared/stub/player_get_info2.cc
index 77c3603..4b443c1 100644
--- a/src/starboard/shared/stub/player_get_info2.cc
+++ b/src/starboard/shared/stub/player_get_info2.cc
@@ -14,7 +14,5 @@
#include "starboard/player.h"
-#if SB_API_VERSION >= 10
void SbPlayerGetInfo2(SbPlayer /*player*/, SbPlayerInfo2* /*out_player_info*/) {
}
-#endif // SB_API_VERSION >= 10
diff --git a/src/starboard/shared/stub/player_get_maximum_number_of_samples_per_write.cc b/src/starboard/shared/stub/player_get_maximum_number_of_samples_per_write.cc
index adb568e..ebba599 100644
--- a/src/starboard/shared/stub/player_get_maximum_number_of_samples_per_write.cc
+++ b/src/starboard/shared/stub/player_get_maximum_number_of_samples_per_write.cc
@@ -14,9 +14,7 @@
#include "starboard/player.h"
-#if SB_API_VERSION >= 10
int SbPlayerGetMaximumNumberOfSamplesPerWrite(SbPlayer /*player*/,
SbMediaType /*sample_type*/) {
return 0;
}
-#endif // SB_API_VERSION >= 10
diff --git a/src/starboard/shared/stub/player_seek.cc b/src/starboard/shared/stub/player_seek.cc
deleted file mode 100644
index c09a56a..0000000
--- a/src/starboard/shared/stub/player_seek.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2016 The Cobalt Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "starboard/player.h"
-
-#if SB_API_VERSION < 10
-void SbPlayerSeek(SbPlayer /*player*/,
- SbMediaTime /*seek_to_pts*/,
- int /*ticket*/) {}
-#endif // SB_API_VERSION < 10
diff --git a/src/starboard/shared/stub/player_seek2.cc b/src/starboard/shared/stub/player_seek2.cc
index be6cb32..23e4b82 100644
--- a/src/starboard/shared/stub/player_seek2.cc
+++ b/src/starboard/shared/stub/player_seek2.cc
@@ -14,8 +14,6 @@
#include "starboard/player.h"
-#if SB_API_VERSION >= 10
void SbPlayerSeek2(SbPlayer /*player*/,
SbTime /*seek_to_timestamp*/,
int /*ticket*/) {}
-#endif // SB_API_VERSION >= 10
diff --git a/src/starboard/shared/stub/player_write_sample.cc b/src/starboard/shared/stub/player_write_sample.cc
deleted file mode 100644
index 0fb7059..0000000
--- a/src/starboard/shared/stub/player_write_sample.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2016 The Cobalt Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "starboard/player.h"
-
-#if SB_API_VERSION < 10
-void SbPlayerWriteSample(SbPlayer /*player*/,
- SbMediaType /*sample_type*/,
- const void* const* /*sample_buffers*/,
- const int* /*sample_buffer_sizes*/,
- int /*number_of_sample_buffers*/,
- SbMediaTime /*sample_pts*/,
- const SbMediaVideoSampleInfo* /*video_sample_info*/,
- const SbDrmSampleInfo* /*sample_drm_info*/) {
-}
-#endif // SB_API_VERSION < 10
diff --git a/src/starboard/shared/stub/player_write_sample2.cc b/src/starboard/shared/stub/player_write_sample2.cc
index e5bdc7f..4ed00c4 100644
--- a/src/starboard/shared/stub/player_write_sample2.cc
+++ b/src/starboard/shared/stub/player_write_sample2.cc
@@ -14,9 +14,7 @@
#include "starboard/player.h"
-#if SB_API_VERSION >= 10
void SbPlayerWriteSample2(SbPlayer /*player*/,
SbMediaType /*sample_type*/,
const SbPlayerSampleInfo* /*sample_infos*/,
int /*number_of_sample_infos*/) {}
-#endif // SB_API_VERSION >= 10
diff --git a/src/starboard/shared/stub/system_supports_resume.cc b/src/starboard/shared/stub/system_supports_resume.cc
index d0dc340..822f960 100644
--- a/src/starboard/shared/stub/system_supports_resume.cc
+++ b/src/starboard/shared/stub/system_supports_resume.cc
@@ -14,10 +14,6 @@
#include "starboard/system.h"
-#if SB_API_VERSION >= 10
-
bool SbSystemSupportsResume() {
return true;
}
-
-#endif // SB_API_VERSION >= 10
diff --git a/src/starboard/shared/wayland/dev_input.cc b/src/starboard/shared/wayland/dev_input.cc
index 3cd3493..cc5a6b1 100644
--- a/src/starboard/shared/wayland/dev_input.cc
+++ b/src/starboard/shared/wayland/dev_input.cc
@@ -524,9 +524,7 @@
void DevInput::CreateKey(int key, int state, bool is_repeat) {
SbInputData* data = new SbInputData();
SbMemorySet(data, 0, sizeof(*data));
-#if SB_API_VERSION >= 10
data->timestamp = SbTimeGetMonotonicNow();
-#endif // SB_API_VERSION >= 10
data->window = window_;
data->type = (state == 0 ? kSbInputEventTypeUnpress : kSbInputEventTypePress);
data->device_type = kSbInputDeviceTypeRemote;
diff --git a/src/starboard/shared/widevine/drm_create_system.cc b/src/starboard/shared/widevine/drm_create_system.cc
index 595cf4d..0ceebdb 100644
--- a/src/starboard/shared/widevine/drm_create_system.cc
+++ b/src/starboard/shared/widevine/drm_create_system.cc
@@ -31,13 +31,9 @@
void* context,
SbDrmSessionUpdateRequestFunc update_request_callback,
SbDrmSessionUpdatedFunc session_updated_callback,
- SbDrmSessionKeyStatusesChangedFunc key_statuses_changed_callback
-#if SB_API_VERSION >= 10
- ,
+ SbDrmSessionKeyStatusesChangedFunc key_statuses_changed_callback,
SbDrmServerCertificateUpdatedFunc server_certificate_updated_callback,
- SbDrmSessionClosedFunc session_closed_callback
-#endif // SB_API_VERSION >= 10
- ) {
+ SbDrmSessionClosedFunc session_closed_callback) {
using starboard::shared::widevine::DrmSystemWidevine;
if (!update_request_callback || !session_updated_callback) {
return kSbDrmSystemInvalid;
@@ -45,29 +41,17 @@
if (!key_statuses_changed_callback) {
return kSbDrmSystemInvalid;
}
-#if SB_API_VERSION >= 10
if (!server_certificate_updated_callback || !session_closed_callback) {
return kSbDrmSystemInvalid;
}
-#endif // SB_API_VERSION >= 10
if (!DrmSystemWidevine::IsKeySystemSupported()) {
SB_DLOG(WARNING) << "Invalid key system " << key_system;
return kSbDrmSystemInvalid;
}
SB_LOG(ERROR) << "|company_name| and |model_name| are set to \"www\", "
<< "premium content playback resolution may be limited.";
- return new DrmSystemWidevine(context, update_request_callback,
- session_updated_callback
- ,
- key_statuses_changed_callback
-#if SB_API_VERSION >= 10
- ,
- server_certificate_updated_callback
-#endif // SB_API_VERSION >= 10
-#if SB_HAS(DRM_SESSION_CLOSED)
- ,
- session_closed_callback
-#endif // SB_HAS(DRM_SESSION_CLOSED)
- ,
- kCompanyName, kModelName);
+ return new DrmSystemWidevine(
+ context, update_request_callback, session_updated_callback,
+ key_statuses_changed_callback, server_certificate_updated_callback,
+ session_closed_callback, kCompanyName, kModelName);
}
diff --git a/src/starboard/shared/widevine/drm_system_widevine.cc b/src/starboard/shared/widevine/drm_system_widevine.cc
index 398b806..fb6b48e 100644
--- a/src/starboard/shared/widevine/drm_system_widevine.cc
+++ b/src/starboard/shared/widevine/drm_system_widevine.cc
@@ -204,28 +204,17 @@
void* context,
SbDrmSessionUpdateRequestFunc session_update_request_callback,
SbDrmSessionUpdatedFunc session_updated_callback,
- SbDrmSessionKeyStatusesChangedFunc key_statuses_changed_callback
-#if SB_API_VERSION >= 10
- ,
- SbDrmServerCertificateUpdatedFunc server_certificate_updated_callback
-#endif // SB_API_VERSION >= 10
-#if SB_HAS(DRM_SESSION_CLOSED)
- ,
- SbDrmSessionClosedFunc session_closed_callback
-#endif // SB_HAS(DRM_SESSION_CLOSED)
- ,
+ SbDrmSessionKeyStatusesChangedFunc key_statuses_changed_callback,
+ SbDrmServerCertificateUpdatedFunc server_certificate_updated_callback,
+ SbDrmSessionClosedFunc session_closed_callback,
const std::string& company_name,
const std::string& model_name)
: context_(context),
session_update_request_callback_(session_update_request_callback),
session_updated_callback_(session_updated_callback),
key_statuses_changed_callback_(key_statuses_changed_callback),
-#if SB_API_VERSION >= 10
server_certificate_updated_callback_(server_certificate_updated_callback),
-#endif // SB_API_VERSION >= 10
-#if SB_HAS(DRM_SESSION_CLOSED)
session_closed_callback_(session_closed_callback),
-#endif // SB_HAS(DRM_SESSION_CLOSED)
ticket_thread_id_(SbThreadGetId()) {
SB_DCHECK(!company_name.empty());
SB_DCHECK(!model_name.empty());
@@ -245,11 +234,7 @@
#endif // !defined(COBALT_BUILD_TYPE_GOLD)
EnsureWidevineCdmIsInitialized(company_name, model_name);
-#if SB_API_VERSION >= 10
const bool kEnablePrivacyMode = true;
-#else // SB_API_VERSION >= 10
- const bool kEnablePrivacyMode = false;
-#endif // SB_API_VERSION >= 10
cdm_.reset(wv3cdm::create(this, NULL, kEnablePrivacyMode));
SB_DCHECK(cdm_);
@@ -332,14 +317,9 @@
first_update_session_received_.store(true);
}
SB_DLOG(INFO) << "Update keys status " << status;
-#if SB_API_VERSION >= 10
session_updated_callback_(this, context_, ticket,
CdmStatusToSbDrmStatus(status), "",
sb_drm_session_id, sb_drm_session_id_size);
-#else // SB_API_VERSION >= 10
- session_updated_callback_(this, context_, ticket, sb_drm_session_id,
- sb_drm_session_id_size, status == wv3cdm::kSuccess);
-#endif // SB_API_VERSION >= 10
// It is possible that |key| actually contains a server certificate, in such
// case try to process the pending GenerateSessionUpdateRequest() calls.
@@ -355,13 +335,10 @@
if (succeeded) {
cdm_->close(wvcdm_session_id);
}
-#if SB_HAS(DRM_SESSION_CLOSED)
session_closed_callback_(this, context_, sb_drm_session_id,
sb_drm_session_id_size);
-#endif // SB_HAS(DRM_SESSION_CLOSED)
}
-#if SB_API_VERSION >= 10
void DrmSystemWidevine::UpdateServerCertificate(int ticket,
const void* certificate,
int certificate_size) {
@@ -375,7 +352,6 @@
server_certificate_updated_callback_(this, context_, ticket,
CdmStatusToSbDrmStatus(status), "");
}
-#endif // SB_API_VERSION >= 10
void IncrementIv(uint8_t* iv, size_t block_count) {
if (0 == block_count)
@@ -578,15 +554,14 @@
kSbDrmTicketInvalid);
SB_DLOG(ERROR) << "GenerateKeyRequest status " << status;
-// Send an empty request to signal an error.
-#if SB_API_VERSION >= 10
+ const char* session_id =
+ SbDrmTicketIsValid(ticket) ? NULL : kFirstSbDrmSessionId;
+ int session_id_size =
+ session_id ? static_cast<int>(SbStringGetLength(session_id)) : 0;
session_update_request_callback_(
this, context_, ticket, CdmStatusToSbDrmStatus(status),
- kSbDrmSessionRequestTypeLicenseRequest, "", NULL, 0, NULL, 0, NULL);
-#else // SB_API_VERSION >= 10
- session_update_request_callback_(this, context_, ticket, NULL, 0, NULL, 0,
- NULL);
-#endif // SB_API_VERSION >= 10
+ kSbDrmSessionRequestTypeLicenseRequest, "", session_id, session_id_size,
+ NULL, 0, NULL);
}
// When |status| is |kDeferred|, it indicates that the cdm requires
@@ -699,12 +674,10 @@
std::string DrmSystemWidevine::WvdmSessionIdToSbDrmSessionId(
const std::string& wvcdm_session_id) {
-#if SB_API_VERSION >= 10
SB_DCHECK(wvcdm_session_id != kFirstSbDrmSessionId);
if (wvcdm_session_id == first_wvcdm_session_id_) {
return kFirstSbDrmSessionId;
}
-#endif // SB_API_VERSION >= 10
return wvcdm_session_id;
}
@@ -715,12 +688,10 @@
SB_DCHECK(wvcdm_session_id);
const std::string str_sb_drm_session_id(
static_cast<const char*>(sb_drm_session_id), sb_drm_session_id_size);
-#if SB_API_VERSION >= 10
if (str_sb_drm_session_id == kFirstSbDrmSessionId) {
*wvcdm_session_id = first_wvcdm_session_id_;
return !first_wvcdm_session_id_.empty();
}
-#endif // SB_API_VERSION >= 10
*wvcdm_session_id = str_sb_drm_session_id;
return true;
}
@@ -737,14 +708,9 @@
kFirstSbDrmSessionId, message);
} else {
// Signals failure by sending NULL as the session id.
-#if SB_API_VERSION >= 10
session_update_request_callback_(
this, context_, ticket, CdmStatusToSbDrmStatus(status),
kSbDrmSessionRequestTypeLicenseRequest, "", NULL, 0, NULL, 0, NULL);
-#else // SB_API_VERSION >= 10
- session_update_request_callback_(this, context_, ticket, NULL, 0, NULL, 0,
- NULL);
-#endif // SB_API_VERSION >= 10
}
}
@@ -783,8 +749,6 @@
const std::string& message) {
int ticket = GetAndResetTicket(sb_drm_session_id);
-#if SB_API_VERSION >= 10
-
#if !defined(COBALT_BUILD_TYPE_GOLD)
if (number_of_session_updates_sent_ > maximum_number_of_session_updates_) {
SB_LOG(INFO) << "Number of drm sessions exceeds maximum allowed session"
@@ -802,12 +766,6 @@
this, context_, ticket, kSbDrmStatusSuccess, type, "",
sb_drm_session_id.c_str(), static_cast<int>(sb_drm_session_id.size()),
message.c_str(), static_cast<int>(message.size()), NULL);
-#else // SB_API_VERSION >= 10
- session_update_request_callback_(
- this, context_, ticket, sb_drm_session_id.c_str(),
- static_cast<int>(sb_drm_session_id.size()), message.c_str(),
- static_cast<int>(message.size()), NULL);
-#endif // SB_API_VERSION >= 10
}
} // namespace widevine
diff --git a/src/starboard/shared/widevine/drm_system_widevine.h b/src/starboard/shared/widevine/drm_system_widevine.h
index fb7bce7..c1a66a9 100644
--- a/src/starboard/shared/widevine/drm_system_widevine.h
+++ b/src/starboard/shared/widevine/drm_system_widevine.h
@@ -45,16 +45,9 @@
void* context,
SbDrmSessionUpdateRequestFunc update_request_callback,
SbDrmSessionUpdatedFunc session_updated_callback,
- SbDrmSessionKeyStatusesChangedFunc key_statuses_changed_callback
-#if SB_API_VERSION >= 10
- ,
- SbDrmServerCertificateUpdatedFunc server_certificate_updated_callback
-#endif // SB_API_VERSION >= 10
-#if SB_HAS(DRM_SESSION_CLOSED)
- ,
- SbDrmSessionClosedFunc session_closed_callback
-#endif // SB_HAS(DRM_SESSION_CLOSED)
- ,
+ SbDrmSessionKeyStatusesChangedFunc key_statuses_changed_callback,
+ SbDrmServerCertificateUpdatedFunc server_certificate_updated_callback,
+ SbDrmSessionClosedFunc session_closed_callback,
const std::string& company_name,
const std::string& model_name);
@@ -80,7 +73,6 @@
DecryptStatus Decrypt(InputBuffer* buffer) override;
-#if SB_API_VERSION >= 10
bool IsServerCertificateUpdatable() override { return true; }
// This function is called by the app to explicitly set the server
@@ -92,7 +84,6 @@
void UpdateServerCertificate(int ticket,
const void* certificate,
int certificate_size) override;
-#endif // SB_API_VERSION >= 10
private:
// Stores the data necessary to call GenerateSessionUpdateRequestInternal().
@@ -164,12 +155,8 @@
const SbDrmSessionUpdateRequestFunc session_update_request_callback_;
const SbDrmSessionUpdatedFunc session_updated_callback_;
const SbDrmSessionKeyStatusesChangedFunc key_statuses_changed_callback_;
-#if SB_API_VERSION >= 10
const SbDrmServerCertificateUpdatedFunc server_certificate_updated_callback_;
-#endif // SB_API_VERSION >= 10
-#if SB_HAS(DRM_SESSION_CLOSED)
const SbDrmSessionClosedFunc session_closed_callback_;
-#endif // SB_HAS(DRM_SESSION_CLOSED)
// Store a map from session id generated by the cdm to its associated ticket
// id. The ticket is a unique id passed to GenerateSessionUpdateRequest() to
@@ -194,11 +181,8 @@
std::string first_wvcdm_session_id_;
scoped_ptr<::widevine::Cdm> cdm_;
-#if SB_API_VERSION >= 10
+
bool is_server_certificate_set_ = false;
-#else // SB_API_VERSION >= 10
- bool is_server_certificate_set_ = true;
-#endif // SB_API_VERSION >= 10
volatile bool quitting_ = false;
diff --git a/src/starboard/shared/x11/application_x11.cc b/src/starboard/shared/x11/application_x11.cc
index 42376d4..07cfc1f 100644
--- a/src/starboard/shared/x11/application_x11.cc
+++ b/src/starboard/shared/x11/application_x11.cc
@@ -1144,9 +1144,7 @@
scoped_ptr<SbInputData> data(new SbInputData());
SbMemorySet(data.get(), 0, sizeof(*data));
-#if SB_API_VERSION >= 10
data->timestamp = SbTimeGetMonotonicNow();
-#endif // SB_API_VERSION >= 10
data->window = windows_[0];
SB_DCHECK(SbWindowIsValid(data->window));
data->type = paste_buffer_key_release_pending_ ? kSbInputEventTypeUnpress
@@ -1212,9 +1210,7 @@
scoped_ptr<SbInputData> data(new SbInputData());
SbMemorySet(data.get(), 0, sizeof(*data));
-#if SB_API_VERSION >= 10
data->timestamp = SbTimeGetMonotonicNow();
-#endif // SB_API_VERSION >= 10
data->window = FindWindow(x_key_event->window);
SB_DCHECK(SbWindowIsValid(data->window));
data->type = x_event->type == KeyPress ? kSbInputEventTypePress
@@ -1240,9 +1236,7 @@
}
scoped_ptr<SbInputData> data(new SbInputData());
SbMemorySet(data.get(), 0, sizeof(*data));
-#if SB_API_VERSION >= 10
data->timestamp = SbTimeGetMonotonicNow();
-#endif // SB_API_VERSION >= 10
data->window = FindWindow(x_button_event->window);
SB_DCHECK(SbWindowIsValid(data->window));
data->key = XButtonEventToSbKey(x_button_event);
@@ -1267,9 +1261,7 @@
XMotionEvent* x_motion_event = reinterpret_cast<XMotionEvent*>(x_event);
scoped_ptr<SbInputData> data(new SbInputData());
SbMemorySet(data.get(), 0, sizeof(*data));
-#if SB_API_VERSION >= 10
data->timestamp = SbTimeGetMonotonicNow();
-#endif // SB_API_VERSION >= 10
data->window = FindWindow(x_motion_event->window);
SB_DCHECK(SbWindowIsValid(data->window));
data->pressure = NAN;
diff --git a/src/starboard/starboard.syms b/src/starboard/starboard.syms
index a83a7ec..a684024 100644
--- a/src/starboard/starboard.syms
+++ b/src/starboard/starboard.syms
@@ -1,3 +1,4 @@
{
Sb*;
+ kSb*;
};
diff --git a/src/starboard/starboard_all.gyp b/src/starboard/starboard_all.gyp
index caf7e36..a8ab024 100644
--- a/src/starboard/starboard_all.gyp
+++ b/src/starboard/starboard_all.gyp
@@ -64,6 +64,7 @@
'<(DEPTH)/starboard/examples/blitter/blitter.gyp:*',
'<(DEPTH)/starboard/examples/window/window.gyp:*',
'<(DEPTH)/starboard/nplb/blitter_pixel_tests/blitter_pixel_tests.gyp:*',
+ '<(DEPTH)/starboard/nplb/nplb_evergreen_compat_tests/nplb_evergreen_compat_tests.gyp:*',
'<(DEPTH)/starboard/nplb/nplb.gyp:*',
'<(DEPTH)/starboard/starboard.gyp:*',
'<(DEPTH)/starboard/tools/tools.gyp:*',
@@ -85,7 +86,7 @@
}],
['sb_filter_based_player==1', {
'dependencies': [
- '<(DEPTH)/starboard/shared/starboard/player/filter/testing/player_filter_tests.gyp:*',
+ '<(DEPTH)/starboard/shared/starboard/player/filter/testing/player_filter_tests.gyp:player_filter_tests_deploy',
'<(DEPTH)/starboard/shared/starboard/player/filter/tools/tools.gyp:*',
],
}],
diff --git a/src/starboard/stub/BUILD.gn b/src/starboard/stub/BUILD.gn
index 32a6ec3..adda976 100644
--- a/src/starboard/stub/BUILD.gn
+++ b/src/starboard/stub/BUILD.gn
@@ -279,15 +279,12 @@
"//starboard/shared/stub/player_create.cc",
"//starboard/shared/stub/player_destroy.cc",
"//starboard/shared/stub/player_get_current_frame.cc",
- "//starboard/shared/stub/player_get_info.cc",
"//starboard/shared/stub/player_get_preferred_output_mode.cc",
"//starboard/shared/stub/player_output_mode_supported.cc",
- "//starboard/shared/stub/player_seek.cc",
"//starboard/shared/stub/player_set_bounds.cc",
"//starboard/shared/stub/player_set_playback_rate.cc",
"//starboard/shared/stub/player_set_volume.cc",
"//starboard/shared/stub/player_write_end_of_stream.cc",
- "//starboard/shared/stub/player_write_sample.cc",
"//starboard/shared/stub/socket_accept.cc",
"//starboard/shared/stub/socket_bind.cc",
"//starboard/shared/stub/socket_clear_last_error.cc",
diff --git a/src/starboard/stub/configuration_constants.cc b/src/starboard/stub/configuration_constants.cc
index cb8fbfe..ae91a87 100644
--- a/src/starboard/stub/configuration_constants.cc
+++ b/src/starboard/stub/configuration_constants.cc
@@ -55,9 +55,6 @@
// Specifies whether this platform updates audio frames asynchronously.
const bool kSbHasAsyncAudioFramesReporting = false;
-// Allow playing audioless video.
-const bool kSbHasAudiolessVideo = true;
-
// Specifies whether this platform has webm/vp9 support. This should be set to
// non-zero on platforms with webm/vp9 support.
const bool kSbHasMediaWebmVp9Support = false;
@@ -140,5 +137,10 @@
// The string form of SB_PATH_SEP_CHAR.
const char* kSbPathSepString = ":";
+// Specifies the preferred byte order of color channels in a pixel. Refer to
+// starboard/configuration.h for the possible values. EGL/GLES platforms should
+// generally prefer a byte order of RGBA, regardless of endianness.
+const int kSbPreferredRgbaByteOrder = SB_PREFERRED_RGBA_BYTE_ORDER_RGBA;
+
// The maximum number of users that can be signed in at the same time.
const uint32_t kSbUserMaxSignedIn = 1;
diff --git a/src/starboard/stub/configuration_public.h b/src/starboard/stub/configuration_public.h
index df4f29e..c339a86 100644
--- a/src/starboard/stub/configuration_public.h
+++ b/src/starboard/stub/configuration_public.h
@@ -204,11 +204,6 @@
// API. The basic requirement is a scaled, clipped, alpha-blended blit.
#define SB_HAS_BLITTER 0
-// Specifies the preferred byte order of color channels in a pixel. Refer to
-// starboard/configuration.h for the possible values. EGL/GLES platforms should
-// generally prefer a byte order of RGBA, regardless of endianness.
-#define SB_PREFERRED_RGBA_BYTE_ORDER SB_PREFERRED_RGBA_BYTE_ORDER_RGBA
-
// Indicates whether or not the given platform supports bilinear filtering.
// This can be checked to enable/disable renderer tests that verify that this is
// working properly.
@@ -220,6 +215,10 @@
#define SB_HAS_VIRTUAL_REALITY 1
+#ifndef COBALT_FORCE_STUB_RASTERIZER
+#define COBALT_FORCE_STUB_RASTERIZER 1
+#endif
+
// --- I/O Configuration -----------------------------------------------------
// Whether the current platform implements the on screen keyboard interface.
diff --git a/src/starboard/stub/gyp_configuration.gypi b/src/starboard/stub/gyp_configuration.gypi
index 1692859..88ea471 100644
--- a/src/starboard/stub/gyp_configuration.gypi
+++ b/src/starboard/stub/gyp_configuration.gypi
@@ -16,7 +16,6 @@
# Stub does not use a filter-based player.
'sb_filter_based_player': 0,
- 'target_arch': 'x64',
'target_os': 'linux',
# No GL drivers available.
diff --git a/src/starboard/stub/stub_sources.gypi b/src/starboard/stub/stub_sources.gypi
index 431269a..58b5737 100644
--- a/src/starboard/stub/stub_sources.gypi
+++ b/src/starboard/stub/stub_sources.gypi
@@ -150,18 +150,15 @@
'<(DEPTH)/starboard/shared/stub/player_create.cc',
'<(DEPTH)/starboard/shared/stub/player_destroy.cc',
'<(DEPTH)/starboard/shared/stub/player_get_current_frame.cc',
- '<(DEPTH)/starboard/shared/stub/player_get_info.cc',
'<(DEPTH)/starboard/shared/stub/player_get_info2.cc',
'<(DEPTH)/starboard/shared/stub/player_get_maximum_number_of_samples_per_write.cc',
'<(DEPTH)/starboard/shared/stub/player_get_preferred_output_mode.cc',
'<(DEPTH)/starboard/shared/stub/player_output_mode_supported.cc',
- '<(DEPTH)/starboard/shared/stub/player_seek.cc',
'<(DEPTH)/starboard/shared/stub/player_seek2.cc',
'<(DEPTH)/starboard/shared/stub/player_set_bounds.cc',
'<(DEPTH)/starboard/shared/stub/player_set_playback_rate.cc',
'<(DEPTH)/starboard/shared/stub/player_set_volume.cc',
'<(DEPTH)/starboard/shared/stub/player_write_end_of_stream.cc',
- '<(DEPTH)/starboard/shared/stub/player_write_sample.cc',
'<(DEPTH)/starboard/shared/stub/player_write_sample2.cc',
'<(DEPTH)/starboard/shared/stub/socket_accept.cc',
'<(DEPTH)/starboard/shared/stub/socket_bind.cc',
diff --git a/src/starboard/system.h b/src/starboard/system.h
index 544abf2..cc09fb5 100644
--- a/src/starboard/system.h
+++ b/src/starboard/system.h
@@ -55,12 +55,6 @@
// usable by Starboard applications.
kSbSystemPathFontConfigurationDirectory,
-#if SB_API_VERSION < 10
- // Deprecated and unused. Tests looking for static data should instead look
- // in the 'test' subdirectory of kSbSystemPathContentDirectory.
- kSbSystemPathSourceDirectory,
-#endif // SB_API_VERSION < 10
-
// Path to a directory where temporary files can be written.
kSbSystemPathTempDirectory,
@@ -130,21 +124,14 @@
// User-Agent, say.
kSbSystemPropertyPlatformName,
-#if SB_API_VERSION < 10
- // A universally-unique ID for the current user.
- kSbSystemPropertyPlatformUuid,
-#endif // SB_API_VERSION < 10
-
// The Google Speech API key. The platform manufacturer is responsible
// for registering a Google Speech API key for their products. In the API
// Console (http://developers.google.com/console), you can enable the
// Speech APIs and generate a Speech API key.
kSbSystemPropertySpeechApiKey,
-#if SB_API_VERSION >= 5
// A field that, if available, is appended to the user agent
kSbSystemPropertyUserAgentAuxField,
-#endif // SB_API_VERSION >= 5
} SbSystemPropertyId;
// Enumeration of device types.
@@ -203,14 +190,12 @@
// call.
kSbSystemCapabilityCanQueryGPUMemoryStats,
-#if SB_API_VERSION >= 10
// Whether this system sets the |timestamp| field of SbInputData. If the
// system does not set this field, then it will automatically be set; however,
// the relative time between input events likely will not be preserved, so
// time-related calculations (e.g. velocity for move events) will be
// incorrect.
kSbSystemCapabilitySetsInputTimestamp,
-#endif
// ATTENTION: Do not add more to this enum. Instead add an "IsSupported"
// function in the relevant module.
@@ -394,7 +379,6 @@
// |out_path|: The platform-defined system path specified by |path_id|.
// |path_length|: The length of the system path.
-// presubmit: allow sb_export mismatch
SB_EXPORT bool SbSystemGetPath(SbSystemPathId path_id,
char* out_path,
int path_length);
@@ -594,7 +578,6 @@
// from any thread and must be idempotent.
SB_EXPORT void SbSystemHideSplashScreen();
-#if SB_API_VERSION >= 10
// Returns false if the platform doesn't need resume after suspend support. In
// such case Cobalt will free up the resource it retains for resume after
// suspend.
@@ -603,7 +586,6 @@
// The return value of this function cannot change over the life time of the
// application.
SB_EXPORT bool SbSystemSupportsResume();
-#endif // SB_API_VERSION >= 10
#if SB_API_VERSION >= 11
// Returns pointer to a constant global struct implementing the extension named
diff --git a/src/starboard/testing/fake_graphics_context_provider.cc b/src/starboard/testing/fake_graphics_context_provider.cc
index 50ce274..5a851cf 100644
--- a/src/starboard/testing/fake_graphics_context_provider.cc
+++ b/src/starboard/testing/fake_graphics_context_provider.cc
@@ -237,7 +237,7 @@
EGLint context_attrib_list[] = {
EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE,
};
-#if defined(GLES3_SUPPORTED)
+#if SB_API_VERSION < SB_GLES3_DEPRECATED_VERSION && defined(GLES3_SUPPORTED)
// Attempt to create an OpenGL ES 3.0 context.
context_ = EGL_CALL_SIMPLE(eglCreateContext(
display_, config, EGL_NO_CONTEXT, context_attrib_list));
diff --git a/src/starboard/tools/media/create_sha1_from_dmp_files.py b/src/starboard/tools/media/create_sha1_from_dmp_files.py
index cafb926..456d077 100644
--- a/src/starboard/tools/media/create_sha1_from_dmp_files.py
+++ b/src/starboard/tools/media/create_sha1_from_dmp_files.py
@@ -31,10 +31,9 @@
def main(argv):
dmp_dir = argv[1]
- sha1 = hashlib.sha1()
- dmp_sha1_dir = os.path.join(dmp_dir, 'dmp_sha1_files')
- gs_dir = os.path.join(dmp_dir, 'gs_files')
+ dmp_sha1_dir = os.path.join(dmp_dir, "dmp_sha1_files")
+ gs_dir = os.path.join(dmp_dir, "gs_files")
if not os.path.exists(dmp_sha1_dir):
os.mkdir(dmp_sha1_dir)
@@ -43,25 +42,33 @@
for filename in os.listdir(dmp_dir):
_, ext = os.path.splitext(filename)
- if ext == '.dmp':
+ if ext == ".dmp":
+ print "*"
+ print "File: " + filename
# Compute the sha1 of the file
filepath = os.path.join(dmp_dir, filename)
- with open(filepath, 'rb') as filehandle:
+ with open(filepath, "rb") as filehandle:
+ sha1 = hashlib.sha1()
buf = filehandle.read(65536)
while buf:
sha1.update(buf)
buf = filehandle.read(65536)
sha1sum = sha1.hexdigest()
+ print "SHA1: " + sha1sum
+
# Rename the original DMP to its |SHA1| with no extension.
- shutil.copyfile(filepath, os.path.join(gs_dir, sha1sum))
+ gs_out = os.path.join(gs_dir, sha1sum)
+ shutil.copyfile(filepath, gs_out)
+ print "Copied \'" + filepath + "\' => \'" + gs_out + "\'"
# Create a new file with the |SHA1| of the DMP as its contents.
- dmp_sha1_filename = os.path.join(dmp_sha1_dir, filename + '.sha1')
- with open(dmp_sha1_filename, 'w') as dmp_sha1_file:
+ dmp_sha1_filename = os.path.join(dmp_sha1_dir, filename + ".sha1")
+ with open(dmp_sha1_filename, "w") as dmp_sha1_file:
dmp_sha1_file.write(sha1sum)
dmp_sha1_file.close()
+ print "Created \'" + dmp_sha1_filename + "\'"
-if __name__ == '__main__':
+if __name__ == "__main__":
sys.exit(main(sys.argv))
diff --git a/src/starboard/tools/testing/test_runner.py b/src/starboard/tools/testing/test_runner.py
index 512734d..9948bfe 100755
--- a/src/starboard/tools/testing/test_runner.py
+++ b/src/starboard/tools/testing/test_runner.py
@@ -239,6 +239,7 @@
self._loader_platform_config = build.GetPlatformConfig(loader_platform)
self._app_config = self._platform_config.GetApplicationConfiguration(
application_name)
+ self.application_name = application_name
self.dry_run = dry_run
self.xml_output_dir = xml_output_dir
self.log_xml_results = log_xml_results
@@ -335,11 +336,21 @@
def _GetTestFilters(self):
filters = self._platform_config.GetTestFilters()
- if not filters:
- filters = []
app_filters = self._app_config.GetTestFilters()
if app_filters:
filters.extend(app_filters)
+ # Regardless of our own platform, if we are Evergreen we also need to
+ # filter the tests that are filtered by the underlying platform. For
+ # example, the 'evergreen-arm-hardfp' needs to filter the 'raspi-2'
+ # filtered tests when it is running on a Raspberry Pi 2.
+ if self.loader_platform and self.loader_config:
+ loader_platform_config = build.GetPlatformConfig(self.loader_platform)
+ loader_app_config = loader_platform_config.GetApplicationConfiguration(
+ self.application_name)
+ for filter in (loader_platform_config.GetTestFilters() +
+ loader_app_config.GetTestFilters()):
+ if filter not in filters:
+ filters.append(filter)
return filters
def _GetAllTestEnvVariables(self):
diff --git a/src/starboard/tools/toolchain/bash.py b/src/starboard/tools/toolchain/bash.py
index 6f03589..1cd17c6 100644
--- a/src/starboard/tools/toolchain/bash.py
+++ b/src/starboard/tools/toolchain/bash.py
@@ -32,6 +32,8 @@
# whitelist common OK ones and quote anything else.
if re.match(r'^[a-zA-Z0-9_=.,\\/+-]+$', argument):
return argument # No quoting necessary.
+ if re.match(r'^--gcc-toolchain', argument):
+ return argument.replace("'", "'\"'\"'") # Do not surround with quotes
return "'" + argument.replace("'", "'\"'\"'") + "'"
def Join(self, command):
diff --git a/src/starboard/tools/toolchain/clangxx.py b/src/starboard/tools/toolchain/clangxx.py
index 22ba859..a1b6562 100644
--- a/src/starboard/tools/toolchain/clangxx.py
+++ b/src/starboard/tools/toolchain/clangxx.py
@@ -56,10 +56,16 @@
def __init__(self, **kwargs):
super(ExecutableLinker, self).__init__(**kwargs)
+ # Groups archives to be searched until all references are resolved.
+ self._write_group = kwargs.get('write_group', False)
def GetCommand(self, path, extra_flags, flags, shell):
del shell # Not used.
- return '{0} {1} {2} @$rspfile -o $out'.format(path, extra_flags, flags)
+ if self._write_group:
+ return ('{0} {1} {2} -Wl,--start-group @$rspfile -Wl,--end-group -o $out'
+ .format(path, extra_flags, flags))
+ else:
+ return '{0} {1} {2} @$rspfile -o $out'.format(path, extra_flags, flags)
class SharedLibraryLinker(DynamicLinkerBase, abstract.SharedLibraryLinker):