Import Cobalt 20.lts.2.234067
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id
index 5e3d559..8907972 100644
--- a/src/cobalt/build/build.id
+++ b/src/cobalt/build/build.id
@@ -1 +1 @@
-224508
\ No newline at end of file
+234067
\ No newline at end of file
diff --git a/src/cobalt/cssom/property_definitions.cc b/src/cobalt/cssom/property_definitions.cc
index 72d36ac..6a4db89 100644
--- a/src/cobalt/cssom/property_definitions.cc
+++ b/src/cobalt/cssom/property_definitions.cc
@@ -884,7 +884,7 @@
SetShorthandPropertyDefinition(kBorderRadiusProperty, "border-radius",
border_radius_longhand_properties);
- // https://www.w3.org/TR/css3-background/#border
+ // https://www.w3.org/TR/css-backgrounds-3/#propdef-border
LonghandPropertySet border_longhand_properties;
border_longhand_properties.insert(kBorderColorProperty);
border_longhand_properties.insert(kBorderStyleProperty);
diff --git a/src/cobalt/doc/net_log.md b/src/cobalt/doc/net_log.md
new file mode 100644
index 0000000..dfc3c98
--- /dev/null
+++ b/src/cobalt/doc/net_log.md
@@ -0,0 +1,30 @@
+# Cobalt NetLog
+
+Chromium has a very useful network diagnostic tool called the NetLog and Cobalt
+is hooked up to use it. It's the main tool to track network traffic and debug
+network code.
+
+### Activate the NetLog
+
+The following command line switch will activate the NetLog and store net log
+record to the specified location.
+`./cobalt --net_log=/PATH/TO/YOUR_NETLOG_NAME.json`
+The output json file will be stored at the file location you choose.
+
+
+### Read the NetLog records
+
+The produced json file is not human-friendly, use the
+[NetLog Viewer](https://netlog-viewer.appspot.com/#import)
+
+Cobalt's net_log can not enable some features in the web viewer, but all the
+network traffic is recorded in the event tab.
+
+
+### Add NetLog entries
+
+To Add NetLog entry, get the NetLog instance owned by NetworkModule to where you
+want to add entries and start/end your entry according to the NetLog interface.
+
+A NetLog object is created at each NetworkModule initialization and is passed
+into Chromium net through URLRequestContext.
diff --git a/src/cobalt/layout/flex_container_box.cc b/src/cobalt/layout/flex_container_box.cc
index bacd234..8bb4127 100644
--- a/src/cobalt/layout/flex_container_box.cc
+++ b/src/cobalt/layout/flex_container_box.cc
@@ -311,8 +311,11 @@
set_margin_right(maybe_margin_right.value_or(LayoutUnit()));
set_margin_top(maybe_margin_top.value_or(LayoutUnit()));
set_margin_bottom(maybe_margin_bottom.value_or(LayoutUnit()));
- if (child_boxes().empty()) {
- baseline_ = GetBorderBoxHeight();
+
+ UpdateRectOfPositionedChildBoxes(child_layout_params, layout_params);
+
+ if (items.empty()) {
+ baseline_ = GetPaddingBoxHeight() + border_bottom_width() + margin_bottom();
} else {
baseline_ = flex_formatting_context.GetBaseline();
}
@@ -480,8 +483,7 @@
}
AnonymousBlockBox* FlexContainerBox::GetLastChildAsAnonymousBlockBox() {
- return child_boxes().empty() ? NULL
- : child_boxes().back()->AsAnonymousBlockBox();
+ return NULL;
}
AnonymousBlockBox* FlexContainerBox::GetOrAddAnonymousBlockBox() {
diff --git a/src/cobalt/layout/flex_container_box.h b/src/cobalt/layout/flex_container_box.h
index a962d44..5e55ce2 100644
--- a/src/cobalt/layout/flex_container_box.h
+++ b/src/cobalt/layout/flex_container_box.h
@@ -15,6 +15,9 @@
#ifndef COBALT_LAYOUT_FLEX_CONTAINER_BOX_H_
#define COBALT_LAYOUT_FLEX_CONTAINER_BOX_H_
+#include <memory>
+
+#include "base/optional.h"
#include "cobalt/cssom/css_computed_style_declaration.h"
#include "cobalt/layout/base_direction.h"
#include "cobalt/layout/block_container_box.h"
diff --git a/src/cobalt/layout/flex_line.cc b/src/cobalt/layout/flex_line.cc
index 124099a..a55819f 100644
--- a/src/cobalt/layout/flex_line.cc
+++ b/src/cobalt/layout/flex_line.cc
@@ -358,7 +358,7 @@
// If the remaining free space is positive and at least one main-axis margin
// on this line is auto, distribute the free space equally among these
// margins.
- std::vector<bool> auto_margins(items_.size());
+ std::vector<bool> auto_margins(items_.size() * 2);
int auto_margin_count = 0;
int margin_idx = 0;
for (auto& item : items_) {
diff --git a/src/cobalt/layout/replaced_box.cc b/src/cobalt/layout/replaced_box.cc
index 3d2a447..ab107f5 100644
--- a/src/cobalt/layout/replaced_box.cc
+++ b/src/cobalt/layout/replaced_box.cc
@@ -366,8 +366,8 @@
if (IsAbsolutelyPositioned()) {
// TODO: Implement CSS section 10.3.8, see
// https://www.w3.org/TR/CSS21/visudet.html#abs-replaced-width.
- set_left(maybe_left.value_or(LayoutUnit()));
- set_top(maybe_top.value_or(LayoutUnit()));
+ set_left(maybe_left.value_or(LayoutUnit(GetStaticPositionLeft())));
+ set_top(maybe_top.value_or(LayoutUnit(GetStaticPositionTop())));
}
// Note that computed height may be "auto", even if it is specified as a
// percentage (depending on conditions of the containing block). See details
diff --git a/src/cobalt/layout_tests/testdata/css3-flexbox/absolutely-positioned-children-expected.png b/src/cobalt/layout_tests/testdata/css3-flexbox/absolutely-positioned-children-expected.png
new file mode 100644
index 0000000..cb33c85
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-flexbox/absolutely-positioned-children-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-flexbox/absolutely-positioned-children.html b/src/cobalt/layout_tests/testdata/css3-flexbox/absolutely-positioned-children.html
new file mode 100644
index 0000000..52e896a
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-flexbox/absolutely-positioned-children.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<!--
+ | Tests for CSS Flexible Box Layout Module.
+ | Testing absolutely positioned flex container children.
+ -->
+<html>
+<head>
+<style>
+ body {
+ margin: 0px;
+ font-family: Roboto;
+ background-color: gray;
+ font-size: 12px;
+ }
+ .flex {
+ display: inline-flex;
+ flex-flow: row wrap;
+ color: fuchsia;
+ background-color: yellow;
+ opacity: 0.75;
+ min-width: 400px;
+ min-height: 200px;
+ margin: 10px 20px 40px 30px;
+ border: solid white;
+ border-width: 10px 25px 25px 25px;
+ -no-position: relative;
+ -no-transform: translateX(0);
+ }
+ .absolute {
+ background-color: blue;
+ position: absolute;
+ }
+ .fixed {
+ background-color: purple;
+ position: fixed;
+ }
+ div > span {
+ padding: 1.25%;
+ border: 10px solid black;
+ }
+ div > video {
+ opacity: 1;
+ width: 5%;
+ height: 5%;
+ z-index: 1;
+ }
+</style>
+</head>
+<body>
+ -gh-
+ <div style="height: 5px; background-color: black;"></div>
+ <div style="display: inline-flex; width: 5px; height: 50px; background-color: black;"></div>
+ <span style="display: inline-block; width: 40px; background-color: lime;">-gh-</span>
+ <div class="flex">
+ <video class="absolute" style="top: 20%;"></video>
+ <video class="absolute" style="top: 30%; left: 0%;"></video>
+ <video class="absolute" style="left: 20%;"></video>
+ <video class="absolute" style="left: 30%; top: 0%;"></video>
+ <video class="fixed" style="top: 40%;"></video>
+ <video class="fixed" style="top: 50%; left: 0%;"></video>
+ <video class="fixed" style="left: 40%;"></video>
+ <video class="fixed" style="left: 50%; top: 0%;"></video>
+ <span class="absolute" style="top: 60%;"></span>
+ <span class="absolute" style="top: 70%; left: 0%;"></span>
+ <span class="absolute" style="left: 60%;"></span>
+ <span class="absolute" style="left: 70%; top: 0%;"></span>
+ <span class="fixed" style="top: 80%;"></span>
+ <span class="fixed" style="top: 90%; left: 0%;"></span>
+ <span class="fixed" style="left: 80%;"></span>
+ <span class="fixed" style="left: 90%; top: 0%"></span>
+ </div>
+ <div style="display: inline-flex; width: 5px; height: 50px; background-color: black;"></div>
+ <div style="height: 5px; background-color: black;"></div>
+ </body>
+</html>
diff --git a/src/cobalt/layout_tests/testdata/css3-flexbox/combined-baseline-expected.png b/src/cobalt/layout_tests/testdata/css3-flexbox/combined-baseline-expected.png
index 4afe5c9..b9b6c39 100644
--- a/src/cobalt/layout_tests/testdata/css3-flexbox/combined-baseline-expected.png
+++ b/src/cobalt/layout_tests/testdata/css3-flexbox/combined-baseline-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-flexbox/empty_container_baseline-expected.png b/src/cobalt/layout_tests/testdata/css3-flexbox/empty_container_baseline-expected.png
new file mode 100644
index 0000000..8b26646
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-flexbox/empty_container_baseline-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css3-flexbox/empty_container_baseline.html b/src/cobalt/layout_tests/testdata/css3-flexbox/empty_container_baseline.html
new file mode 100644
index 0000000..e605155
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-flexbox/empty_container_baseline.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<!--
+ | Tests for CSS Flexible Box Layout Module.
+ | Testing absolutely positioned flex container children.
+ -->
+<html>
+<head>
+<style>
+ body {
+ margin: 0px;
+ font-family: Roboto;
+ background-color: gray;
+ font-size: 36px;
+ }
+ .flex {
+ display: inline-flex;
+ flex-flow: row wrap;
+ color: fuchsia;
+ background-color: yellow;
+ opacity: 0.75;
+ min-width: 10px;
+ min-height: 10px;
+ border: solid white;
+ }
+ .absolute {
+ background-color: blue;
+ position: absolute;
+ }
+ .fixed {
+ background-color: purple;
+ position: fixed;
+ }
+ div > span {
+ padding: 1.25%;
+ border: 10px solid black;
+ }
+ div > video {
+ opacity: 1;
+ width: 5%;
+ height: 5%;
+ z-index: 1;
+ }
+ .margin-a {
+ margin: 6px 12px 24px 16px;
+ }
+ .margin-b {
+ margin: 24px 16px 6px 12px;
+ }
+ .border-a {
+ border-width: 6px 12px 12px 12px;
+ }
+ .border-b {
+ border-width: 12px 12px 5px 12px;
+ }
+</style>
+</head>
+<body>
+ -gh-
+ <div style="height: 5px; background-color: black;"></div>
+ <div style="display: inline-flex; width: 5px; height: 50px; background-color: black;"></div>
+ <span style="display: inline-block; width: 60px; background-color: lime">-gh- -gh-</span>
+ <div class="flex"></div>
+ <div class="flex margin-a"></div>
+ <div class="flex margin-b"></div>
+ <div class="flex border-a"></div>
+ <div class="flex border-b"></div>
+ <div class="flex margin-a border-a"></div>
+ <div class="flex margin-a border-b""></div>
+ <div class="flex margin-b border-a"></div>
+ <div class="flex margin-b border-b""></div>
+ <div style="display: inline-flex; width: 5px; height: 50px; background-color: black;"></div>
+ <div style="height: 5px; background-color: black;"></div>
+ </body>
+</html>
diff --git a/src/cobalt/layout_tests/testdata/css3-flexbox/layout_tests.txt b/src/cobalt/layout_tests/testdata/css3-flexbox/layout_tests.txt
index c8a34e8..26b3994 100644
--- a/src/cobalt/layout_tests/testdata/css3-flexbox/layout_tests.txt
+++ b/src/cobalt/layout_tests/testdata/css3-flexbox/layout_tests.txt
@@ -1,3 +1,4 @@
+absolutely-positioned-children
combined-baseline
combined-container-sizing-edge-cases
combined-order-and-multiline
@@ -133,5 +134,6 @@
csswg_flex-shrink-006
csswg_flex-shrink-007
csswg_flex-shrink-008
+empty_container_baseline
flex-items-flexibility
positioned-containers
diff --git a/src/cobalt/media/base/starboard_player.cc b/src/cobalt/media/base/starboard_player.cc
index 628898c..c41e9ac 100644
--- a/src/cobalt/media/base/starboard_player.cc
+++ b/src/cobalt/media/base/starboard_player.cc
@@ -337,6 +337,13 @@
base::TimeDelta* buffer_start_time, base::TimeDelta* buffer_length_time) {
DCHECK(buffer_start_time || buffer_length_time);
DCHECK(is_url_based_);
+
+ if (state_ == kSuspended) {
+ *buffer_start_time = base::TimeDelta();
+ *buffer_length_time = base::TimeDelta();
+ return;
+ }
+
DCHECK(SbPlayerIsValid(player_));
SbUrlPlayerExtraInfo url_player_info;
@@ -355,9 +362,16 @@
void StarboardPlayer::GetVideoResolution(int* frame_width, int* frame_height) {
DCHECK(frame_width);
DCHECK(frame_height);
- DCHECK(SbPlayerIsValid(player_));
DCHECK(is_url_based_);
+ if (state_ == kSuspended) {
+ *frame_width = video_sample_info_.frame_width;
+ *frame_height = video_sample_info_.frame_height;
+ return;
+ }
+
+ DCHECK(SbPlayerIsValid(player_));
+
SbPlayerInfo2 out_player_info;
SbPlayerGetInfo2(player_, &out_player_info);
diff --git a/src/cobalt/media/formats/mp4/mp4_stream_parser.cc b/src/cobalt/media/formats/mp4/mp4_stream_parser.cc
index e4d7754..391318b 100644
--- a/src/cobalt/media/formats/mp4/mp4_stream_parser.cc
+++ b/src/cobalt/media/formats/mp4/mp4_stream_parser.cc
@@ -287,6 +287,8 @@
sample_format = kSampleFormatU8;
} else if (entry.samplesize == 16) {
sample_format = kSampleFormatS16;
+ } else if (entry.samplesize == 24) {
+ sample_format = kSampleFormatS24;
} else if (entry.samplesize == 32) {
sample_format = kSampleFormatS32;
} else {
diff --git a/src/cobalt/media/player/web_media_player_impl.cc b/src/cobalt/media/player/web_media_player_impl.cc
index 6185a52..2a268ae 100644
--- a/src/cobalt/media/player/web_media_player_impl.cc
+++ b/src/cobalt/media/player/web_media_player_impl.cc
@@ -646,7 +646,8 @@
// Any error that occurs before reaching ReadyStateHaveMetadata should
// be considered a format error.
SetNetworkError(WebMediaPlayer::kNetworkStateFormatError,
- "Ready state have nothing.");
+ message.empty() ? "Ready state have nothing."
+ : "Ready state have nothing: " + message);
return;
}
diff --git a/src/cobalt/renderer/rasterizer/egl/render_tree_node_visitor.cc b/src/cobalt/renderer/rasterizer/egl/render_tree_node_visitor.cc
index 40c04a4..8d6e121 100644
--- a/src/cobalt/renderer/rasterizer/egl/render_tree_node_visitor.cc
+++ b/src/cobalt/renderer/rasterizer/egl/render_tree_node_visitor.cc
@@ -109,8 +109,13 @@
}
bool ImageNodeSupportedNatively(render_tree::ImageNode* image_node) {
+ // Ensure any required backend processing is done to create the necessary
+ // GPU resource. This must be done to verify whether the GPU resource can
+ // be rendered by the shader.
skia::Image* skia_image =
base::polymorphic_downcast<skia::Image*>(image_node->data().source.get());
+ skia_image->EnsureInitialized();
+
if (skia_image->GetTypeId() == base::GetTypeId<skia::MultiPlaneImage>()) {
skia::HardwareMultiPlaneImage* hardware_image =
base::polymorphic_downcast<skia::HardwareMultiPlaneImage*>(skia_image);
@@ -501,10 +506,6 @@
base::polymorphic_downcast<skia::Image*>(data.source.get());
bool is_opaque = skia_image->IsOpaque() && IsOpaque(draw_state_.opacity);
- // Ensure any required backend processing is done to create the necessary
- // GPU resource.
- skia_image->EnsureInitialized();
-
// Calculate matrix to transform texture coordinates according to the local
// transform.
math::Matrix3F texcoord_transform(math::Matrix3F::Identity());
diff --git a/src/cobalt/script/mozjs-45/mozjs_global_environment.h b/src/cobalt/script/mozjs-45/mozjs_global_environment.h
index 0bc4428..0aa069d 100644
--- a/src/cobalt/script/mozjs-45/mozjs_global_environment.h
+++ b/src/cobalt/script/mozjs-45/mozjs_global_environment.h
@@ -185,14 +185,17 @@
JSContext* context_;
int garbage_collection_count_;
WeakHeapObjectManager weak_object_manager_;
- std::unordered_map<Wrappable*, CountedHeapObject> kept_alive_objects_;
std::unique_ptr<ReferencedObjectMap> referenced_objects_;
- std::vector<InterfaceData> cached_interface_data_;
+ // Beware the order of destruction. Anything which references the JSContext
+ // should be destroyed before ~ContextDestructor.
ContextDestructor context_destructor_;
+
+ JS::Heap<JSObject*> global_object_proxy_;
std::unique_ptr<WrapperFactory> wrapper_factory_;
std::unique_ptr<MozjsScriptValueFactory> script_value_factory_;
- JS::Heap<JSObject*> global_object_proxy_;
+ std::vector<InterfaceData> cached_interface_data_;
+ std::unordered_map<Wrappable*, CountedHeapObject> kept_alive_objects_;
EnvironmentSettings* environment_settings_;
// TODO: Should be |std::unordered_set| once C++11 is enabled.
base::hash_set<Traceable*> visited_traceables_;
diff --git a/src/cobalt/script/mozjs-45/referenced_object_map.cc b/src/cobalt/script/mozjs-45/referenced_object_map.cc
index bceb6c4..b822336 100644
--- a/src/cobalt/script/mozjs-45/referenced_object_map.cc
+++ b/src/cobalt/script/mozjs-45/referenced_object_map.cc
@@ -29,6 +29,10 @@
ReferencedObjectMap::ReferencedObjectMap(JSContext* context)
: context_(context) {}
+ReferencedObjectMap::~ReferencedObjectMap() {
+ DCHECK(referenced_objects_.empty());
+}
+
// Add/Remove a reference from a WrapperPrivate to a JSValue.
void ReferencedObjectMap::AddReferencedObject(Wrappable* wrappable,
JS::HandleValue referee) {
diff --git a/src/cobalt/script/mozjs-45/referenced_object_map.h b/src/cobalt/script/mozjs-45/referenced_object_map.h
index 487f2db..134c515 100644
--- a/src/cobalt/script/mozjs-45/referenced_object_map.h
+++ b/src/cobalt/script/mozjs-45/referenced_object_map.h
@@ -32,6 +32,7 @@
class ReferencedObjectMap {
public:
explicit ReferencedObjectMap(JSContext* context);
+ ~ReferencedObjectMap();
void AddReferencedObject(Wrappable* wrappable, JS::HandleValue referee);
void RemoveReferencedObject(Wrappable* wrappable, JS::HandleValue referee);
diff --git a/src/cobalt/version.h b/src/cobalt/version.h
index cc3f61a..e8b74f9 100644
--- a/src/cobalt/version.h
+++ b/src/cobalt/version.h
@@ -35,6 +35,6 @@
// release is cut.
//.
-#define COBALT_VERSION "20.lts.1"
+#define COBALT_VERSION "20.lts.2"
#endif // COBALT_VERSION_H_
diff --git a/src/cobalt/xhr/xml_http_request.cc b/src/cobalt/xhr/xml_http_request.cc
index ed7f026..dc0c961 100644
--- a/src/cobalt/xhr/xml_http_request.cc
+++ b/src/cobalt/xhr/xml_http_request.cc
@@ -760,17 +760,22 @@
return;
}
}
- // Ensure all fetched data is read and transfered to this XHR.
- OnURLFetchDownloadProgress(source, 0, 0, 0);
- fetch_callback_.reset();
- fetch_mode_callback_.reset();
+
const net::URLRequestStatus& status = source->GetStatus();
if (status.is_success()) {
stop_timeout_ = true;
if (error_) {
+ // Ensure the fetch callbacks are reset when URL fetch is complete,
+ // regardless of error status.
+ fetch_callback_.reset();
+ fetch_mode_callback_.reset();
return;
}
+ // Ensure all fetched data is read and transfered to this XHR. This should
+ // only be done for successful and error-free fetches.
+ OnURLFetchDownloadProgress(source, 0, 0, 0);
+
// The request may have completed too quickly, before URLFetcher's upload
// progress timer had a chance to inform us upload is finished.
if (!upload_complete_ && upload_listener_) {
@@ -786,6 +791,9 @@
} else {
HandleRequestError(kNetworkError);
}
+
+ fetch_callback_.reset();
+ fetch_mode_callback_.reset();
}
// Reset some variables in case the XHR object is reused.
@@ -979,6 +987,7 @@
FireProgressEvent(this, base::Tokens::loadend());
fetch_callback_.reset();
+ fetch_mode_callback_.reset();
DecrementActiveRequests();
}
diff --git a/src/glimp/include/quad_drawer/helper.h b/src/glimp/include/quad_drawer/helper.h
deleted file mode 100644
index 7749fac..0000000
--- a/src/glimp/include/quad_drawer/helper.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2019 Google Inc. 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 QuadDrawer interface implementation.
-
-#ifndef GLIMP_INCLUDE_QUAD_DRAWER_HELPER_H_
-#define GLIMP_INCLUDE_QUAD_DRAWER_HELPER_H_
-
-#include "starboard/ps4/singleton.h"
-
-class QuadDrawerHelper : public starboard::ps4::Singleton<QuadDrawerHelper> {
- public:
- typedef enum color_range {
- kStudioRange = 0, // Y [16..235], UV [16..240]
- kFullRange = 1 // YUV/RGB [0..255]
- } color_range_t;
-
- typedef enum primary_id {
- kPrimaryBt709 = 0,
- kPrimaryBt2020 = 1
- } primary_id_t;
-
- struct QuadDrawerTarget {
- unsigned int x;
- unsigned int y;
- unsigned int width;
- unsigned int height;
- unsigned int display_width;
- unsigned int display_height;
- unsigned char* planes[3];
- int stride[3];
- unsigned int bit_depth;
- color_range_t color_range;
- primary_id_t primary;
- };
-
- using QuadDrawerCallBack = void(void* context, void* target);
-
- void SetCallBack(void* context, QuadDrawerCallBack* quad_drawer_callback);
- QuadDrawerTarget* GetTarget();
-
- private:
- QuadDrawerTarget quad_drawer_target_ = {};
- QuadDrawerCallBack* quad_drawer_callback_ = nullptr;
- void* context_ = nullptr;
-};
-
-#endif // GLIMP_INCLUDE_QUAD_DRAWER_HELPER_H_
diff --git a/src/net/socket/tcp_socket_starboard.cc b/src/net/socket/tcp_socket_starboard.cc
index 829a279..5964db6 100644
--- a/src/net/socket/tcp_socket_starboard.cc
+++ b/src/net/socket/tcp_socket_starboard.cc
@@ -198,7 +198,7 @@
// waiting for Accept() to succeed and 2. Peer address is unused in
// most use cases. Chromium implementations get the address from accept()
// directly, but Starboard API is incapable of that.
- LOG(WARNING) << "Could not get peer address for the server socket.";
+ DVLOG(1) << "Could not get peer address for the server socket.";
}
}
diff --git a/src/net/third_party/quic/platform/impl/quic_logging_impl.h b/src/net/third_party/quic/platform/impl/quic_logging_impl.h
index 4d2bc0d..0e7c18d 100644
--- a/src/net/third_party/quic/platform/impl/quic_logging_impl.h
+++ b/src/net/third_party/quic/platform/impl/quic_logging_impl.h
@@ -18,41 +18,25 @@
#define QUIC_LOG_IF_IMPL(severity, condition) \
QUIC_CHROMIUM_LOG_IF_##severity(condition)
-#if defined(STARBOARD)
-#define QUIC_CHROMIUM_LOG_INFO DLOG(INFO)
-#else
#define QUIC_CHROMIUM_LOG_INFO VLOG(1)
-#endif
#define QUIC_CHROMIUM_LOG_WARNING DLOG(WARNING)
#define QUIC_CHROMIUM_LOG_ERROR DLOG(ERROR)
#define QUIC_CHROMIUM_LOG_FATAL LOG(FATAL)
#define QUIC_CHROMIUM_LOG_DFATAL LOG(DFATAL)
-#if defined(STARBOARD)
-#define QUIC_CHROMIUM_DLOG_INFO DLOG(INFO)
-#else
#define QUIC_CHROMIUM_DLOG_INFO DVLOG(1)
-#endif
#define QUIC_CHROMIUM_DLOG_WARNING DLOG(WARNING)
#define QUIC_CHROMIUM_DLOG_ERROR DLOG(ERROR)
#define QUIC_CHROMIUM_DLOG_FATAL DLOG(FATAL)
#define QUIC_CHROMIUM_DLOG_DFATAL DLOG(DFATAL)
-#if defined(STARBOARD)
-#define QUIC_CHROMIUM_LOG_IF_INFO(condition) DLOG_IF(INFO, condition)
-#else
#define QUIC_CHROMIUM_LOG_IF_INFO(condition) VLOG_IF(1, condition)
-#endif
#define QUIC_CHROMIUM_LOG_IF_WARNING(condition) DLOG_IF(WARNING, condition)
#define QUIC_CHROMIUM_LOG_IF_ERROR(condition) DLOG_IF(ERROR, condition)
#define QUIC_CHROMIUM_LOG_IF_FATAL(condition) LOG_IF(FATAL, condition)
#define QUIC_CHROMIUM_LOG_IF_DFATAL(condition) LOG_IF(DFATAL, condition)
-#if defined(STARBOARD)
-#define QUIC_CHROMIUM_DLOG_IF_INFO(condition) DLOG_IF(INFO, condition)
-#else
#define QUIC_CHROMIUM_DLOG_IF_INFO(condition) DVLOG_IF(1, condition)
-#endif
#define QUIC_CHROMIUM_DLOG_IF_WARNING(condition) DLOG_IF(WARNING, condition)
#define QUIC_CHROMIUM_DLOG_IF_ERROR(condition) DLOG_IF(ERROR, condition)
#define QUIC_CHROMIUM_DLOG_IF_FATAL(condition) DLOG_IF(FATAL, condition)
@@ -70,11 +54,7 @@
#define QUIC_LOG_WARNING_IS_ON_IMPL() 1
#define QUIC_LOG_ERROR_IS_ON_IMPL() 1
#endif
-#if defined(STARBOARD) && !defined(NDEBUG)
-#define QUIC_DLOG_INFO_IS_ON_IMPL() 1
-#else
#define QUIC_DLOG_INFO_IS_ON_IMPL() 0
-#endif
#if defined(OS_WIN)
// wingdi.h defines ERROR to be 0. When we call QUIC_DLOG(ERROR), it gets
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/CobaltService.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/CobaltService.java
index 65e6dc8..e5a4254 100644
--- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/CobaltService.java
+++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/CobaltService.java
@@ -26,6 +26,9 @@
/** Get the name of the service. */
public String getServiceName();
}
+ /** Take in a reference to StarboardBridge & use it as needed. Default behavior is no-op. */
+ public void receiveStarboardBridge(StarboardBridge bridge) {}
+
// Lifecycle
/** Prepare service for start or resume. */
public abstract void beforeStartOrResume();
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java
index 49b37c0..85c7c56 100644
--- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java
+++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/StarboardBridge.java
@@ -525,6 +525,11 @@
return false;
}
+ /** Return the CobaltMediaSession. */
+ public CobaltMediaSession cobaltMediaSession() {
+ return cobaltMediaSession;
+ }
+
public void registerCobaltService(CobaltService.Factory factory) {
cobaltServiceFactories.put(factory.getServiceName(), factory);
}
@@ -550,6 +555,7 @@
}
CobaltService service = factory.createCobaltService(nativeService);
if (service != null) {
+ service.receiveStarboardBridge(this);
cobaltServices.put(serviceName, service);
}
return service;
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/VoiceRecognizer.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/VoiceRecognizer.java
index d9aba31..06cc02f 100644
--- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/VoiceRecognizer.java
+++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/coat/VoiceRecognizer.java
@@ -14,6 +14,8 @@
package dev.cobalt.coat;
+import static dev.cobalt.util.Log.TAG;
+
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
@@ -24,6 +26,7 @@
import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer;
import dev.cobalt.util.Holder;
+import dev.cobalt.util.Log;
import dev.cobalt.util.UsedByNative;
import java.util.ArrayList;
@@ -175,7 +178,12 @@
}
private void reset() {
- speechRecognizer.destroy();
+ try {
+ speechRecognizer.destroy();
+ } catch (IllegalArgumentException ex) {
+ // Soft handling
+ Log.e(TAG, "Error in speechRecognizer.destroy()!", ex);
+ }
speechRecognizer = null;
nativeSpeechRecognizerImpl = 0;
diff --git a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/CobaltMediaSession.java b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/CobaltMediaSession.java
index fcc31b1..ae511c9 100644
--- a/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/CobaltMediaSession.java
+++ b/src/starboard/android/apk/app/src/main/java/dev/cobalt/media/CobaltMediaSession.java
@@ -84,9 +84,17 @@
private static final String[] PLAYBACK_STATE_NAME = {"playing", "paused", "none"};
// Accessed on the main looper thread only.
- private int playbackState = PLAYBACK_STATE_NONE;
+ private int currentPlaybackState = PLAYBACK_STATE_NONE;
private boolean transientPause = false;
private boolean suspended = true;
+ private boolean explicitUserActionRequired = false;
+
+ /** LifecycleCallback to notify listeners when |mediaSession| becomes active or inactive. */
+ public interface LifecycleCallback {
+ void onMediaSessionLifecycle(boolean isActive, MediaSessionCompat.Token token);
+ }
+
+ private LifecycleCallback lifecycleCallback = null;
public CobaltMediaSession(
Context context, Holder<Activity> activityHolder, UpdateVolumeListener volumeListener) {
@@ -98,7 +106,16 @@
setMediaSession();
}
+ public void setLifecycleCallback(LifecycleCallback lifecycleCallback) {
+ this.lifecycleCallback = lifecycleCallback;
+ if (lifecycleCallback != null) {
+ lifecycleCallback.onMediaSessionLifecycle(
+ this.mediaSession.isActive(), this.mediaSession.getSessionToken());
+ }
+ }
+
private void setMediaSession() {
+ Log.i(TAG, "MediaSession new");
mediaSession = new MediaSessionCompat(context, TAG);
mediaSession.setFlags(MEDIA_SESSION_FLAG_HANDLES_TRANSPORT_CONTROLS);
mediaSession.setCallback(
@@ -106,6 +123,7 @@
@Override
public void onFastForward() {
Log.i(TAG, "MediaSession action: FAST FORWARD");
+ explicitUserActionRequired = false;
nativeInvokeAction(PlaybackStateCompat.ACTION_FAST_FORWARD);
}
@@ -118,30 +136,35 @@
@Override
public void onPlay() {
Log.i(TAG, "MediaSession action: PLAY");
+ explicitUserActionRequired = false;
nativeInvokeAction(PlaybackStateCompat.ACTION_PLAY);
}
@Override
public void onRewind() {
Log.i(TAG, "MediaSession action: REWIND");
+ explicitUserActionRequired = false;
nativeInvokeAction(PlaybackStateCompat.ACTION_REWIND);
}
@Override
public void onSkipToNext() {
Log.i(TAG, "MediaSession action: SKIP NEXT");
+ explicitUserActionRequired = false;
nativeInvokeAction(PlaybackStateCompat.ACTION_SKIP_TO_NEXT);
}
@Override
public void onSkipToPrevious() {
Log.i(TAG, "MediaSession action: SKIP PREVIOUS");
+ explicitUserActionRequired = false;
nativeInvokeAction(PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS);
}
@Override
public void onSeekTo(long pos) {
Log.i(TAG, "MediaSession action: SEEK " + pos);
+ explicitUserActionRequired = false;
nativeInvokeAction(PlaybackStateCompat.ACTION_SEEK_TO, pos);
}
@@ -164,8 +187,10 @@
}
/**
- * Sets system media resources active or not according to whether media is playing. This is
- * idempotent as it may be called multiple times during the course of a media session.
+ * Sets system media resources active or not according to whether media is playing. The concept of
+ * "media focus" encapsulates wake lock, audio focus and active media session so that all three
+ * are set together to stay coherent as playback state changes. This is idempotent as it may be
+ * called multiple times during the course of a media session.
*/
private void configureMediaFocus(int playbackState) {
checkMainLooperThread();
@@ -186,8 +211,13 @@
setMediaSession();
}
mediaSession.setActive(playbackState != PLAYBACK_STATE_NONE);
+ if (lifecycleCallback != null) {
+ lifecycleCallback.onMediaSessionLifecycle(
+ this.mediaSession.isActive(), this.mediaSession.getSessionToken());
+ }
if (deactivating) {
// Suspending lands here.
+ Log.i(TAG, "MediaSession release");
mediaSession.release();
}
}
@@ -268,7 +298,7 @@
// fall through
case AudioManager.AUDIOFOCUS_LOSS:
Log.i(TAG, "Audiofocus loss" + logExtra);
- if (playbackState == PLAYBACK_STATE_PLAYING) {
+ if (currentPlaybackState == PLAYBACK_STATE_PLAYING) {
Log.i(TAG, "Audiofocus action: PAUSE");
nativeInvokeAction(PlaybackStateCompat.ACTION_PAUSE);
}
@@ -285,7 +315,7 @@
// The app has been granted audio focus (again). Raise volume to normal,
// restart playback if necessary.
volumeListener.onUpdateVolume(1.0f);
- if (transientPause && playbackState == PLAYBACK_STATE_PAUSED) {
+ if (transientPause && currentPlaybackState == PLAYBACK_STATE_PAUSED) {
Log.i(TAG, "Audiofocus action: PLAY");
nativeInvokeAction(PlaybackStateCompat.ACTION_PLAY);
}
@@ -295,6 +325,9 @@
// Keep track of whether we're currently paused because of a transient loss of audiofocus.
transientPause = (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT);
+ // To restart playback after permanent loss, the user must take an explicit action.
+ // See: https://developer.android.com/guide/topics/media-apps/audio-focus
+ explicitUserActionRequired = (focusChange == AudioManager.AUDIOFOCUS_LOSS);
}
private AudioManager getAudioManager() {
@@ -315,17 +348,21 @@
checkMainLooperThread();
suspended = false;
// Undoing what may have been done in suspendInternal().
- configureMediaFocus(playbackState);
+ configureMediaFocus(currentPlaybackState);
}
public void suspend() {
- mainHandler.post(
- new Runnable() {
- @Override
- public void run() {
- suspendInternal();
- }
- });
+ if (Looper.getMainLooper() == Looper.myLooper()) {
+ suspendInternal();
+ } else {
+ mainHandler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ suspendInternal();
+ }
+ });
+ }
}
private void suspendInternal() {
@@ -339,9 +376,9 @@
// it's in a playing state. We'll configure it again in resumeInternal() and the HTML5 app will
// be none the wiser.
playbackStateBuilder.setState(
- playbackState,
+ currentPlaybackState,
PlaybackStateCompat.PLAYBACK_POSITION_UNKNOWN,
- playbackState == PLAYBACK_STATE_PLAYING ? 1.0f : 0.0f);
+ currentPlaybackState == PLAYBACK_STATE_PLAYING ? 1.0f : 0.0f);
configureMediaFocus(PLAYBACK_STATE_NONE);
}
@@ -384,9 +421,10 @@
final long duration) {
checkMainLooperThread();
+ boolean hasStateChange = this.currentPlaybackState != playbackState;
// Always keep track of what the HTML5 app thinks the playback state is so we can configure the
// media focus correctly, either immediately or when resuming from being suspended.
- this.playbackState = playbackState;
+ this.currentPlaybackState = playbackState;
// Don't update anything while suspended.
if (suspended) {
@@ -394,7 +432,25 @@
return;
}
- configureMediaFocus(playbackState);
+ if (hasStateChange) {
+ if (playbackState == PLAYBACK_STATE_PLAYING) {
+ // We don't want to request media focus if |explicitUserActionRequired| is true when we
+ // don't have window focus. Ideally, we should recognize user action to re-request audio
+ // focus if |explicitUserActionRequired| is true. Currently we're not able to recognize
+ // it. But if we don't have window focus, we know the user is not interacting with our app
+ // and we should not request media focus.
+ if (!explicitUserActionRequired || activityHolder.get().hasWindowFocus()) {
+ explicitUserActionRequired = false;
+ configureMediaFocus(playbackState);
+ } else {
+ Log.w(TAG, "Audiofocus action: PAUSE (explicit user action required)");
+ nativeInvokeAction(PlaybackStateCompat.ACTION_PAUSE);
+ }
+ } else {
+ // It's fine to abandon media focus anytime.
+ configureMediaFocus(playbackState);
+ }
+ }
// Ignore updates to the MediaSession metadata if playback is stopped.
if (playbackState == PLAYBACK_STATE_NONE) {
diff --git a/src/starboard/android/shared/application_android.cc b/src/starboard/android/shared/application_android.cc
index 8b411b0..cae801e 100644
--- a/src/starboard/android/shared/application_android.cc
+++ b/src/starboard/android/shared/application_android.cc
@@ -249,7 +249,8 @@
}
break;
case AndroidCommand::kNativeWindowDestroyed:
- env->CallStarboardVoidMethodOrAbort("beforeSuspend", "()V");
+ // No need to JNI call StarboardBridge.beforeSuspend() since we did it
+ // early in SendAndroidCommand().
{
ScopedLock lock(android_command_mutex_);
// Cobalt can't keep running without a window, even if the Activity
@@ -331,6 +332,14 @@
void ApplicationAndroid::SendAndroidCommand(AndroidCommand::CommandType type,
void* data) {
SB_LOG(INFO) << "Send Android command: " << AndroidCommandName(type);
+ if (type == AndroidCommand::kNativeWindowDestroyed) {
+ // When this command is processed it will suspend Cobalt, so make the JNI
+ // call to StarboardBridge.beforeSuspend() early while still here on the
+ // Android main thread. This lets the MediaSession get released now without
+ // having to wait to bounce between threads.
+ JniEnvExt* env = JniEnvExt::Get();
+ env->CallStarboardVoidMethodOrAbort("beforeSuspend", "()V");
+ }
AndroidCommand cmd {type, data};
ScopedLock lock(android_command_mutex_);
write(android_command_writefd_, &cmd, sizeof(cmd));
diff --git a/src/starboard/android/shared/gyp_configuration.py b/src/starboard/android/shared/gyp_configuration.py
index 8fc3c9b..8d973cb 100644
--- a/src/starboard/android/shared/gyp_configuration.py
+++ b/src/starboard/android/shared/gyp_configuration.py
@@ -290,4 +290,9 @@
# the following tests depend upon.
'VideoDecoderTests/VideoDecoderTest.ThreeMoreDecoders/*',
],
+ 'nplb': [
+ # This test is failing because localhost is not defined for IPv6 in
+ # /etc/hosts.
+ 'SbSocketAddressTypes/SbSocketResolveTest.Localhost/1',
+ ],
}
diff --git a/src/starboard/android/shared/media_codec_bridge.cc b/src/starboard/android/shared/media_codec_bridge.cc
index 01ed2e3..398f3b5 100644
--- a/src/starboard/android/shared/media_codec_bridge.cc
+++ b/src/starboard/android/shared/media_codec_bridge.cc
@@ -245,14 +245,6 @@
env->DeleteGlobalRef(j_media_codec_bridge_);
j_media_codec_bridge_ = NULL;
- SB_DCHECK(j_reused_dequeue_input_result_);
- env->DeleteGlobalRef(j_reused_dequeue_input_result_);
- j_reused_dequeue_input_result_ = NULL;
-
- SB_DCHECK(j_reused_dequeue_output_result_);
- env->DeleteGlobalRef(j_reused_dequeue_output_result_);
- j_reused_dequeue_output_result_ = NULL;
-
SB_DCHECK(j_reused_get_output_format_result_);
env->DeleteGlobalRef(j_reused_get_output_format_result_);
j_reused_get_output_format_result_ = NULL;
@@ -402,17 +394,6 @@
JniEnvExt* env = JniEnvExt::Get();
SB_DCHECK(env->GetObjectRefType(j_media_codec_bridge_) == JNIGlobalRefType);
- j_reused_dequeue_input_result_ = env->NewObjectOrAbort(
- "dev/cobalt/media/MediaCodecBridge$DequeueInputResult", "()V");
- SB_DCHECK(j_reused_dequeue_input_result_);
- j_reused_dequeue_input_result_ =
- env->ConvertLocalRefToGlobalRef(j_reused_dequeue_input_result_);
-
- j_reused_dequeue_output_result_ = env->NewObjectOrAbort(
- "dev/cobalt/media/MediaCodecBridge$DequeueOutputResult", "()V");
- SB_DCHECK(j_reused_dequeue_output_result_);
- j_reused_dequeue_output_result_ =
- env->ConvertLocalRefToGlobalRef(j_reused_dequeue_output_result_);
j_reused_get_output_format_result_ = env->NewObjectOrAbort(
"dev/cobalt/media/MediaCodecBridge$GetOutputFormatResult", "()V");
diff --git a/src/starboard/android/shared/media_codec_bridge.h b/src/starboard/android/shared/media_codec_bridge.h
index 23ddf8a..0329f06 100644
--- a/src/starboard/android/shared/media_codec_bridge.h
+++ b/src/starboard/android/shared/media_codec_bridge.h
@@ -110,7 +110,6 @@
~MediaCodecBridge();
- DequeueInputResult DequeueInputBuffer(jlong timeout_us);
// It is the responsibility of the client to manage the lifetime of the
// jobject that |GetInputBuffer| returns.
jobject GetInputBuffer(jint index);
@@ -124,7 +123,6 @@
const SbDrmSampleInfo& drm_sample_info,
jlong presentation_time_microseconds);
- DequeueOutputResult DequeueOutputBuffer(jlong timeout_us);
// It is the responsibility of the client to manage the lifetime of the
// jobject that |GetOutputBuffer| returns.
jobject GetOutputBuffer(jint index);
@@ -159,8 +157,6 @@
// playback. We mitigate this by reusing these output objects between calls
// to |DequeueInputBuffer|, |DequeueOutputBuffer|, and
// |GetOutputDimensions|.
- jobject j_reused_dequeue_input_result_ = NULL;
- jobject j_reused_dequeue_output_result_ = NULL;
jobject j_reused_get_output_format_result_ = NULL;
SB_DISALLOW_COPY_AND_ASSIGN(MediaCodecBridge);
diff --git a/src/starboard/android/shared/media_decoder.cc b/src/starboard/android/shared/media_decoder.cc
index fe757cc..482b6a8 100644
--- a/src/starboard/android/shared/media_decoder.cc
+++ b/src/starboard/android/shared/media_decoder.cc
@@ -466,8 +466,15 @@
is_output_restricted_ = true;
drm_system_->OnInsufficientOutputProtection();
} else {
- error_cb_(kSbPlayerErrorDecode,
- FormatString("%s failed with status %d.", action_name, status));
+ if (media_type_ == kSbMediaTypeAudio) {
+ error_cb_(kSbPlayerErrorDecode,
+ FormatString("%s failed with status %d (audio).", action_name,
+ status));
+ } else {
+ error_cb_(kSbPlayerErrorDecode,
+ FormatString("%s failed with status %d (video).", action_name,
+ status));
+ }
}
if (retry) {
@@ -489,7 +496,15 @@
<< " error with message: " << diagnostic_info;
if (!is_transient) {
- error_cb_(kSbPlayerErrorDecode, "OnMediaCodecError");
+ if (media_type_ == kSbMediaTypeAudio) {
+ error_cb_(kSbPlayerErrorDecode,
+ "OnMediaCodecError (audio): " + diagnostic_info +
+ (is_recoverable ? ", recoverable " : ", unrecoverable "));
+ } else {
+ error_cb_(kSbPlayerErrorDecode,
+ "OnMediaCodecError (video): " + diagnostic_info +
+ (is_recoverable ? ", recoverable " : ", unrecoverable "));
+ }
}
}
diff --git a/src/starboard/linux/shared/media_is_video_supported.cc b/src/starboard/linux/shared/media_is_video_supported.cc
index dcb89b9..7c59b66 100644
--- a/src/starboard/linux/shared/media_is_video_supported.cc
+++ b/src/starboard/linux/shared/media_is_video_supported.cc
@@ -53,7 +53,7 @@
SB_UNREFERENCED_PARAMETER(level);
if (!IsSDRVideo(bit_depth, primary_id, transfer_id, matrix_id)) {
- if (bit_depth != 10) {
+ if (bit_depth != 10 && bit_depth != 12) {
return false;
}
if (video_codec != kSbMediaVideoCodecAv1 &&
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 53a5d3f..d2ba6f7 100644
--- a/src/starboard/linux/x64x11/blittergles/sbversion/10/configuration_public.h
+++ b/src/starboard/linux/x64x11/blittergles/sbversion/10/configuration_public.h
@@ -18,6 +18,9 @@
#ifndef STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_10_CONFIGURATION_PUBLIC_H_
#define STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_10_CONFIGURATION_PUBLIC_H_
+#undef SB_API_VERSION
+#define SB_API_VERSION 10
+
#include "starboard/linux/x64x11/blittergles/configuration_public.h"
#endif // STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_10_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/11/configuration_public.h b/src/starboard/linux/x64x11/blittergles/sbversion/11/configuration_public.h
index 55cf0ba..561cb2b 100644
--- a/src/starboard/linux/x64x11/blittergles/sbversion/11/configuration_public.h
+++ b/src/starboard/linux/x64x11/blittergles/sbversion/11/configuration_public.h
@@ -18,6 +18,9 @@
#ifndef STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_11_CONFIGURATION_PUBLIC_H_
#define STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_11_CONFIGURATION_PUBLIC_H_
+#undef SB_API_VERSION
+#define SB_API_VERSION 11
+
#include "starboard/linux/x64x11/blittergles/configuration_public.h"
#endif // STARBOARD_LINUX_X64X11_BLITTERGLES_SBVERSION_11_CONFIGURATION_PUBLIC_H_
diff --git a/src/starboard/linux/x64x11/blittergles/sbversion/6/configuration_public.h b/src/starboard/linux/x64x11/blittergles/sbversion/6/configuration_public.h
index e73676b..678695d 100644
--- a/src/starboard/linux/x64x11/blittergles/sbversion/6/configuration_public.h
+++ b/src/starboard/linux/x64x11/blittergles/sbversion/6/configuration_public.h
@@ -18,6 +18,9 @@
#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
+
#include "starboard/linux/x64x11/blittergles/configuration_public.h"
#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
index 6930874..228c1ba 100644
--- a/src/starboard/linux/x64x11/blittergles/sbversion/6/gyp_configuration.py
+++ b/src/starboard/linux/x64x11/blittergles/sbversion/6/gyp_configuration.py
@@ -20,7 +20,7 @@
class LinuxX64X11BlitterglesSbversion6Configuration(
- parent_configuration.LinuxX64X11Configuration('linux-x64x11-blittergles')):
+ parent_configuration.LinuxX64X11Configuration):
def GetVariables(self, config_name):
variables = super(LinuxX64X11BlitterglesSbversion6Configuration,
@@ -35,5 +35,5 @@
def CreatePlatformConfig():
- return parent_configuration.LinuxX64X11Configuration(
+ return LinuxX64X11BlitterglesSbversion6Configuration(
'linux-x64x11-blittergles-sbversion-6')
diff --git a/src/starboard/shared/blittergles/blitter_create_default_device.cc b/src/starboard/shared/blittergles/blitter_create_default_device.cc
index 8435118..41bb497 100644
--- a/src/starboard/shared/blittergles/blitter_create_default_device.cc
+++ b/src/starboard/shared/blittergles/blitter_create_default_device.cc
@@ -15,6 +15,7 @@
#include "starboard/blitter.h"
#include <EGL/egl.h>
+#include <sanitizer/lsan_interface.h>
#include <memory>
@@ -96,13 +97,27 @@
SbBlitterDestroySurface(dummy_surface);
}
+#if defined ADDRESS_SANITIZER
+
+class ScopedLeakSanitizerDisabler {
+ public:
+ ScopedLeakSanitizerDisabler() { __lsan_disable(); }
+ ~ScopedLeakSanitizerDisabler() { __lsan_enable(); }
+};
+#define ANNOTATE_SCOPED_MEMORY_LEAK \
+ ScopedLeakSanitizerDisabler leak_sanitizer_disabler; static_cast<void>(0)
+
+#else
+
+#define ANNOTATE_SCOPED_MEMORY_LEAK ((void)0)
+
+#endif
} // namespace
SbBlitterDevice SbBlitterCreateDefaultDevice() {
starboard::shared::blittergles::SbBlitterDeviceRegistry* device_registry =
starboard::shared::blittergles::GetBlitterDeviceRegistry();
starboard::ScopedLock lock(device_registry->mutex);
-
if (device_registry->default_device) {
SB_DLOG(ERROR) << ": Default device has already been created.";
return kSbBlitterInvalidDevice;
@@ -115,9 +130,14 @@
return kSbBlitterInvalidDevice;
}
- if (!eglInitialize(device->display, NULL, NULL)) {
- SB_DLOG(ERROR) << ": Failed to initialize device.";
- return kSbBlitterInvalidDevice;
+ {
+ // Despite eglTerminate() being used in SbBlitterDestroyDevice(), the
+ // current mesa egl drivers still leak memory.
+ ANNOTATE_SCOPED_MEMORY_LEAK;
+ if (!eglInitialize(device->display, NULL, NULL)) {
+ SB_DLOG(ERROR) << ": Failed to initialize device.";
+ return kSbBlitterInvalidDevice;
+ }
}
starboard::optional<EGLConfig> config = GetEGLConfig(device->display);
diff --git a/src/starboard/shared/libaom/aom_video_decoder.cc b/src/starboard/shared/libaom/aom_video_decoder.cc
index f75f816..f2caac4 100644
--- a/src/starboard/shared/libaom/aom_video_decoder.cc
+++ b/src/starboard/shared/libaom/aom_video_decoder.cc
@@ -240,7 +240,8 @@
}
}
- if (aom_image->bit_depth != 8 && aom_image->bit_depth != 10) {
+ if (aom_image->bit_depth != 8 && aom_image->bit_depth != 10 &&
+ aom_image->bit_depth != 12) {
SB_DLOG(ERROR) << "Unsupported bit depth " << aom_image->bit_depth;
ReportError(
FormatString("Unsupported bit depth %d.", aom_image->bit_depth));
diff --git a/src/starboard/shared/libde265/de265_video_decoder.cc b/src/starboard/shared/libde265/de265_video_decoder.cc
index 13db895..619f962 100644
--- a/src/starboard/shared/libde265/de265_video_decoder.cc
+++ b/src/starboard/shared/libde265/de265_video_decoder.cc
@@ -249,7 +249,7 @@
int strides[kImagePlanes];
auto bit_depth = de265_get_bits_per_pixel(image, 0);
- if (bit_depth != 8 && bit_depth != 10) {
+ if (bit_depth != 8 && bit_depth != 10 && bit_depth != 12) {
SB_DLOG(ERROR) << "Unsupported bit depth " << bit_depth;
ReportError(FormatString("Unsupported bit depth %d.", bit_depth));
return;
diff --git a/src/starboard/shared/libvpx/vpx_video_decoder.cc b/src/starboard/shared/libvpx/vpx_video_decoder.cc
index 1a1029b..9cb5253 100644
--- a/src/starboard/shared/libvpx/vpx_video_decoder.cc
+++ b/src/starboard/shared/libvpx/vpx_video_decoder.cc
@@ -238,7 +238,8 @@
}
}
- if (vpx_image->bit_depth != 8 && vpx_image->bit_depth != 10) {
+ if (vpx_image->bit_depth != 8 && vpx_image->bit_depth != 10 &&
+ vpx_image->bit_depth != 12) {
SB_DLOG(ERROR) << "Unsupported bit depth " << vpx_image->bit_depth;
ReportError(
FormatString("Unsupported bit depth %d.", vpx_image->bit_depth));
diff --git a/src/starboard/shared/starboard/decode_target/decode_target_context_runner.h b/src/starboard/shared/starboard/decode_target/decode_target_context_runner.h
index 012eb23..4d3bcee 100644
--- a/src/starboard/shared/starboard/decode_target/decode_target_context_runner.h
+++ b/src/starboard/shared/starboard/decode_target/decode_target_context_runner.h
@@ -30,6 +30,10 @@
SbDecodeTargetGraphicsContextProvider* provider);
void RunOnGlesContext(std::function<void()> function);
+ SbDecodeTargetGraphicsContextProvider* context_provider() const {
+ return provider_;
+ }
+
private:
SbDecodeTargetGraphicsContextProvider* provider_;
};
diff --git a/src/starboard/shared/starboard/media/media_util.cc b/src/starboard/shared/starboard/media/media_util.cc
index 50a26ac..03bbdfa 100644
--- a/src/starboard/shared/starboard/media/media_util.cc
+++ b/src/starboard/shared/starboard/media/media_util.cc
@@ -115,15 +115,19 @@
std::string eotf = mime_type.GetParamStringValue("eotf", "");
if (!eotf.empty()) {
- SB_LOG_IF(WARNING, transfer_id != kSbMediaTransferIdUnspecified)
- << "transfer_id " << transfer_id << " set by the codec string \""
- << codec << "\" will be overwritten by the eotf attribute " << eotf;
- transfer_id = GetTransferIdFromString(eotf);
+ SbMediaTransferId transfer_id_from_eotf = GetTransferIdFromString(eotf);
// If the eotf is not known, reject immediately - without checking with
// the platform.
- if (transfer_id == kSbMediaTransferIdUnknown) {
+ if (transfer_id_from_eotf == kSbMediaTransferIdUnknown) {
return false;
}
+ if (transfer_id != kSbMediaTransferIdUnspecified &&
+ transfer_id != transfer_id_from_eotf) {
+ SB_LOG_IF(WARNING, transfer_id != kSbMediaTransferIdUnspecified)
+ << "transfer_id " << transfer_id << " set by the codec string \""
+ << codec << "\" will be overwritten by the eotf attribute " << eotf;
+ }
+ transfer_id = transfer_id_from_eotf;
#if !SB_HAS(MEDIA_IS_VIDEO_SUPPORTED_REFINEMENT)
if (!SbMediaIsTransferCharacteristicsSupported(transfer_id)) {
return false;
@@ -222,17 +226,20 @@
}
if (primary_id != kSbMediaPrimaryIdBt709 &&
- primary_id != kSbMediaPrimaryIdUnspecified) {
+ primary_id != kSbMediaPrimaryIdUnspecified &&
+ primary_id != kSbMediaPrimaryIdSmpte170M) {
return false;
}
if (transfer_id != kSbMediaTransferIdBt709 &&
- transfer_id != kSbMediaTransferIdUnspecified) {
+ transfer_id != kSbMediaTransferIdUnspecified &&
+ transfer_id != kSbMediaTransferIdSmpte170M) {
return false;
}
if (matrix_id != kSbMediaMatrixIdBt709 &&
- matrix_id != kSbMediaMatrixIdUnspecified) {
+ matrix_id != kSbMediaMatrixIdUnspecified &&
+ matrix_id != kSbMediaMatrixIdSmpte170M) {
return false;
}
diff --git a/src/starboard/shared/starboard/player/filter/cpu_video_frame.cc b/src/starboard/shared/starboard/player/filter/cpu_video_frame.cc
index 1d79355..3aecfd4 100644
--- a/src/starboard/shared/starboard/player/filter/cpu_video_frame.cc
+++ b/src/starboard/shared/starboard/player/filter/cpu_video_frame.cc
@@ -77,10 +77,21 @@
return s_clamp_table[component + 512];
}
-void Copy10bitsPlane(uint8_t* destination, const uint8_t* source, int pixels) {
+void CopyPlane(int bit_depth,
+ uint8_t* destination,
+ const uint8_t* source,
+ int pixels) {
+ if (bit_depth == 8) {
+ SbMemoryCopy(destination, source, pixels);
+ return;
+ }
+ SB_DCHECK(bit_depth == 10 || bit_depth == 12);
+
+ const int conversion_factor = 1 << (bit_depth - 8);
+
const uint16_t* source_in_uint16 = reinterpret_cast<const uint16_t*>(source);
while (pixels > 0) {
- *destination = static_cast<uint8_t>(*source_in_uint16 / 4);
+ *destination = static_cast<uint8_t>(*source_in_uint16 / conversion_factor);
++source_in_uint16;
++destination;
--pixels;
@@ -174,7 +185,7 @@
const uint8_t* y,
const uint8_t* u,
const uint8_t* v) {
- SB_DCHECK(bit_depth == 8 || bit_depth == 10);
+ SB_DCHECK(bit_depth == 8 || bit_depth == 10 || bit_depth == 12);
scoped_refptr<CpuVideoFrame> frame(new CpuVideoFrame(timestamp));
frame->format_ = kYV12;
@@ -182,7 +193,7 @@
frame->height_ = height;
auto destination_pitch_in_bytes = source_pitch_in_bytes;
- if (bit_depth == 10) {
+ if (bit_depth == 10 || bit_depth == 12) {
// Reduce destination pitch to half as it will be converted into 8 bits.
destination_pitch_in_bytes /= 2;
}
@@ -200,21 +211,13 @@
frame->pixel_buffer_.reset(
new uint8_t[y_plane_size_in_bytes + uv_plane_size_in_bytes * 2]);
- if (bit_depth == 8) {
- SbMemoryCopy(frame->pixel_buffer_.get(), y, y_plane_size_in_bytes);
- SbMemoryCopy(frame->pixel_buffer_.get() + y_plane_size_in_bytes, u,
- uv_plane_size_in_bytes);
- SbMemoryCopy(frame->pixel_buffer_.get() + y_plane_size_in_bytes +
- uv_plane_size_in_bytes,
- v, uv_plane_size_in_bytes);
- } else {
- Copy10bitsPlane(frame->pixel_buffer_.get(), y, y_plane_size_in_bytes);
- Copy10bitsPlane(frame->pixel_buffer_.get() + y_plane_size_in_bytes, u,
- uv_plane_size_in_bytes);
- Copy10bitsPlane(frame->pixel_buffer_.get() + y_plane_size_in_bytes +
- uv_plane_size_in_bytes,
- v, uv_plane_size_in_bytes);
- }
+ CopyPlane(bit_depth, frame->pixel_buffer_.get(), y, y_plane_size_in_bytes);
+ CopyPlane(bit_depth, frame->pixel_buffer_.get() + y_plane_size_in_bytes, u,
+ uv_plane_size_in_bytes);
+ CopyPlane(bit_depth,
+ frame->pixel_buffer_.get() + y_plane_size_in_bytes +
+ uv_plane_size_in_bytes,
+ v, uv_plane_size_in_bytes);
frame->planes_.push_back(Plane(width, height, destination_pitch_in_bytes,
frame->pixel_buffer_.get()));
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 6f5593e..ea3a192 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
@@ -493,9 +493,14 @@
}
SbDecodeTarget FilterBasedPlayerWorkerHandler::GetCurrentDecodeTarget() {
- ::starboard::ScopedLock lock(video_renderer_existence_mutex_);
- return video_renderer_ ? video_renderer_->GetCurrentDecodeTarget()
- : kSbDecodeTargetInvalid;
+ SbDecodeTarget decode_target = kSbDecodeTargetInvalid;
+ if (video_renderer_existence_mutex_.AcquireTry()) {
+ if (video_renderer_) {
+ decode_target = video_renderer_->GetCurrentDecodeTarget();
+ }
+ video_renderer_existence_mutex_.Release();
+ }
+ return decode_target;
}
MediaTimeProvider* FilterBasedPlayerWorkerHandler::GetMediaTimeProvider()
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 0c4634a..717eec3 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
@@ -26,7 +26,9 @@
const GetRefreshRateFn& get_refresh_rate_fn)
: get_refresh_rate_fn_(get_refresh_rate_fn) {
if (get_refresh_rate_fn_) {
- SB_LOG(INFO) << "VideoRenderAlgorithmImpl will render with cadence control";
+ SB_LOG(INFO) << "VideoRenderAlgorithmImpl will render with cadence control "
+ << "with display refresh rate set at "
+ << get_refresh_rate_fn_();
}
}
@@ -154,6 +156,12 @@
return;
}
+ auto refresh_rate = get_refresh_rate_fn_();
+ SB_DCHECK(refresh_rate >= 1);
+ if (refresh_rate < 1) {
+ refresh_rate = 60;
+ }
+
bool is_audio_playing;
bool is_audio_eos_played;
bool is_underflow;
@@ -165,28 +173,38 @@
frame_rate_estimate_.Update(*frames);
auto frame_rate = frame_rate_estimate_.frame_rate();
SB_DCHECK(frame_rate != VideoFrameRateEstimator::kInvalidFrameRate);
- cadence_pattern_generator_.UpdateRefreshRateAndMaybeReset(
- get_refresh_rate_fn_());
+ cadence_pattern_generator_.UpdateRefreshRateAndMaybeReset(refresh_rate);
cadence_pattern_generator_.UpdateFrameRate(frame_rate);
SB_DCHECK(cadence_pattern_generator_.has_cadence());
- if (current_frame_rendered_times_ >=
- cadence_pattern_generator_.GetNumberOfTimesCurrentFrameDisplays()) {
- frames->pop_front();
- cadence_pattern_generator_.AdvanceToNextFrame();
- break;
- }
-
auto second_iter = frames->begin();
++second_iter;
- if ((*second_iter)->is_end_of_stream() ||
- (*second_iter)->timestamp() > media_time) {
+ if ((*second_iter)->is_end_of_stream()) {
break;
}
auto frame_duration =
- static_cast<SbTime>(kSbTimeSecond / get_refresh_rate_fn_());
+ static_cast<SbTime>(kSbTimeSecond / refresh_rate);
+
+ if (current_frame_rendered_times_ >=
+ cadence_pattern_generator_.GetNumberOfTimesCurrentFrameDisplays()) {
+ if (current_frame_rendered_times_ == 0) {
+ ++dropped_frames_;
+ }
+ frames->pop_front();
+ cadence_pattern_generator_.AdvanceToNextFrame();
+ current_frame_rendered_times_ = 0;
+ if (cadence_pattern_generator_.GetNumberOfTimesCurrentFrameDisplays()
+ == 0) {
+ continue;
+ }
+ if (frames->front()->timestamp() <= media_time - frame_duration) {
+ continue;
+ }
+ break;
+ }
+
if ((*second_iter)->timestamp() > media_time - frame_duration) {
break;
}
diff --git a/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc b/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc
index 396d832..0eae09d 100644
--- a/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc
+++ b/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc
@@ -318,8 +318,19 @@
{
ScopedLock scoped_lock_decoder_frames(decoder_frames_mutex_);
sink_frames_mutex_.Acquire();
- sink_frames_.insert(sink_frames_.end(), decoder_frames_.begin(),
- decoder_frames_.end());
+ for (auto decoder_frame : decoder_frames_) {
+ if (sink_frames_.empty()) {
+ sink_frames_.push_back(decoder_frame);
+ continue;
+ }
+ if (sink_frames_.back()->is_end_of_stream()) {
+ continue;
+ }
+ if (decoder_frame->is_end_of_stream() ||
+ decoder_frame->timestamp() > sink_frames_.back()->timestamp()) {
+ sink_frames_.push_back(decoder_frame);
+ }
+ }
decoder_frames_.clear();
}
size_t number_of_sink_frames = sink_frames_.size();
diff --git a/src/starboard/starboard_all.gyp b/src/starboard/starboard_all.gyp
index a5b3291..76bb448 100644
--- a/src/starboard/starboard_all.gyp
+++ b/src/starboard/starboard_all.gyp
@@ -66,6 +66,7 @@
'<(DEPTH)/starboard/nplb/blitter_pixel_tests/blitter_pixel_tests.gyp:*',
'<(DEPTH)/starboard/nplb/nplb.gyp:*',
'<(DEPTH)/starboard/starboard.gyp:*',
+ '<(DEPTH)/starboard/tools/tools.gyp:*',
],
'conditions': [
['gl_type != "none"', {
diff --git a/src/starboard/tools/app_launcher_packager.py b/src/starboard/tools/app_launcher_packager.py
index 092b387..9be2843 100644
--- a/src/starboard/tools/app_launcher_packager.py
+++ b/src/starboard/tools/app_launcher_packager.py
@@ -1,5 +1,3 @@
-#!/usr/bin/python
-#
# Copyright 2017 The Cobalt Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -21,54 +19,21 @@
that the app launcher can be run independent of the Cobalt source tree.
"""
-
-################################################################################
-# API #
-################################################################################
-
-
-def CopyAppLauncherTools(repo_root, dest_root,
- additional_glob_patterns=None,
- include_black_box_tests=True):
- """Copies app launcher related files to the destination root.
- repo_root: The 'src' path that will be used for packaging.
- dest_root: The directory where the src files will be stored.
- additional_glob_patterns: Some platforms may need to include certain
- dependencies beyond the default include file patterns. The results here will
- be merged in with _INCLUDE_FILE_PATTERNS.
- include_black_box_tests: If True then the resources for the black box tests
- are included."""
- _CopyAppLauncherTools(repo_root, dest_root,
- additional_glob_patterns,
- include_black_box_tests=include_black_box_tests)
-
-
-def MakeZipArchive(src, output_zip):
- """Convenience function to zip up all files in the src directory (produced
- as dest_root argument in CopyAppLauncherTools()) which will create a zip
- file with the relative root being the src directory."""
- _MakeZipArchive(src, output_zip)
-
-
-################################################################################
-# IMPL #
-################################################################################
-
-
import argparse
import fnmatch
import logging
import os
import shutil
import sys
+import tempfile
import _env # pylint: disable=unused-import
from paths import REPOSITORY_ROOT
from paths import THIRD_PARTY_ROOT
sys.path.append(THIRD_PARTY_ROOT)
-import starboard.tools.platform
+# pylint: disable=g-import-not-at-top,g-bad-import-order
import jinja2
-
+import starboard.tools.platform
# Default python directories to app launcher resources.
_INCLUDE_FILE_PATTERNS = [
@@ -79,11 +44,10 @@
('lbshell', '*.py'),
('starboard', '*.py'),
# jinja2 required by this app_launcher_packager.py script.
- ('third_party/jinja2', '*.py'),
- ('third_party/markupsafe', '*.py'), # Required by third_party/jinja2
+ ('third_party/jinja2', '*.py'),
+ ('third_party/markupsafe', '*.py'), # Required by third_party/jinja2
]
-
_INCLUDE_BLACK_BOX_TESTS_PATTERNS = [
# Black box and web platform tests have non-py assets, so everything
# is picked up.
@@ -95,6 +59,20 @@
# Do not allow .git directories to make it into the build.
_EXCLUDE_DIRECTORY_PATTERNS = ['.git']
+_IS_WINDOWS = sys.platform in ['win32', 'cygwin']
+
+
+def _ToWinUncPath(dos_path, encoding=None):
+ """Windows supports long file names when using a UNC path."""
+ assert _IS_WINDOWS
+ do_convert = (not isinstance(dos_path, unicode) and encoding is not None)
+ if do_convert:
+ dos_path = dos_path.decode(encoding)
+ path = os.path.abspath(dos_path)
+ if path.startswith(u'\\\\'):
+ return u'\\\\?\\UNC\\' + path[2:]
+ return u'\\\\?\\' + path
+
def _MakeDir(d):
"""Make the specified directory and any parents in the path.
@@ -114,18 +92,24 @@
Args:
source_root: Absolute path to the root of the files to be copied.
d: Directory to be checked.
+
+ Returns:
+ true if d in in source_root/out.
"""
out_dir = os.path.join(source_root, 'out')
return out_dir in d
-def _FindFilesRecursive(src_root, glob_pattern):
+def _FindFilesRecursive( # pylint: disable=missing-docstring
+ src_root, glob_pattern):
src_root = os.path.normpath(src_root)
logging.info('Searching in %s for %s type files.', src_root, glob_pattern)
file_list = []
for root, dirs, files in os.walk(src_root, topdown=True):
# Prunes when using os.walk with topdown=True
- [dirs.remove(d) for d in list(dirs) if d in _EXCLUDE_DIRECTORY_PATTERNS]
+ for d in list(dirs):
+ if d in _EXCLUDE_DIRECTORY_PATTERNS:
+ dirs.remove(d)
# Eliminate any locally built files under the out directory.
if _IsOutDir(src_root, root):
continue
@@ -166,12 +150,47 @@
logging.info('Finished baking in platform info files.')
-def _CopyAppLauncherTools(repo_root, dest_root, additional_glob_patterns,
- include_black_box_tests):
- # Step 1: Remove previous output directory if it exists
+def CopyAppLauncherTools(repo_root,
+ dest_root,
+ additional_glob_patterns=None,
+ include_black_box_tests=True):
+ """Copies app launcher related files to the destination root.
+
+ Args:
+ repo_root: The 'src' path that will be used for packaging.
+ dest_root: The directory where the src files will be stored.
+ additional_glob_patterns: Some platforms may need to include certain
+ dependencies beyond the default include file patterns. The results here
+ will be merged in with _INCLUDE_FILE_PATTERNS.
+ include_black_box_tests: If True then the resources for the black box tests
+ are included.
+ """
+ dest_root = _PrepareDestination(dest_root)
+ copy_list = _GetSourceFilesList(repo_root, additional_glob_patterns,
+ include_black_box_tests)
+ _CopyFiles(repo_root, dest_root, copy_list)
+
+
+def _PrepareDestination(dest_root): # pylint: disable=missing-docstring
+ # Make sure dest_root is an absolute path.
+ logging.info('Copying App Launcher tools to = %s', dest_root)
+ dest_root = os.path.normpath(dest_root)
+ if not os.path.isabs(dest_root):
+ dest_root = os.path.join(os.getcwd(), dest_root)
+ if _IS_WINDOWS:
+ dest_root = _ToWinUncPath(dest_root)
+ logging.info('Absolute destination path = %s', dest_root)
+ # Remove previous output directory if it exists
if os.path.isdir(dest_root):
shutil.rmtree(dest_root)
- # Step 2: Find all glob files from specified search directories.
+ return dest_root
+
+
+def _GetSourceFilesList( # pylint: disable=missing-docstring
+ repo_root,
+ additional_glob_patterns=None,
+ include_black_box_tests=True):
+ # Find all glob files from specified search directories.
include_glob_patterns = _INCLUDE_FILE_PATTERNS
if additional_glob_patterns:
include_glob_patterns += additional_glob_patterns
@@ -189,8 +208,13 @@
# Order by file path string and remove any duplicate paths.
copy_list = list(set(copy_list))
copy_list.sort()
+ return copy_list
+
+
+def _CopyFiles( # pylint: disable=missing-docstring
+ repo_root, dest_root, copy_list):
+ # Copy the src files to the destination directory.
folders_logged = set()
- # Step 3: Copy the src files to the destination directory.
for src in copy_list:
tail_path = os.path.relpath(src, repo_root)
dst = os.path.join(dest_root, tail_path)
@@ -198,15 +222,24 @@
if not os.path.isdir(d):
os.makedirs(d)
src_folder = os.path.dirname(src)
- if not src_folder in folders_logged:
+ if src_folder not in folders_logged:
folders_logged.add(src_folder)
logging.info(src_folder + ' -> ' + os.path.dirname(dst))
shutil.copy2(src, dst)
- # Step 4: Re-write the platform infos file in the new repo copy.
+ # Re-write the platform infos file in the new repo copy.
_WritePlatformsInfo(repo_root, dest_root)
-def _MakeZipArchive(src, output_zip):
+def MakeZipArchive(src, output_zip):
+ """Convenience function to zip up all files in the src directory.
+
+ Intended for use with the dest_root output from CopyAppLauncherTools() to
+ create a zip file with the relative root being the src directory.
+
+ Args:
+ src: Path to the directory of files to zip up.
+ output_zip: Path to the zip file to create.
+ """
if os.path.isfile(output_zip):
os.unlink(output_zip)
logging.info('Creating a zip file of the app launcher package')
@@ -218,14 +251,49 @@
def main(command_args):
logging.basicConfig(level=logging.INFO)
parser = argparse.ArgumentParser()
- parser.add_argument(
+ dest_group = parser.add_mutually_exclusive_group(required=True)
+ dest_group.add_argument(
'-d',
'--destination_root',
- required=True,
help='The path to the root of the destination folder into which the '
- 'application resources are packaged.')
+ 'application resources are packaged.')
+ dest_group.add_argument(
+ '-z',
+ '--zip_file',
+ help='The path to a zip file into which the application resources are '
+ 'packaged.')
+ dest_group.add_argument(
+ '-l',
+ '--list',
+ action='store_true',
+ help='List to stdout the application resources relative to the current '
+ 'directory.')
+ parser.add_argument(
+ '-v', '--verbose', action='store_true', help='Verbose logging output.')
args = parser.parse_args(command_args)
- CopyAppLauncherTools(REPOSITORY_ROOT, args.destination_root)
+
+ if not args.verbose:
+ logging.disable(logging.INFO)
+
+ if args.destination_root:
+ CopyAppLauncherTools(REPOSITORY_ROOT, args.destination_root)
+ elif args.zip_file:
+ try:
+ temp_dir = tempfile.mkdtemp(prefix='cobalt_app_launcher_')
+ CopyAppLauncherTools(REPOSITORY_ROOT, temp_dir)
+ MakeZipArchive(temp_dir, args.zip_file)
+ finally:
+ shutil.rmtree(temp_dir)
+ elif args.list:
+ for src_file in _GetSourceFilesList(REPOSITORY_ROOT):
+ # Skip paths with '$' since they won't get through the Ninja generator.
+ if '$' in src_file:
+ continue
+ # Relative to CWD where gyp ran this; same as '<(DEPTH)' in gyp file.
+ src_file = os.path.relpath(src_file)
+ # Forward slashes for gyp, even on Windows.
+ src_file = src_file.replace('\\', '/')
+ print src_file
return 0
diff --git a/src/starboard/tools/testing/build_tests.py b/src/starboard/tools/testing/build_tests.py
index b02470e..c9f7082 100644
--- a/src/starboard/tools/testing/build_tests.py
+++ b/src/starboard/tools/testing/build_tests.py
@@ -1,7 +1,25 @@
+# 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.
+"""Common code for building various types of targets, typically tests."""
+
import logging
import os
import subprocess
+APP_LAUNCHER_TARGET = 'app_launcher_zip'
+
+
def BuildTargets(targets, out_directory, dry_run=False, extra_build_flags=[]):
"""Builds all specified targets.
@@ -16,6 +34,7 @@
if dry_run:
args_list.append("-n")
+ args_list.append(APP_LAUNCHER_TARGET)
args_list.extend(["{}_deploy".format(test_name) for test_name in targets])
args_list.extend(extra_build_flags)
diff --git a/src/starboard/tools/tools.gyp b/src/starboard/tools/tools.gyp
new file mode 100644
index 0000000..a80103f
--- /dev/null
+++ b/src/starboard/tools/tools.gyp
@@ -0,0 +1,47 @@
+# 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 "all" target, which includes all interesting targets for the
+# Starboard project.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'app_launcher_zip',
+ 'type': 'none',
+ 'variables': {
+ 'app_launcher_packager_path': 'app_launcher_packager.py',
+ 'app_launcher_zip_file': '<(PRODUCT_DIR)/app_launcher.zip',
+ },
+ 'actions': [
+ {
+ 'action_name': 'package_app_launcher',
+ 'message': 'Zipping <(app_launcher_zip_file)',
+ 'inputs': [
+ '<!@(["python", "<(app_launcher_packager_path)", "-l"])',
+ ],
+ 'outputs': [
+ '<(app_launcher_zip_file)',
+ ],
+ 'action': [
+ 'python',
+ '<(app_launcher_packager_path)',
+ '-z',
+ '<(app_launcher_zip_file)',
+ ],
+ },
+ ],
+ },
+ ]
+}
diff --git a/src/third_party/mozjs-45/js/src/jit/x86-shared/Encoding-x86-shared.h b/src/third_party/mozjs-45/js/src/jit/x86-shared/Encoding-x86-shared.h
index 2457f85..99d8859 100644
--- a/src/third_party/mozjs-45/js/src/jit/x86-shared/Encoding-x86-shared.h
+++ b/src/third_party/mozjs-45/js/src/jit/x86-shared/Encoding-x86-shared.h
@@ -244,6 +244,16 @@
case OP2_MOVSD_WsdVsd: // also OP2_MOVPS_WpsVps
case OP2_MOVAPS_WsdVsd:
case OP2_MOVDQ_WdqVdq:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+inline bool IsXMMReversedOperands(ThreeByteOpcodeID opcode)
+{
+ switch (opcode) {
case OP3_PEXTRD_EdVdqIb:
return true;
default: