Import Cobalt 21.lts.4.300899
diff --git a/src/buildtools/linux64/gn b/src/buildtools/linux64/gn deleted file mode 100755 index 9485341..0000000 --- a/src/buildtools/linux64/gn +++ /dev/null Binary files differ
diff --git a/src/cobalt/CHANGELOG.md b/src/cobalt/CHANGELOG.md index 644ecae..b201080 100644 --- a/src/cobalt/CHANGELOG.md +++ b/src/cobalt/CHANGELOG.md
@@ -125,6 +125,18 @@ This behavior can now be overridden by implementing the cobalt extension function `CobaltExtensionGraphicsApi::ShouldClearFrameOnShutdown`. + - **Added support for adjusting colors of 360 videos.** + + Platforms which support 360 videos may adjust the colors of the video frame + using `CobaltExtensionGraphicsApi::GetMapToMeshColorAdjustments`. + + - **Added support for rendering the frame with a custom root transform.** + + Platforms can force frame rendering to use a custom root transform by using + `CobaltExtensionGraphicsApi::GetRenderRootTransform`. This only impacts + rendering; the web app does not know about the custom transform so may not + layout elements appropriately. + ## Version 20 - **Support for QUIC and SPDY is now enabled.** @@ -483,7 +495,7 @@ The Cobalt splash screen is customizable. Documents may use a link element with attribute rel="splashscreen" to reference the splash screen which will be cached if local cache is implemented on the platform. Additionally - fallbacks may be specified via command line parmeter or gypi variable. + fallbacks may be specified via command line parameter or gypi variable. For more information, see [doc/splash_screen.md](doc/splash_screen.md). - **Introduce C\+\+11**
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id index 9bdf0dc..4021ee4 100644 --- a/src/cobalt/build/build.id +++ b/src/cobalt/build/build.id
@@ -1 +1 @@ -300530 \ No newline at end of file +300899 \ No newline at end of file
diff --git a/src/cobalt/content/ssl/certs/9c2e7d30.0 b/src/cobalt/content/ssl/certs/9c2e7d30.0 deleted file mode 100644 index 36a998d..0000000 --- a/src/cobalt/content/ssl/certs/9c2e7d30.0 +++ /dev/null
@@ -1,19 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP -MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx -MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV -BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o -Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt -5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s -3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej -vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu -8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw -DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG -MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil -zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/ -3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD -FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6 -Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2 -ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M ------END CERTIFICATE-----
diff --git a/src/cobalt/extension/extension_test.cc b/src/cobalt/extension/extension_test.cc index 0670fbb..1bbc6c8 100644 --- a/src/cobalt/extension/extension_test.cc +++ b/src/cobalt/extension/extension_test.cc
@@ -63,7 +63,7 @@ EXPECT_STREQ(extension_api->name, kExtensionName); EXPECT_GE(extension_api->version, 1u); - EXPECT_LE(extension_api->version, 4u); + EXPECT_LE(extension_api->version, 5u); EXPECT_NE(extension_api->GetMaximumFrameIntervalInMilliseconds, nullptr); float maximum_frame_interval = @@ -97,6 +97,11 @@ } } + if (extension_api->version >= 5) { + EXPECT_NE(extension_api->GetMapToMeshColorAdjustments, nullptr); + EXPECT_NE(extension_api->GetRenderRootTransform, nullptr); + } + const ExtensionApi* second_extension_api = static_cast<const ExtensionApi*>(SbSystemGetExtension(kExtensionName)); EXPECT_EQ(second_extension_api, extension_api)
diff --git a/src/cobalt/extension/graphics.h b/src/cobalt/extension/graphics.h index a1a3b4e..ed55a2e 100644 --- a/src/cobalt/extension/graphics.h +++ b/src/cobalt/extension/graphics.h
@@ -25,6 +25,21 @@ #define kCobaltExtensionGraphicsName "dev.cobalt.extension.Graphics" +// This structure allows post-processing of output colors for 360 videos. +// Given "rgba" is the color that the pixel shader calculates, this struct +// allows additional processing in the form of: +// final color = rgba0_scale + +// rgba1_scale * rgba + +// rgba2_scale * rgba * rgba + +// rgba3_scale * rgba * rgba * rgba; +// The final_color is then clamped to the range of [0,1] for each element. +typedef struct CobaltExtensionGraphicsMapToMeshColorAdjustment { + float rgba0_scale[4]; // multiplier for rgba^0 + float rgba1_scale[4]; // multiplier for rgba^1 + float rgba2_scale[4]; // multiplier for rgba^2 + float rgba3_scale[4]; // multiplier for rgba^3 +} CobaltExtensionGraphicsMapToMeshColorAdjustment; + typedef struct CobaltExtensionGraphicsApi { // Name should be the string kCobaltExtensionGraphicsName. // This helps to validate that the extension API is correct. @@ -75,6 +90,23 @@ float* clear_color_green, float* clear_color_blue, float* clear_color_alpha); + + // The fields below this point were added in version 5 or later. + + // Use the provided color adjustments for 360 videos if the function returns + // true. See declaration of CobaltExtensionGraphicsMapToMeshColorAdjustment + // for details. + bool (*GetMapToMeshColorAdjustments)( + CobaltExtensionGraphicsMapToMeshColorAdjustment* adjustment); + + // This function can be used to insert a custom transform at the root of + // rendering. This allows custom scaling, rotating, etc. of the frame. This + // only impacts rendering of the frame -- the web app will not know about this + // transform, so it may not layout elements appropriately. This function + // should return true if a custom transform should be used. + bool (*GetRenderRootTransform)(float* m00, float* m01, float* m02, float* m10, + float* m11, float* m12, float* m20, float* m21, + float* m22); } CobaltExtensionGraphicsApi; #ifdef __cplusplus
diff --git a/src/cobalt/layout/layout.cc b/src/cobalt/layout/layout.cc index b635518..6ab79ff 100644 --- a/src/cobalt/layout/layout.cc +++ b/src/cobalt/layout/layout.cc
@@ -24,12 +24,14 @@ #include "cobalt/dom/html_body_element.h" #include "cobalt/dom/html_element_context.h" #include "cobalt/dom/html_html_element.h" +#include "cobalt/extension/graphics.h" #include "cobalt/layout/benchmark_stat_names.h" #include "cobalt/layout/box_generator.h" #include "cobalt/layout/initial_containing_block.h" #include "cobalt/layout/layout_boxes.h" #include "cobalt/layout/used_style.h" #include "cobalt/render_tree/animations/animate_node.h" +#include "cobalt/render_tree/matrix_transform_node.h" namespace cobalt { namespace layout { @@ -194,9 +196,26 @@ // status for animated images. used_style_provider->UpdateAnimatedImages(); - render_tree::CompositionNode* static_root_node = + render_tree::Node* static_root_node = new render_tree::CompositionNode(std::move(render_tree_root_builder)); +#if SB_API_VERSION >= 11 + // Support insertion of a custom transform at the render tree root. + static const CobaltExtensionGraphicsApi* s_graphics_extension = + static_cast<const CobaltExtensionGraphicsApi*>( + SbSystemGetExtension(kCobaltExtensionGraphicsName)); + float m00, m01, m02, m10, m11, m12, m20, m21, m22; + if (s_graphics_extension && + strcmp(s_graphics_extension->name, kCobaltExtensionGraphicsName) == 0 && + s_graphics_extension->version >= 5 && + s_graphics_extension->GetRenderRootTransform(&m00, &m01, &m02, &m10, &m11, + &m12, &m20, &m21, &m22)) { + static_root_node = new render_tree::MatrixTransformNode( + static_root_node, math::Matrix3F::FromValues(m00, m01, m02, m10, m11, + m12, m20, m21, m22)); + } +#endif // SB_API_VERSION >= 11 + // Make it easy to animate the entire tree by placing an AnimateNode at the // root to merge any sub-AnimateNodes. render_tree::animations::AnimateNode* animate_node =
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_directgles_color_include.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_directgles_color_include.glsl index f42f765..ddeb45d 100644 --- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_directgles_color_include.glsl +++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_directgles_color_include.glsl
@@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -precision mediump float; +precision highp float; uniform vec4 u_include; // include scissor (x_min, y_min, x_max, y_max) varying vec2 v_offset; varying vec4 v_color;
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_textured_vbo_rgba.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_textured_vbo_rgba.glsl index 04eaa9c..fdffec9 100644 --- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_textured_vbo_rgba.glsl +++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_textured_vbo_rgba.glsl
@@ -4,5 +4,6 @@ void main() { vec4 untransformed_color = vec4(texture2D(texture_rgba, v_tex_coord_rgba).rgba); - gl_FragColor = untransformed_color; -} \ No newline at end of file + vec4 color = untransformed_color; + gl_FragColor = color; +}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_textured_vbo_uyvy_1plane.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_textured_vbo_uyvy_1plane.glsl index 9a77757..1a36b31 100644 --- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_textured_vbo_uyvy_1plane.glsl +++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_textured_vbo_uyvy_1plane.glsl
@@ -30,5 +30,6 @@ } vec4 untransformed_color = vec4(y_value, uv_value.r, uv_value.g, 1.0); - gl_FragColor = untransformed_color * to_rgb_color_matrix; + vec4 color = untransformed_color * to_rgb_color_matrix; + gl_FragColor = color; }
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_textured_vbo_yuv_2plane.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_textured_vbo_yuv_2plane.glsl index 75b5036..15c79fa 100644 --- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_textured_vbo_yuv_2plane.glsl +++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_textured_vbo_yuv_2plane.glsl
@@ -10,5 +10,6 @@ texture2D(texture_y, v_tex_coord_y).a, texture2D(texture_uv, v_tex_coord_uv).ba, 1.0); - gl_FragColor = untransformed_color * to_rgb_color_matrix; + vec4 color = untransformed_color * to_rgb_color_matrix; + gl_FragColor = color; }
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_textured_vbo_yuv_3plane.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_textured_vbo_yuv_3plane.glsl index 91137c6..da6e748 100644 --- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_textured_vbo_yuv_3plane.glsl +++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_textured_vbo_yuv_3plane.glsl
@@ -11,5 +11,6 @@ texture2D(texture_y, v_tex_coord_y).a, texture2D(texture_u, v_tex_coord_u).a, texture2D(texture_v, v_tex_coord_v).a, 1.0); - gl_FragColor = untransformed_color * to_rgb_color_matrix; + vec4 color = untransformed_color * to_rgb_color_matrix; + gl_FragColor = color; }
diff --git a/src/cobalt/renderer/rasterizer/egl/shaders/fragment_color_include.glsl b/src/cobalt/renderer/rasterizer/egl/shaders/fragment_color_include.glsl index 2cb71f7..aadf5d0 100644 --- a/src/cobalt/renderer/rasterizer/egl/shaders/fragment_color_include.glsl +++ b/src/cobalt/renderer/rasterizer/egl/shaders/fragment_color_include.glsl
@@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -precision mediump float; +precision highp float; uniform vec4 u_include; // include scissor (x_min, y_min, x_max, y_max) varying vec2 v_offset; varying vec4 v_color;
diff --git a/src/cobalt/renderer/rasterizer/egl/textured_mesh_renderer.cc b/src/cobalt/renderer/rasterizer/egl/textured_mesh_renderer.cc index 874c225..ac3cb80 100644 --- a/src/cobalt/renderer/rasterizer/egl/textured_mesh_renderer.cc +++ b/src/cobalt/renderer/rasterizer/egl/textured_mesh_renderer.cc
@@ -21,6 +21,7 @@ #include <vector> #include "base/strings/stringprintf.h" +#include "cobalt/extension/graphics.h" #include "cobalt/math/size.h" #include "cobalt/renderer/backend/egl/utils.h" #include "cobalt/renderer/egl_and_gles.h" @@ -346,12 +347,53 @@ if (color_matrix) { blit_fragment_shader_source += ");" - " gl_FragColor = untransformed_color * to_rgb_color_matrix;" - "}"; + " vec4 color = untransformed_color * to_rgb_color_matrix;"; } else { blit_fragment_shader_source += ");" - " gl_FragColor = untransformed_color;" + " vec4 color = untransformed_color;"; + } +#if SB_API_VERSION >= 11 + const CobaltExtensionGraphicsApi* graphics_extension = + static_cast<const CobaltExtensionGraphicsApi*>( + SbSystemGetExtension(kCobaltExtensionGraphicsName)); + CobaltExtensionGraphicsMapToMeshColorAdjustment color_adjustment; + if (graphics_extension != nullptr && + strcmp(graphics_extension->name, kCobaltExtensionGraphicsName) == 0 && + graphics_extension->version >= 5 && + graphics_extension->GetMapToMeshColorAdjustments(&color_adjustment)) { + // Setup vectors for the color adjustments. Ensure they use dot for decimal + // point regardless of locale. + std::stringstream buffer; + buffer.imbue(std::locale::classic()); + buffer << " vec4 scale0 = vec4(" << color_adjustment.rgba0_scale[0] << "," + << color_adjustment.rgba0_scale[1] << "," + << color_adjustment.rgba0_scale[2] << "," + << color_adjustment.rgba0_scale[3] << ");"; + buffer << " vec4 scale1 = vec4(" << color_adjustment.rgba1_scale[0] << "," + << color_adjustment.rgba1_scale[1] << "," + << color_adjustment.rgba1_scale[2] << "," + << color_adjustment.rgba1_scale[3] << ");"; + buffer << " vec4 scale2 = vec4(" << color_adjustment.rgba2_scale[0] << "," + << color_adjustment.rgba2_scale[1] << "," + << color_adjustment.rgba2_scale[2] << "," + << color_adjustment.rgba2_scale[3] << ");"; + buffer << " vec4 scale3 = vec4(" << color_adjustment.rgba3_scale[0] << "," + << color_adjustment.rgba3_scale[1] << "," + << color_adjustment.rgba3_scale[2] << "," + << color_adjustment.rgba3_scale[3] << ");"; + blit_fragment_shader_source += + " vec4 color2 = color * color;" + " vec4 color3 = color2 * color;" + + buffer.str() + + " color = scale0 + scale1*color + scale2*color2 + scale3*color3;" + " gl_FragColor = clamp(color, vec4(0.0), vec4(1.0));" + "}"; + } else +#endif // SB_API_VERSION >= 11 + { + blit_fragment_shader_source += + " gl_FragColor = color;" "}"; }
diff --git a/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc b/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc index 537a25f..2558ad5 100644 --- a/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc +++ b/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc
@@ -45,8 +45,6 @@ #include "cobalt/renderer/rasterizer/skia/font.h" #include "cobalt/renderer/rasterizer/skia/glyph_buffer.h" #include "cobalt/renderer/rasterizer/skia/image.h" -#include "cobalt/renderer/rasterizer/skia/skia/src/effects/SkNV122RGBShader.h" -#include "cobalt/renderer/rasterizer/skia/skia/src/effects/SkYUV2RGBShader.h" #include "cobalt/renderer/rasterizer/skia/skottie_animation.h" #include "cobalt/renderer/rasterizer/skia/software_image.h" #include "third_party/skia/include/core/SkBlendMode.h"
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/skia_cobalt.gypi b/src/cobalt/renderer/rasterizer/skia/skia/skia_cobalt.gypi index 6f73d3e..72ac12e 100644 --- a/src/cobalt/renderer/rasterizer/skia/skia/skia_cobalt.gypi +++ b/src/cobalt/renderer/rasterizer/skia/skia/skia_cobalt.gypi
@@ -19,10 +19,6 @@ 'sources': [ 'config/SkUserConfig.h', - 'src/effects/SkNV122RGBShader.cc', - 'src/effects/SkNV122RGBShader.h', - 'src/effects/SkYUV2RGBShader.cc', - 'src/effects/SkYUV2RGBShader.h', 'src/google_logging.cc', 'src/gpu/gl/GrGLMakeNativeInterface_cobalt.cc', 'src/ports/SkFontConfigParser_cobalt.cc',
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkNV122RGBShader.cc b/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkNV122RGBShader.cc deleted file mode 100644 index 8f9f343..0000000 --- a/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkNV122RGBShader.cc +++ /dev/null
@@ -1,174 +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 "cobalt/renderer/rasterizer/skia/skia/src/effects/SkNV122RGBShader.h" - -#include <algorithm> - -#include "base/logging.h" -#include "cobalt/base/polymorphic_downcast.h" -#include "third_party/skia/include/core/SkColorPriv.h" -#include "third_party/skia/include/core/SkShader.h" -#include "third_party/skia/include/core/SkString.h" -#include "third_party/skia/src/core/SkReadBuffer.h" -#include "third_party/skia/src/core/SkWriteBuffer.h" - -#if SK_SUPPORT_GPU -#include "third_party/skia/src/gpu/GrFragmentProcessor.h" -#endif - -SkNV122RGBShader::SkNV122RGBShader(SkYUVColorSpace color_space, - const sk_sp<SkImage>& y_image, - const SkMatrix& y_matrix, - const sk_sp<SkImage>& uv_image, - const SkMatrix& uv_matrix) - : color_space_(color_space), - y_image_(y_image), - y_matrix_(y_matrix), - uv_image_(uv_image), - uv_matrix_(uv_matrix) { - DCHECK(y_image_); - DCHECK(uv_image_); - InitializeShaders(); -} - -void SkNV122RGBShader::InitializeShaders() { - y_shader_.reset(base::polymorphic_downcast<SkImageShader*>( - SkImageShader::Make(y_image_, SkTileMode::kClamp, SkTileMode::kClamp, - &y_matrix_, false) - .get())); - DCHECK(y_shader_); - - uv_shader_.reset(base::polymorphic_downcast<SkImageShader*>( - SkImageShader::Make(uv_image_, SkTileMode::kClamp, SkTileMode::kClamp, - &uv_matrix_, false) - .get())); - DCHECK(uv_shader_); -} - -SkNV122RGBShader::~SkNV122RGBShader() { -} - -void SkNV122RGBShader::flatten(SkWriteBuffer& buffer) const { - buffer.writeInt(color_space_); - buffer.writeImage(y_image_.get()); - buffer.writeMatrix(y_matrix_); - buffer.writeImage(uv_image_.get()); - buffer.writeMatrix(uv_matrix_); -} - -uint32_t SkNV122RGBShader::NV122RGBShaderContext::getFlags() const { return 0; } - -SkNV122RGBShader::NV122RGBShaderContext::NV122RGBShaderContext( - SkYUVColorSpace color_space, const SkNV122RGBShader& yuv2rgb_shader, - SkShaderBase::Context* y_shader_context, - SkShaderBase::Context* uv_shader_context, const ContextRec& rec) - : INHERITED(yuv2rgb_shader, rec), - color_space_(color_space), - y_shader_context_(y_shader_context), - uv_shader_context_(uv_shader_context) {} - -SkNV122RGBShader::NV122RGBShaderContext::~NV122RGBShaderContext() { - y_shader_context_->~Context(); - uv_shader_context_->~Context(); -} - -void SkNV122RGBShader::NV122RGBShaderContext::shadeSpan(int x, int y, - SkPMColor result[], - int count) { - static const int kPixelCountPerSpan = 64; - SkPMColor y_values[kPixelCountPerSpan]; - SkPMColor uv_values[kPixelCountPerSpan]; - - DCHECK_EQ(kRec709_SkYUVColorSpace, color_space_) - << "Currently we only support the BT.709 YUV colorspace."; - - do { - int count_in_chunk = - count > kPixelCountPerSpan ? kPixelCountPerSpan : count; - - y_shader_context_->shadeSpan(x, y, y_values, count_in_chunk); - uv_shader_context_->shadeSpan(x, y, uv_values, count_in_chunk); - - for (int i = 0; i < count_in_chunk; ++i) { - int32_t y_value = SkColorGetA(y_values[i]) - 16; - int32_t u_value = SkColorGetB(uv_values[i]) - 128; - int32_t v_value = SkColorGetA(uv_values[i]) - 128; - - const float kA = 1.164f; - const float kB = -0.213f; - const float kC = 2.112f; - const float kD = 1.793f; - const float kE = -0.533f; - int32_t r_unclamped = static_cast<int32_t>(kA * y_value + kD * v_value); - int32_t g_unclamped = - static_cast<int32_t>(kA * y_value + kB * u_value + kE * v_value); - int32_t b_unclamped = static_cast<int32_t>(kA * y_value + kC * u_value); - - int32_t r_clamped = - std::min<int32_t>(255, std::max<int32_t>(0, r_unclamped)); - int32_t g_clamped = - std::min<int32_t>(255, std::max<int32_t>(0, g_unclamped)); - int32_t b_clamped = - std::min<int32_t>(255, std::max<int32_t>(0, b_unclamped)); - - result[i] = SkPackARGB32NoCheck(255, r_clamped, g_clamped, b_clamped); - } - result += count_in_chunk; - x += count_in_chunk; - count -= count_in_chunk; - } while (count > 0); -} - -#if SK_SUPPORT_GPU - -std::unique_ptr<GrFragmentProcessor> SkNV122RGBShader::asFragmentProcessor( - const GrFPArgs&) const { -#if 0 - // TODO SKIA_M61_EFFECTS. Investigate if we still need this. - // Code snippet taken from SkBitmapProcShader::asFragmentProcessor(). - SkMatrix matrix; - matrix.setIDiv(y_image_->width(), y_image_->height()); - - SkMatrix lmInverse; - if (!y_shader_->getLocalMatrix().invert(&lmInverse)) { - return false; - } - if (localMatrix) { - SkMatrix inv; - if (!localMatrix->invert(&inv)) { - return false; - } - lmInverse.postConcat(inv); - } - matrix.preConcat(lmInverse); - - GrTextureParams::FilterMode filter_mode = - paint.getFilterLevel() == SkPaint::kNone_FilterLevel - ? GrTextureParams::kNone_FilterMode - : GrTextureParams::kBilerp_FilterMode; - GrTextureParams texture_params; - texture_params.setFilterMode(filter_mode); - - *fp = GrYUVtoRGBEffect::Create(y_image_->getTexture(), - uv_image_->getTexture(), - NULL, matrix, texture_params, - kRec709_SkYUVColorSpace, true); - return true; -#else - return nullptr; -#endif -} - -#endif // SK_SUPPORT_GPU
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkNV122RGBShader.h b/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkNV122RGBShader.h deleted file mode 100644 index c822333..0000000 --- a/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkNV122RGBShader.h +++ /dev/null
@@ -1,78 +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. - -#ifndef COBALT_RENDERER_RASTERIZER_SKIA_SKIA_SRC_EFFECTS_SKNV122RGBSHADER_H_ -#define COBALT_RENDERER_RASTERIZER_SKIA_SKIA_SRC_EFFECTS_SKNV122RGBSHADER_H_ - -#include "third_party/skia/src/shaders/SkShaderBase.h" - -#include "third_party/skia/src/shaders/SkImageShader.h" - -class SkNV122RGBShader : public SkShaderBase { - public: - SkNV122RGBShader(SkYUVColorSpace color_space, const sk_sp<SkImage>& y_image, - const SkMatrix& y_matrix, const sk_sp<SkImage>& uv_image, - const SkMatrix& uv_matrix); - virtual ~SkNV122RGBShader(); - - class NV122RGBShaderContext : public SkShaderBase::Context { - public: - // Takes ownership of shaderContext and calls its destructor. - NV122RGBShaderContext(SkYUVColorSpace color_space, - const SkNV122RGBShader& yuv2rgb_shader, - SkShaderBase::Context* y_shader_context, - SkShaderBase::Context* uv_shader_context, - const ContextRec& rec); - virtual ~NV122RGBShaderContext(); - - uint32_t getFlags() const override; - - void shadeSpan(int x, int y, SkPMColor[], int count) override; - - private: - SkYUVColorSpace color_space_; - - SkShaderBase::Context* y_shader_context_; - SkShaderBase::Context* uv_shader_context_; - - typedef SkShaderBase::Context INHERITED; - }; - -#if SK_SUPPORT_GPU - std::unique_ptr<GrFragmentProcessor> asFragmentProcessor( - const GrFPArgs&) const override; -#endif - - SK_FLATTENABLE_HOOKS(SkNV122RGBShader) - - protected: - void flatten(SkWriteBuffer&) const override; - - private: - void InitializeShaders(); - - SkYUVColorSpace color_space_; - - sk_sp<SkImage> y_image_; - SkMatrix y_matrix_; - sk_sp<SkImageShader> y_shader_; - - sk_sp<SkImage> uv_image_; - SkMatrix uv_matrix_; - sk_sp<SkImageShader> uv_shader_; - - typedef SkShaderBase INHERITED; -}; - -#endif // COBALT_RENDERER_RASTERIZER_SKIA_SKIA_SRC_EFFECTS_SKNV122RGBSHADER_H_
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkYUV2RGBShader.cc b/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkYUV2RGBShader.cc deleted file mode 100644 index 71efe90..0000000 --- a/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkYUV2RGBShader.cc +++ /dev/null
@@ -1,159 +0,0 @@ -// Copyright 2015 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 "cobalt/renderer/rasterizer/skia/skia/src/effects/SkYUV2RGBShader.h" - -#include <algorithm> - -#include "base/logging.h" -#include "cobalt/base/polymorphic_downcast.h" -#include "third_party/skia/include/core/SkColorPriv.h" -#include "third_party/skia/include/core/SkShader.h" -#include "third_party/skia/include/core/SkString.h" -#include "third_party/skia/src/core/SkReadBuffer.h" -#include "third_party/skia/src/core/SkWriteBuffer.h" -#include "third_party/skia/src/gpu/GrFragmentProcessor.h" -#include "third_party/skia/src/gpu/effects/GrYUVtoRGBEffect.h" -#include "third_party/skia/src/shaders/SkImageShader.h" - -SkYUV2RGBShader::SkYUV2RGBShader(SkYUVColorSpace color_space, - const sk_sp<SkImage>& y_image, - const SkMatrix& y_matrix, - const sk_sp<SkImage>& u_image, - const SkMatrix& u_matrix, - const sk_sp<SkImage>& v_image, - const SkMatrix& v_matrix) - : color_space_(color_space), - y_image_(y_image), - y_matrix_(y_matrix), - u_image_(u_image), - u_matrix_(u_matrix), - v_image_(v_image), - v_matrix_(v_matrix) { - DCHECK(y_image_); - DCHECK(u_image_); - DCHECK(v_image_); - InitializeShaders(); -} - -void SkYUV2RGBShader::InitializeShaders() { - y_shader_.reset(base::polymorphic_downcast<SkImageShader*>( - SkImageShader::Make(y_image_, SkTileMode::kClamp, SkTileMode::kClamp, - &y_matrix_, false) - .get())); - DCHECK(y_shader_); - - u_shader_.reset(base::polymorphic_downcast<SkImageShader*>( - SkImageShader::Make(u_image_, SkTileMode::kClamp, SkTileMode::kClamp, - &u_matrix_, false) - .get())); - DCHECK(u_shader_); - - v_shader_.reset(base::polymorphic_downcast<SkImageShader*>( - SkImageShader::Make(v_image_, SkTileMode::kClamp, SkTileMode::kClamp, - &v_matrix_, false) - .get())); - DCHECK(v_shader_); -} - -void SkYUV2RGBShader::flatten(SkWriteBuffer& buffer) const { - buffer.writeInt(color_space_); - buffer.writeImage(y_image_.get()); - buffer.writeMatrix(y_matrix_); - buffer.writeImage(u_image_.get()); - buffer.writeMatrix(u_matrix_); - buffer.writeImage(v_image_.get()); - buffer.writeMatrix(v_matrix_); -} - -uint32_t SkYUV2RGBShader::YUV2RGBShaderContext::getFlags() const { - return 0; -} - -SkShaderBase::Context* SkYUV2RGBShader::onMakeContext( - const ContextRec& rec, SkArenaAlloc* storage) const { - return nullptr; -} -SkYUV2RGBShader::YUV2RGBShaderContext::YUV2RGBShaderContext( - SkYUVColorSpace color_space, const SkYUV2RGBShader& yuv2rgb_shader, - SkShaderBase::Context* y_shader_context, - SkShaderBase::Context* u_shader_context, - SkShaderBase::Context* v_shader_context, const ContextRec& rec) - : INHERITED(yuv2rgb_shader, rec), - color_space_(color_space), - y_shader_context_(y_shader_context), - u_shader_context_(u_shader_context), - v_shader_context_(v_shader_context) {} - -SkYUV2RGBShader::YUV2RGBShaderContext::~YUV2RGBShaderContext() { - y_shader_context_->~Context(); - u_shader_context_->~Context(); - v_shader_context_->~Context(); -} -void SkYUV2RGBShader::YUV2RGBShaderContext::shadeSpan( - int x, int y, SkPMColor result[], int count) { - static const int kPixelCountPerSpan = 64; - SkPMColor y_values[kPixelCountPerSpan]; - SkPMColor u_values[kPixelCountPerSpan]; - SkPMColor v_values[kPixelCountPerSpan]; - - DCHECK_EQ(kRec709_SkYUVColorSpace, color_space_) << - "Currently we only support the BT.709 YUV colorspace."; - - do { - int count_in_chunk = - count > kPixelCountPerSpan ? kPixelCountPerSpan : count; - - y_shader_context_->shadeSpan(x, y, y_values, count_in_chunk); - u_shader_context_->shadeSpan(x, y, u_values, count_in_chunk); - v_shader_context_->shadeSpan(x, y, v_values, count_in_chunk); - - for (int i = 0; i < count_in_chunk; ++i) { - int32_t y_value = SkColorGetA(y_values[i]) - 16; - int32_t u_value = SkColorGetA(u_values[i]) - 128; - int32_t v_value = SkColorGetA(v_values[i]) - 128; - - const float kA = 1.164f; - const float kB = -0.213f; - const float kC = 2.112f; - const float kD = 1.793f; - const float kE = -0.533f; - int32_t r_unclamped = static_cast<int32_t>(kA * y_value + kD * v_value); - int32_t g_unclamped = - static_cast<int32_t>(kA * y_value + kB * u_value + kE * v_value); - int32_t b_unclamped = static_cast<int32_t>(kA * y_value + kC * u_value); - - int32_t r_clamped = - std::min<int32_t>(255, std::max<int32_t>(0, r_unclamped)); - int32_t g_clamped = - std::min<int32_t>(255, std::max<int32_t>(0, g_unclamped)); - int32_t b_clamped = - std::min<int32_t>(255, std::max<int32_t>(0, b_unclamped)); - - result[i] = SkPackARGB32NoCheck(255, r_clamped, g_clamped, b_clamped); - } - result += count_in_chunk; - x += count_in_chunk; - count -= count_in_chunk; - } while (count > 0); -} - -#if SK_SUPPORT_GPU - -std::unique_ptr<GrFragmentProcessor> SkYUV2RGBShader::asFragmentProcessor( - const GrFPArgs&) const { - return nullptr; -} - -#endif // SK_SUPPORT_GPU
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkYUV2RGBShader.h b/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkYUV2RGBShader.h deleted file mode 100644 index f05534b..0000000 --- a/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkYUV2RGBShader.h +++ /dev/null
@@ -1,87 +0,0 @@ -// Copyright 2015 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 COBALT_RENDERER_RASTERIZER_SKIA_SKIA_SRC_EFFECTS_SKYUV2RGBSHADER_H_ -#define COBALT_RENDERER_RASTERIZER_SKIA_SKIA_SRC_EFFECTS_SKYUV2RGBSHADER_H_ - -#include "third_party/skia/src/shaders/SkShaderBase.h" - -#include "third_party/skia/src/shaders/SkImageShader.h" - -class SkYUV2RGBShader : public SkShaderBase { - public: - SkYUV2RGBShader(SkYUVColorSpace color_space, const sk_sp<SkImage>& y_image, - const SkMatrix& y_matrix, const sk_sp<SkImage>& u_image, - const SkMatrix& u_matrix, const sk_sp<SkImage>& v_image, - const SkMatrix& v_matrix); - virtual ~SkYUV2RGBShader() = default; - - class YUV2RGBShaderContext : public SkShaderBase::Context { - public: - // Takes ownership of shaderContext and calls its destructor. - YUV2RGBShaderContext(SkYUVColorSpace color_space, - const SkYUV2RGBShader& yuv2rgb_shader, - SkShaderBase::Context* y_shader_context, - SkShaderBase::Context* u_shader_context, - SkShaderBase::Context* v_shader_context, - const ContextRec& rec); - virtual ~YUV2RGBShaderContext(); - - uint32_t getFlags() const override; - - void shadeSpan(int x, int y, SkPMColor[], int count) override; - - private: - SkYUVColorSpace color_space_; - - SkShaderBase::Context* y_shader_context_; - SkShaderBase::Context* u_shader_context_; - SkShaderBase::Context* v_shader_context_; - - typedef SkShaderBase::Context INHERITED; - }; - -#if SK_SUPPORT_GPU - std::unique_ptr<GrFragmentProcessor> asFragmentProcessor( - const GrFPArgs&) const override; -#endif - - SK_FLATTENABLE_HOOKS(SkYUV2RGBShader) - - protected: - void flatten(SkWriteBuffer&) const override; - SkShaderBase::Context* onMakeContext(const ContextRec& rec, - SkArenaAlloc* storage) const override; - - private: - void InitializeShaders(); - - SkYUVColorSpace color_space_; - - sk_sp<SkImage> y_image_; - SkMatrix y_matrix_; - sk_sp<SkImageShader> y_shader_; - - sk_sp<SkImage> u_image_; - SkMatrix u_matrix_; - sk_sp<SkImageShader> u_shader_; - - sk_sp<SkImage> v_image_; - SkMatrix v_matrix_; - sk_sp<SkImageShader> v_shader_; - - typedef SkShaderBase INHERITED; -}; - -#endif // COBALT_RENDERER_RASTERIZER_SKIA_SKIA_SRC_EFFECTS_SKYUV2RGBSHADER_H_
diff --git a/src/cobalt/updater/updater_module.cc b/src/cobalt/updater/updater_module.cc index ee9b712..4cba4f3 100644 --- a/src/cobalt/updater/updater_module.cc +++ b/src/cobalt/updater/updater_module.cc
@@ -145,8 +145,13 @@ updater_observer_.reset(); update_client_ = nullptr; - updater_configurator_->GetPrefService()->CommitPendingWrite( - base::BindOnce(&QuitLoop, base::Bind(base::DoNothing::Repeatedly()))); + if (updater_configurator_ != nullptr) { + auto pref_service = updater_configurator_->GetPrefService(); + if (pref_service != nullptr) { + pref_service->CommitPendingWrite( + base::BindOnce(&QuitLoop, base::Bind(base::DoNothing::Repeatedly()))); + } + } updater_configurator_ = nullptr; }
diff --git a/src/starboard/android/apk/app/src/app/AndroidManifest.xml b/src/starboard/android/apk/app/src/app/AndroidManifest.xml index 7337495..bceef34 100644 --- a/src/starboard/android/apk/app/src/app/AndroidManifest.xml +++ b/src/starboard/android/apk/app/src/app/AndroidManifest.xml
@@ -67,4 +67,9 @@ </application> + <queries> + <!-- This is needed to access the speech recognition service in SDK 30 --> + <package android:name="com.google.android.katniss" /> + </queries> + </manifest>
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 bf21be7..fc4907a 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
@@ -537,7 +537,16 @@ return false; } - int[] supportedHdrTypes = defaultDisplay.getHdrCapabilities().getSupportedHdrTypes(); + Display.HdrCapabilities hdrCapabilities = defaultDisplay.getHdrCapabilities(); + if (hdrCapabilities == null) { + return false; + } + + int[] supportedHdrTypes = hdrCapabilities.getSupportedHdrTypes(); + if (supportedHdrTypes == null) { + return false; + } + for (int supportedType : supportedHdrTypes) { if (supportedType == hdrType) { return true;
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 547c67c..e3d0c3c 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
@@ -523,7 +523,7 @@ MediaCrypto crypto) { MediaCodec mediaCodec = null; try { - String decoderName = MediaCodecUtil.findAudioDecoder(mime, 0); + String decoderName = MediaCodecUtil.findAudioDecoder(mime, 0, false); if (decoderName.equals("")) { Log.e(TAG, String.format("Failed to find decoder: %s, isSecure: %s", mime, isSecure)); return null;
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 be473bb..5318110 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
@@ -397,10 +397,19 @@ int frameHeight, int bitrate, int fps, - boolean mustSupportHdr) { + boolean mustSupportHdr, + boolean mustSupportTunnelMode) { FindVideoDecoderResult findVideoDecoderResult = findVideoDecoder( - mimeType, secure, frameWidth, frameHeight, bitrate, fps, mustSupportHdr, false, false); + mimeType, + secure, + frameWidth, + frameHeight, + bitrate, + fps, + mustSupportHdr, + false, + mustSupportTunnelMode); return !findVideoDecoderResult.name.equals("") && (!mustSupportHdr || isHdrCapableVideoDecoder(mimeType, findVideoDecoderResult)); } @@ -411,8 +420,9 @@ */ @SuppressWarnings("unused") @UsedByNative - public static boolean hasAudioDecoderFor(String mimeType, int bitrate) { - return !findAudioDecoder(mimeType, bitrate).equals(""); + public static boolean hasAudioDecoderFor( + String mimeType, int bitrate, boolean mustSupportTunnelMode) { + return !findAudioDecoder(mimeType, bitrate, mustSupportTunnelMode).equals(""); } /** @@ -438,15 +448,6 @@ return isHdrCapableVideoDecoder(mimeType, findVideoDecoderResult); } - /** Determine whether the system support tunneled playback */ - @SuppressWarnings("unused") - @UsedByNative - public static boolean hasTunneledCapableDecoder(String mimeType, boolean isSecure) { - FindVideoDecoderResult findVideoDecoderResult = - findVideoDecoder(mimeType, isSecure, 0, 0, 0, 0, false, false, true); - return !findVideoDecoderResult.name.equals(""); - } - /** Determine whether findVideoDecoderResult is capable of playing HDR */ public static boolean isHdrCapableVideoDecoder( String mimeType, FindVideoDecoderResult findVideoDecoderResult) { @@ -723,7 +724,8 @@ * The same as hasAudioDecoderFor, only return the name of the audio decoder if it is found, and * "" otherwise. */ - public static String findAudioDecoder(String mimeType, int bitrate) { + public static String findAudioDecoder( + String mimeType, int bitrate, boolean requireTunneledPlayback) { // Note: MediaCodecList is sorted by the framework such that the best decoders come first. for (MediaCodecInfo info : new MediaCodecList(MediaCodecList.ALL_CODECS).getCodecInfos()) { if (info.isEncoder()) { @@ -734,13 +736,21 @@ continue; } String name = info.getName(); - AudioCapabilities audioCapabilities = - info.getCapabilitiesForType(supportedType).getAudioCapabilities(); + CodecCapabilities codecCapabilities = info.getCapabilitiesForType(supportedType); + AudioCapabilities audioCapabilities = codecCapabilities.getAudioCapabilities(); Range<Integer> bitrateRange = Range.create(0, audioCapabilities.getBitrateRange().getUpper()); if (!bitrateRange.contains(bitrate)) { continue; } + if (requireTunneledPlayback + && !codecCapabilities.isFeatureSupported(CodecCapabilities.FEATURE_TunneledPlayback)) { + continue; + } + // TODO: Determine if we can safely check if an audio codec requires the tunneled playback + // feature. i.e., reject when |requireTunneledPlayback| == false + // and codecCapabilities.isFeatureRequired(CodecCapabilities.FEATURE_TunneledPlayback) == + // true. return name; } }
diff --git a/src/starboard/android/apk/build.id b/src/starboard/android/apk/build.id deleted file mode 100644 index 57a90bb..0000000 --- a/src/starboard/android/apk/build.id +++ /dev/null
@@ -1 +0,0 @@ -300523 \ No newline at end of file
diff --git a/src/starboard/android/shared/media_is_audio_supported.cc b/src/starboard/android/shared/media_is_audio_supported.cc index e47aaaf..fe8b4ec 100644 --- a/src/starboard/android/shared/media_is_audio_supported.cc +++ b/src/starboard/android/shared/media_is_audio_supported.cc
@@ -16,6 +16,7 @@ #include "starboard/android/shared/jni_utils.h" #include "starboard/android/shared/media_common.h" +#include "starboard/audio_sink.h" #include "starboard/configuration.h" #include "starboard/configuration_constants.h" #include "starboard/media.h" @@ -47,14 +48,36 @@ if (!enable_audio_routing_parameter_value.empty() && enable_audio_routing_parameter_value != "true" && enable_audio_routing_parameter_value != "false") { - SB_LOG(WARNING) << "Invalid value for enableaudiorouting: " - << enable_audio_routing_parameter_value << "."; + SB_LOG(INFO) + << "Invalid value for audio mime parameter \"enableaudiorouting\": " + << enable_audio_routing_parameter_value << "."; return false; } + // Allows for enabling tunneled playback. Disabled by default. + // (https://source.android.com/devices/tv/multimedia-tunneling) + auto enable_tunnel_mode_parameter_value = + mime_type.GetParamStringValue("tunnelmode", ""); + if (!enable_tunnel_mode_parameter_value.empty() && + enable_tunnel_mode_parameter_value != "true" && + enable_tunnel_mode_parameter_value != "false") { + SB_LOG(INFO) << "Invalid value for audio mime parameter \"tunnelmode\": " + << enable_tunnel_mode_parameter_value << "."; + return false; + } else if (enable_tunnel_mode_parameter_value == "true" && + !SbAudioSinkIsAudioSampleTypeSupported( + kSbMediaAudioSampleTypeInt16Deprecated)) { + SB_LOG(WARNING) + << "Tunnel mode is rejected because int16 sample is required " + "but not supported."; + return false; + } + JniEnvExt* env = JniEnvExt::Get(); ScopedLocalJavaRef<jstring> j_mime(env->NewStringStandardUTFOrAbort(mime)); + const bool must_support_tunnel_mode = + enable_tunnel_mode_parameter_value == "true"; return env->CallStaticBooleanMethodOrAbort( "dev/cobalt/media/MediaCodecUtil", "hasAudioDecoderFor", - "(Ljava/lang/String;I)Z", j_mime.Get(), - static_cast<jint>(bitrate)) == JNI_TRUE; + "(Ljava/lang/String;IZ)Z", j_mime.Get(), + static_cast<jint>(bitrate), must_support_tunnel_mode) == JNI_TRUE; }
diff --git a/src/starboard/android/shared/media_is_video_supported.cc b/src/starboard/android/shared/media_is_video_supported.cc index a0c42d0..332e4b2 100644 --- a/src/starboard/android/shared/media_is_video_supported.cc +++ b/src/starboard/android/shared/media_is_video_supported.cc
@@ -20,11 +20,13 @@ #include "starboard/configuration.h" #include "starboard/media.h" #include "starboard/shared/starboard/media/media_util.h" +#include "starboard/shared/starboard/media/mime_type.h" using starboard::android::shared::JniEnvExt; using starboard::android::shared::ScopedLocalJavaRef; using starboard::android::shared::SupportedVideoCodecToMimeType; using starboard::shared::starboard::media::IsSDRVideo; +using starboard::shared::starboard::media::MimeType; namespace { @@ -93,13 +95,38 @@ if (!mime) { return false; } + MimeType mime_type(content_type); + // Allows for enabling tunneled playback. Disabled by default. + // (https://source.android.com/devices/tv/multimedia-tunneling) + auto enable_tunnel_mode_parameter_value = + mime_type.GetParamStringValue("tunnelmode", ""); + if (!enable_tunnel_mode_parameter_value.empty() && + enable_tunnel_mode_parameter_value != "true" && + enable_tunnel_mode_parameter_value != "false") { + SB_LOG(INFO) << "Invalid value for video mime parameter \"tunnelmode\": " + << enable_tunnel_mode_parameter_value << "."; + return false; + } else if (enable_tunnel_mode_parameter_value == "true" && + decode_to_texture_required) { + SB_LOG(WARNING) << "Tunnel mode is rejected because output mode decode to " + "texture is required but not supported."; + return false; + } JniEnvExt* env = JniEnvExt::Get(); ScopedLocalJavaRef<jstring> j_mime(env->NewStringStandardUTFOrAbort(mime)); - bool must_support_hdr = (transfer_id != kSbMediaTransferIdBt709 && - transfer_id != kSbMediaTransferIdUnspecified); + const bool must_support_hdr = (transfer_id != kSbMediaTransferIdBt709 && + transfer_id != kSbMediaTransferIdUnspecified); + const bool must_support_tunnel_mode = + enable_tunnel_mode_parameter_value == "true"; + // We assume that if a device supports a format for clear playback, it will + // also support it for encrypted playback. However, some devices require + // tunneled playback to be encrypted, so we must align the tunnel mode + // requirement with the secure playback requirement. + const bool require_secure_playback = must_support_tunnel_mode; return env->CallStaticBooleanMethodOrAbort( "dev/cobalt/media/MediaCodecUtil", "hasVideoDecoderFor", - "(Ljava/lang/String;ZIIIIZ)Z", j_mime.Get(), false, frame_width, - frame_height, static_cast<jint>(bitrate), fps, - must_support_hdr) == JNI_TRUE; + "(Ljava/lang/String;ZIIIIZZ)Z", j_mime.Get(), + require_secure_playback, frame_width, frame_height, + static_cast<jint>(bitrate), fps, must_support_hdr, + must_support_tunnel_mode) == JNI_TRUE; }
diff --git a/src/starboard/android/shared/player_components_factory.h b/src/starboard/android/shared/player_components_factory.h index c771391..5e1b078 100644 --- a/src/starboard/android/shared/player_components_factory.h +++ b/src/starboard/android/shared/player_components_factory.h
@@ -27,6 +27,7 @@ #include "starboard/android/shared/video_decoder.h" #include "starboard/atomic.h" #include "starboard/common/log.h" +#include "starboard/common/media.h" #include "starboard/common/ref_counted.h" #include "starboard/common/scoped_ptr.h" #include "starboard/media.h" @@ -46,9 +47,8 @@ namespace android { namespace shared { -// Tunnel mode is disabled by default. Set the following variable to true to -// enable tunnel mode. -constexpr bool kTunnelModeEnabled = false; +using starboard::shared::starboard::media::MimeType; + // On some platforms tunnel mode is only supported in the secure pipeline. Set // the following variable to true to force creating a secure pipeline in tunnel // mode, even for clear content. @@ -162,8 +162,43 @@ SB_DCHECK(error_message); int tunnel_mode_audio_session_id = -1; + bool enable_tunnel_mode = false; + if (creation_parameters.audio_codec() != kSbMediaAudioCodecNone && + creation_parameters.video_codec() != kSbMediaVideoCodecNone) { + MimeType audio_mime_type(creation_parameters.audio_mime()); + MimeType video_mime_type(creation_parameters.video_mime()); + auto enable_tunnel_mode_audio_parameter_value = + audio_mime_type.GetParamStringValue("tunnelmode", ""); + auto enable_tunnel_mode_video_parameter_value = + video_mime_type.GetParamStringValue("tunnelmode", ""); + if (enable_tunnel_mode_audio_parameter_value == "true" && + enable_tunnel_mode_video_parameter_value == "true") { + enable_tunnel_mode = true; + } else { + if (enable_tunnel_mode_audio_parameter_value.empty()) { + enable_tunnel_mode_audio_parameter_value = "not provided"; + } + if (enable_tunnel_mode_video_parameter_value.empty()) { + enable_tunnel_mode_video_parameter_value = "not provided"; + } + SB_LOG(INFO) << "Tunnel mode is disabled. Audio mime parameter " + "\"tunnelmode\" value: " + << enable_tunnel_mode_audio_parameter_value + << ", video mime parameter \"tunnelmode\" value: " + << enable_tunnel_mode_video_parameter_value << "."; + } + } else { + SB_LOG(INFO) << "Tunnel mode requires both an audio and video stream. " + << "Audio codec: " + << GetMediaAudioCodecName(creation_parameters.audio_codec()) + << ", Video codec: " + << GetMediaVideoCodecName(creation_parameters.video_codec()) + << ". Tunnel mode is disabled."; + } + bool force_secure_pipeline_under_tunnel_mode = false; - if (IsTunnelModeSupported(creation_parameters, + if (enable_tunnel_mode && + IsTunnelModeSupported(creation_parameters, &force_secure_pipeline_under_tunnel_mode)) { tunnel_mode_audio_session_id = GenerateAudioSessionId(creation_parameters); @@ -205,16 +240,15 @@ GetExtendedDrmSystem(creation_parameters.drm_system()), decoder_creator)); bool enable_audio_routing = true; - starboard::shared::starboard::media::MimeType mime_type( - creation_parameters.audio_mime()); + MimeType audio_mime_type(creation_parameters.audio_mime()); auto enable_audio_routing_parameter_value = - mime_type.GetParamStringValue("enableaudiorouting", ""); + audio_mime_type.GetParamStringValue("enableaudiorouting", ""); if (enable_audio_routing_parameter_value.empty() || enable_audio_routing_parameter_value == "true") { SB_LOG(INFO) << "AudioRouting is enabled."; } else { enable_audio_routing = false; - SB_LOG(INFO) << "Mime attribute enableaudiorouting is set to: " + SB_LOG(INFO) << "Mime attribute \"enableaudiorouting\" is set to: " << enable_audio_routing_parameter_value << ". AudioRouting is disabled."; } @@ -297,11 +331,6 @@ SB_DCHECK(force_secure_pipeline_under_tunnel_mode); *force_secure_pipeline_under_tunnel_mode = false; - if (!kTunnelModeEnabled) { - SB_LOG(INFO) << "Tunnel mode is disabled globally."; - return false; - } - if (!SbAudioSinkIsAudioSampleTypeSupported( kSbMediaAudioSampleTypeInt16Deprecated)) { SB_LOG(INFO) << "Disable tunnel mode because int16 sample is required " @@ -341,8 +370,9 @@ bool is_encrypted = !!j_media_crypto; if (env->CallStaticBooleanMethodOrAbort( - "dev/cobalt/media/MediaCodecUtil", "hasTunneledCapableDecoder", - "(Ljava/lang/String;Z)Z", j_mime.Get(), is_encrypted) == JNI_TRUE) { + "dev/cobalt/media/MediaCodecUtil", "hasVideoDecoderFor", + "(Ljava/lang/String;ZIIIIZZ)Z", j_mime.Get(), is_encrypted, 0, 0, 0, + 0, false, true) == JNI_TRUE) { return true; } @@ -350,8 +380,9 @@ const bool kIsEncrypted = true; auto support_tunnel_mode_under_secure_pipeline = env->CallStaticBooleanMethodOrAbort( - "dev/cobalt/media/MediaCodecUtil", "hasTunneledCapableDecoder", - "(Ljava/lang/String;Z)Z", j_mime.Get(), kIsEncrypted) == JNI_TRUE; + "dev/cobalt/media/MediaCodecUtil", "hasVideoDecoderFor", + "(Ljava/lang/String;ZIIIIZZ)Z", j_mime.Get(), kIsEncrypted, 0, 0, + 0, 0, false, true) == JNI_TRUE; if (support_tunnel_mode_under_secure_pipeline) { *force_secure_pipeline_under_tunnel_mode = true; return true;
diff --git a/src/starboard/doc/evergreen/cobalt_evergreen_overview.md b/src/starboard/doc/evergreen/cobalt_evergreen_overview.md index c8a3272..247d19f 100644 --- a/src/starboard/doc/evergreen/cobalt_evergreen_overview.md +++ b/src/starboard/doc/evergreen/cobalt_evergreen_overview.md
@@ -435,6 +435,8 @@ ├── installation_store_<APP_KEY>.pb └── icu (default location shared by installation slots, to be explained below) ``` +Note that after the Cobalt binary is loaded by the loader_app, `kSbSystemPathContentDirectory` points to the +content directory of the running binary, as stated in Starboard Module Reference of system.h. #### App metadata Each Cobalt Evergreen application has a set of unique metadata to track slot
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 a3c0d50..c931500 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
@@ -506,7 +506,7 @@ double playback_rate; auto media_time = media_time_provider_->GetCurrentMediaTime( &is_playing, &is_eos_played, &is_underflow, &playback_rate); - update_media_info_cb_(media_time, dropped_frames, is_underflow); + update_media_info_cb_(media_time, dropped_frames, !is_underflow); } update_job_token_ = Schedule(update_job_, kUpdateInterval);
diff --git a/src/starboard/shared/starboard/player/player_internal.cc b/src/starboard/shared/starboard/player/player_internal.cc index c273223..5a6b20b 100644 --- a/src/starboard/shared/starboard/player/player_internal.cc +++ b/src/starboard/shared/starboard/player/player_internal.cc
@@ -29,9 +29,9 @@ using std::placeholders::_3; using std::placeholders::_4; -SbTime GetMediaTime(SbTime media_time, - SbTimeMonotonic media_time_update_time, - double playback_rate) { +SbTime CalculateMediaTime(SbTime media_time, + SbTimeMonotonic media_time_update_time, + double playback_rate) { SbTimeMonotonic elapsed = SbTimeGetMonotonicNow() - media_time_update_time; return media_time + static_cast<SbTime>(elapsed * playback_rate); } @@ -61,9 +61,8 @@ worker_ = starboard::make_scoped_ptr(PlayerWorker::CreateInstance( audio_codec, video_codec, player_worker_handler.Pass(), std::bind(&SbPlayerPrivate::UpdateMediaInfo, this, _1, _2, _3, _4), - decoder_status_func, player_status_func, - player_error_func, - this, context)); + decoder_status_func, player_status_func, player_error_func, this, + context)); ++number_of_players_; SB_DLOG(INFO) << "Creating SbPlayerPrivate. There are " << number_of_players_ @@ -83,9 +82,8 @@ 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, - player_error_func, - context, player_worker_handler.Pass()); + decoder_status_func, player_status_func, player_error_func, context, + player_worker_handler.Pass()); if (ret && ret->worker_) { return ret; @@ -100,6 +98,7 @@ SB_DCHECK(ticket_ != ticket); media_time_ = seek_to_time; media_time_updated_at_ = SbTimeGetMonotonicNow(); + is_progressing_ = false; ticket_ = ticket; } @@ -159,11 +158,11 @@ starboard::ScopedLock lock(mutex_); out_player_info->duration = SB_PLAYER_NO_DURATION; - if (is_paused_ || underflow_) { + if (is_paused_ || !is_progressing_) { out_player_info->current_media_timestamp = media_time_; } else { out_player_info->current_media_timestamp = - GetMediaTime(media_time_, media_time_updated_at_, playback_rate_); + CalculateMediaTime(media_time_, media_time_updated_at_, playback_rate_); } out_player_info->frame_width = frame_width_; @@ -194,13 +193,13 @@ void SbPlayerPrivate::UpdateMediaInfo(SbTime media_time, int dropped_video_frames, int ticket, - bool underflow) { + bool is_progressing) { starboard::ScopedLock lock(mutex_); if (ticket_ != ticket) { return; } media_time_ = media_time; - underflow_ = underflow; + is_progressing_ = is_progressing; media_time_updated_at_ = SbTimeGetMonotonicNow(); dropped_video_frames_ = dropped_video_frames; }
diff --git a/src/starboard/shared/starboard/player/player_internal.h b/src/starboard/shared/starboard/player/player_internal.h index 4a94236..559531f 100644 --- a/src/starboard/shared/starboard/player/player_internal.h +++ b/src/starboard/shared/starboard/player/player_internal.h
@@ -82,7 +82,7 @@ void UpdateMediaInfo(SbTime media_time, int dropped_video_frames, int ticket, - bool underflow); + bool is_progressing); SbPlayerDeallocateSampleFunc sample_deallocate_func_; void* context_; @@ -101,7 +101,9 @@ double volume_ = 1.0; int total_video_frames_ = 0; int dropped_video_frames_ = 0; - bool underflow_ = false; + // Used to determine if |worker_| is progressing with playback so that + // we may extrapolate the media time in GetInfo(). + bool is_progressing_ = false; starboard::scoped_ptr<PlayerWorker> worker_;
diff --git a/src/starboard/shared/starboard/player/player_worker.cc b/src/starboard/shared/starboard/player/player_worker.cc index c4f3110..1a1a557 100644 --- a/src/starboard/shared/starboard/player/player_worker.cc +++ b/src/starboard/shared/starboard/player/player_worker.cc
@@ -68,12 +68,10 @@ SbPlayerErrorFunc player_error_func, SbPlayer player, void* context) { - - PlayerWorker* ret = new PlayerWorker(audio_codec, video_codec, handler.Pass(), - update_media_info_cb, - decoder_status_func, player_status_func, - player_error_func, - player, context); + PlayerWorker* ret = + new PlayerWorker(audio_codec, video_codec, handler.Pass(), + update_media_info_cb, decoder_status_func, + player_status_func, player_error_func, player, context); if (ret && SbThreadIsValid(ret->thread_)) { return ret; @@ -139,8 +137,9 @@ void PlayerWorker::UpdateMediaInfo(SbTime time, int dropped_video_frames, - bool underflow) { - update_media_info_cb_(time, dropped_video_frames, ticket_, underflow); + bool is_progressing) { + SB_DCHECK(player_state_ == kSbPlayerStatePresenting); + update_media_info_cb_(time, dropped_video_frames, ticket_, is_progressing); } void PlayerWorker::UpdatePlayerState(SbPlayerState player_state) {
diff --git a/src/starboard/shared/starboard/player/player_worker.h b/src/starboard/shared/starboard/player/player_worker.h index 6c70552..3539c31 100644 --- a/src/starboard/shared/starboard/player/player_worker.h +++ b/src/starboard/shared/starboard/player/player_worker.h
@@ -46,7 +46,7 @@ typedef std::function<void(SbTime media_time, int dropped_video_frames, int ticket, - bool underflow)> + bool is_progressing)> UpdateMediaInfoCB; struct Bounds { @@ -61,7 +61,7 @@ class Handler { public: typedef std::function< - void(SbTime media_time, int dropped_video_frames, bool underflow)> + void(SbTime media_time, int dropped_video_frames, bool is_progressing)> UpdateMediaInfoCB; typedef std::function<SbPlayerState()> GetPlayerStateCB; typedef std::function<void(SbPlayerState player_state)> UpdatePlayerStateCB;