diff --git a/DEPS b/DEPS index d4d41eb..40a49997 100644 --- a/DEPS +++ b/DEPS
@@ -39,7 +39,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '262a71b7f95ce98ff3dd8dba845afbd724470903', + 'skia_revision': '776d49b41bb2aaa77f1d02a06963ff4266b502be', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other.
diff --git a/android_webview/browser/net/aw_url_request_context_getter.cc b/android_webview/browser/net/aw_url_request_context_getter.cc index 7e39d1cd..484259b 100644 --- a/android_webview/browser/net/aw_url_request_context_getter.cc +++ b/android_webview/browser/net/aw_url_request_context_getter.cc
@@ -220,7 +220,7 @@ network_session_params; ApplyCmdlineOverridesToNetworkSessionParams(&network_session_params); builder.set_http_network_session_params(network_session_params); - builder.SetSpdyAndQuicEnabled(true, true); + builder.SetSpdyAndQuicEnabled(true, false); scoped_ptr<net::MappedHostResolver> host_resolver(new net::MappedHostResolver( net::HostResolver::CreateDefaultResolver(nullptr)));
diff --git a/base/command_line.cc b/base/command_line.cc index c2ce33d..e2dde1cd 100644 --- a/base/command_line.cc +++ b/base/command_line.cc
@@ -75,7 +75,11 @@ bool parse_switches = true; for (size_t i = 1; i < argv.size(); ++i) { CommandLine::StringType arg = argv[i]; +#if defined(OS_WIN) TrimWhitespace(arg, TRIM_ALL, &arg); +#else + TrimWhitespaceASCII(arg, TRIM_ALL, &arg); +#endif CommandLine::StringType switch_string; CommandLine::StringType switch_value; @@ -263,7 +267,11 @@ } void CommandLine::SetProgram(const FilePath& program) { +#if defined(OS_WIN) TrimWhitespace(program.value(), TRIM_ALL, &argv_[0]); +#else + TrimWhitespaceASCII(program.value(), TRIM_ALL, &argv_[0]); +#endif } bool CommandLine::HasSwitch(const base::StringPiece& switch_string) const {
diff --git a/base/strings/string_util.cc b/base/strings/string_util.cc index 731a77d..72b85006 100644 --- a/base/strings/string_util.cc +++ b/base/strings/string_util.cc
@@ -403,14 +403,6 @@ return TrimStringPieceT(input, StringPiece(kWhitespaceASCII), positions); } -// This function is only for backward-compatibility. -// To be removed when all callers are updated. -TrimPositions TrimWhitespace(const std::string& input, - TrimPositions positions, - std::string* output) { - return TrimWhitespaceASCII(input, positions, output); -} - template<typename STR> STR CollapseWhitespaceT(const STR& text, bool trim_sequences_with_line_breaks) {
diff --git a/base/strings/string_util.h b/base/strings/string_util.h index 3976111..af7b6e6ae9 100644 --- a/base/strings/string_util.h +++ b/base/strings/string_util.h
@@ -243,12 +243,6 @@ BASE_EXPORT StringPiece TrimWhitespaceASCII(StringPiece input, TrimPositions positions); -// Deprecated. This function is only for backward compatibility and calls -// TrimWhitespaceASCII(). -BASE_EXPORT TrimPositions TrimWhitespace(const std::string& input, - TrimPositions positions, - std::string* output); - // Searches for CR or LF characters. Removes all contiguous whitespace // strings that contain them. This is useful when trying to deal with text // copied from terminals.
diff --git a/base/strings/string_util_unittest.cc b/base/strings/string_util_unittest.cc index 765ba83..1db7746 100644 --- a/base/strings/string_util_unittest.cc +++ b/base/strings/string_util_unittest.cc
@@ -250,7 +250,7 @@ for (size_t i = 0; i < arraysize(trim_cases_ascii); ++i) { const trim_case_ascii& value = trim_cases_ascii[i]; EXPECT_EQ(value.return_value, - TrimWhitespace(value.input, value.positions, &output_ascii)); + TrimWhitespaceASCII(value.input, value.positions, &output_ascii)); EXPECT_EQ(value.output, output_ascii); } }
diff --git a/cc/base/switches.cc b/cc/base/switches.cc index 13a9735..af836e3f 100644 --- a/cc/base/switches.cc +++ b/cc/base/switches.cc
@@ -56,10 +56,10 @@ // Enables the GPU benchmarking extension const char kEnableGpuBenchmarking[] = "enable-gpu-benchmarking"; -// Enables the use of property trees rather than CalcDrawProps for computing +// Disables the use of property trees rather than CalcDrawProps for computing // draw properties. -const char kEnableCompositorPropertyTrees[] = - "enable-compositor-property-trees"; +const char kDisableCompositorPropertyTrees[] = + "disable-compositor-property-trees"; // Renders a border around compositor layers to help debug and study // layer compositing.
diff --git a/cc/base/switches.h b/cc/base/switches.h index bd5b2eb..3465eaf9 100644 --- a/cc/base/switches.h +++ b/cc/base/switches.h
@@ -30,7 +30,7 @@ // Switches for both the renderer and ui compositors. CC_EXPORT extern const char kEnableBeginFrameScheduling[]; CC_EXPORT extern const char kEnableGpuBenchmarking[]; -CC_EXPORT extern const char kEnableCompositorPropertyTrees[]; +CC_EXPORT extern const char kDisableCompositorPropertyTrees[]; // Debug visualizations. CC_EXPORT extern const char kShowCompositedLayerBorders[];
diff --git a/cc/surfaces/BUILD.gn b/cc/surfaces/BUILD.gn index 6dd7240..cfb42b7 100644 --- a/cc/surfaces/BUILD.gn +++ b/cc/surfaces/BUILD.gn
@@ -33,6 +33,7 @@ "surface_factory_client.h", "surface_hittest.cc", "surface_hittest.h", + "surface_hittest_delegate.h", "surface_id_allocator.cc", "surface_id_allocator.h", "surface_manager.cc",
diff --git a/cc/surfaces/surface_hittest.cc b/cc/surfaces/surface_hittest.cc index b7414de..1f443d6 100644 --- a/cc/surfaces/surface_hittest.cc +++ b/cc/surfaces/surface_hittest.cc
@@ -10,15 +10,16 @@ #include "cc/quads/render_pass_draw_quad.h" #include "cc/quads/surface_draw_quad.h" #include "cc/surfaces/surface.h" +#include "cc/surfaces/surface_hittest_delegate.h" #include "cc/surfaces/surface_manager.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/transform.h" namespace cc { -namespace { -} -SurfaceHittest::SurfaceHittest(SurfaceManager* manager) : manager_(manager) {} +SurfaceHittest::SurfaceHittest(SurfaceHittestDelegate* delegate, + SurfaceManager* manager) + : delegate_(delegate), manager_(manager) {} SurfaceHittest::~SurfaceHittest() {} @@ -95,6 +96,11 @@ // Surface. const SurfaceDrawQuad* surface_quad = SurfaceDrawQuad::MaterialCast(quad); + if (delegate_ && + delegate_->RejectHitTarget(surface_quad, point_in_quad_space)) { + continue; + } + gfx::Transform transform_to_child_space; if (GetTargetSurfaceAtPointInternal( surface_quad->surface_id, RenderPassId(), point_in_quad_space,
diff --git a/cc/surfaces/surface_hittest.h b/cc/surfaces/surface_hittest.h index 60fa8937..ce45a90f 100644 --- a/cc/surfaces/surface_hittest.h +++ b/cc/surfaces/surface_hittest.h
@@ -16,16 +16,18 @@ } namespace cc { + class DrawQuad; class QuadList; class RenderPass; class RenderPassId; +class SurfaceHittestDelegate; class SurfaceManager; // Performs a hittest in surface quads. class CC_SURFACES_EXPORT SurfaceHittest { public: - explicit SurfaceHittest(SurfaceManager* manager); + SurfaceHittest(SurfaceHittestDelegate* delegate, SurfaceManager* manager); ~SurfaceHittest(); // Returns the target surface that falls underneath the provided |point|. @@ -67,6 +69,7 @@ gfx::Transform* target_to_quad_transform, gfx::Point* point_in_quad_space); + SurfaceHittestDelegate* const delegate_; SurfaceManager* const manager_; }; } // namespace cc
diff --git a/cc/surfaces/surface_hittest_delegate.h b/cc/surfaces/surface_hittest_delegate.h new file mode 100644 index 0000000..1f0fbf9 --- /dev/null +++ b/cc/surfaces/surface_hittest_delegate.h
@@ -0,0 +1,24 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_SURFACES_SURFACE_HITTEST_DELEGATE_H_ +#define CC_SURFACES_SURFACE_HITTEST_DELEGATE_H_ + +namespace cc { + +class SurfaceDrawQuad; + +// Clients of SurfaceHittest can provide a SurfaceHittestDelegate implementation +// to override the hit target based on metadata outside of the Surfaces system. +class SurfaceHittestDelegate { + public: + // Return true if this delegate rejects this |surface_quad| as a candidate hit + // target. + virtual bool RejectHitTarget(const SurfaceDrawQuad* surface_quad, + const gfx::Point& point_in_quad_space) = 0; +}; + +} // namespace cc + +#endif // CC_SURFACES_SURFACE_HITTEST_DELEGATE_H_
diff --git a/cc/surfaces/surface_hittest_unittest.cc b/cc/surfaces/surface_hittest_unittest.cc index 2b59f0a..144d0d6e 100644 --- a/cc/surfaces/surface_hittest_unittest.cc +++ b/cc/surfaces/surface_hittest_unittest.cc
@@ -25,8 +25,11 @@ gfx::Point expected_output_point; }; -void RunTests(SurfaceManager* manager, TestCase* tests, size_t test_count) { - SurfaceHittest hittest(manager); +void RunTests(SurfaceHittestDelegate* delegate, + SurfaceManager* manager, + TestCase* tests, + size_t test_count) { + SurfaceHittest hittest(delegate, manager); for (size_t i = 0; i < test_count; ++i) { const TestCase& test = tests[i]; gfx::Point point(test.input_point); @@ -83,7 +86,7 @@ SurfaceFactory::DrawCallback()); { - SurfaceHittest hittest(&manager); + SurfaceHittest hittest(nullptr, &manager); // It is expected this test will complete without crashes. gfx::Transform transform; EXPECT_EQ(root_surface_id, @@ -120,7 +123,7 @@ }, }; - RunTests(&manager, tests, arraysize(tests)); + RunTests(nullptr, &manager, tests, arraysize(tests)); factory.Destroy(root_surface_id); } @@ -215,7 +218,7 @@ } }; - RunTests(&manager, tests, arraysize(tests)); + RunTests(nullptr, &manager, tests, arraysize(tests)); // Submit another root frame, with a slightly perturbed child Surface. root_frame = CreateCompositorFrame(root_rect, &root_pass); @@ -233,7 +236,7 @@ // Verify that point (100, 100) no longer falls on the child surface. // Verify that the transform to the child surface's space has also shifted. { - SurfaceHittest hittest(&manager); + SurfaceHittest hittest(nullptr, &manager); gfx::Point point(100, 100); gfx::Transform transform; @@ -355,7 +358,7 @@ } }; - RunTests(&manager, tests, arraysize(tests)); + RunTests(nullptr, &manager, tests, arraysize(tests)); factory.Destroy(root_surface_id); factory.Destroy(child_surface_id); @@ -459,7 +462,131 @@ } }; - RunTests(&manager, tests, arraysize(tests)); + RunTests(nullptr, &manager, tests, arraysize(tests)); + + factory.Destroy(root_surface_id); +} + +TEST(SurfaceHittestTest, Hittest_SingleSurface_WithInsetsDelegate) { + SurfaceManager manager; + EmptySurfaceFactoryClient client; + SurfaceFactory factory(&manager, &client); + + // Creates a root surface. + gfx::Rect root_rect(300, 300); + RenderPass* root_pass = nullptr; + scoped_ptr<CompositorFrame> root_frame = + CreateCompositorFrame(root_rect, &root_pass); + + // Add a reference to the child surface on the root surface. + SurfaceIdAllocator child_allocator(3); + SurfaceId child_surface_id = child_allocator.GenerateId(); + gfx::Rect child_rect(200, 200); + CreateSurfaceDrawQuad( + root_pass, + gfx::Transform(1.0f, 0.0f, 0.0f, 50.0f, + 0.0f, 1.0f, 0.0f, 50.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f), + root_rect, child_rect, child_surface_id); + + // Submit the root frame. + SurfaceIdAllocator root_allocator(2); + SurfaceId root_surface_id = root_allocator.GenerateId(); + factory.Create(root_surface_id); + factory.SubmitCompositorFrame(root_surface_id, std::move(root_frame), + SurfaceFactory::DrawCallback()); + + // Creates a child surface. + RenderPass* child_pass = nullptr; + scoped_ptr<CompositorFrame> child_frame = + CreateCompositorFrame(child_rect, &child_pass); + + // Add a solid quad in the child surface. + gfx::Rect child_solid_quad_rect(200, 200); + CreateSolidColorDrawQuad( + child_pass, + gfx::Transform(), + root_rect, child_solid_quad_rect); + + // Submit the frame. + factory.Create(child_surface_id); + factory.SubmitCompositorFrame(child_surface_id, std::move(child_frame), + SurfaceFactory::DrawCallback()); + + TestCase test_expectations_without_insets[] = { + { + root_surface_id, + gfx::Point(50, 50), + child_surface_id, + gfx::Point(0, 0) + }, + { + root_surface_id, + gfx::Point(60, 60), + child_surface_id, + gfx::Point(10, 10) + }, + { + root_surface_id, + gfx::Point(239, 239), + child_surface_id, + gfx::Point(189, 189) + }, + { + root_surface_id, + gfx::Point(249, 249), + child_surface_id, + gfx::Point(199, 199) + }, + }; + + TestSurfaceHittestDelegate delegate; + RunTests(&delegate, &manager, test_expectations_without_insets, + arraysize(test_expectations_without_insets)); + + // Verify that insets have NOT affected hit targeting. + EXPECT_EQ(0, delegate.target_overrides()); + + delegate.AddInsetsForSurface(child_surface_id, gfx::Insets(10, 10, 10, 10)); + + TestCase test_expectations_with_insets[] = { + // Point (50, 50) falls outside the child surface due to the insets + // introduced above. + { + root_surface_id, + gfx::Point(50, 50), + root_surface_id, + gfx::Point(50, 50) + }, + // These two points still fall within the child surface. + { + root_surface_id, + gfx::Point(60, 60), + child_surface_id, + gfx::Point(10, 10) + }, + { + root_surface_id, + gfx::Point(239, 239), + child_surface_id, + gfx::Point(189, 189) + }, + // Point (249, 249) falls outside the child surface due to the insets + // introduced above. + { + root_surface_id, + gfx::Point(249, 249), + root_surface_id, + gfx::Point(249, 249) + }, + }; + + RunTests(&delegate, &manager, test_expectations_with_insets, + arraysize(test_expectations_with_insets)); + + // Verify that insets have affected hit targeting. + EXPECT_EQ(2, delegate.target_overrides()); factory.Destroy(root_surface_id); }
diff --git a/cc/test/data/background_filter_on_scaled_layer_gl.png b/cc/test/data/background_filter_on_scaled_layer_gl.png index 83cb2c5..fc5c8f9c 100644 --- a/cc/test/data/background_filter_on_scaled_layer_gl.png +++ b/cc/test/data/background_filter_on_scaled_layer_gl.png Binary files differ
diff --git a/cc/test/surface_hittest_test_helpers.cc b/cc/test/surface_hittest_test_helpers.cc index 8c579597..b83d6d4b 100644 --- a/cc/test/surface_hittest_test_helpers.cc +++ b/cc/test/surface_hittest_test_helpers.cc
@@ -92,5 +92,32 @@ return root_frame; } +TestSurfaceHittestDelegate::TestSurfaceHittestDelegate() + : target_overrides_(0) {} + +TestSurfaceHittestDelegate::~TestSurfaceHittestDelegate() {} + +void TestSurfaceHittestDelegate::AddInsetsForSurface( + const SurfaceId& surface_id, + const gfx::Insets& inset) { + insets_for_surface_.insert(std::make_pair(surface_id, inset)); +} + +bool TestSurfaceHittestDelegate::RejectHitTarget( + const SurfaceDrawQuad* surface_quad, + const gfx::Point& point_in_quad_space) { + if (!insets_for_surface_.count(surface_quad->surface_id)) + return false; + gfx::Rect bounds(surface_quad->rect); + bounds.Inset(insets_for_surface_[surface_quad->surface_id]); + // If the point provided falls outside the inset, then we skip this surface. + if (!bounds.Contains(point_in_quad_space)) { + if (surface_quad->rect.Contains(point_in_quad_space)) + ++target_overrides_; + return true; + } + return false; +} + } // namespace test } // namespace cc
diff --git a/cc/test/surface_hittest_test_helpers.h b/cc/test/surface_hittest_test_helpers.h index be4ad2e..4a276592 100644 --- a/cc/test/surface_hittest_test_helpers.h +++ b/cc/test/surface_hittest_test_helpers.h
@@ -5,9 +5,14 @@ #ifndef CC_TEST_SURFACE_HITTEST_TEST_HELPERS_H_ #define CC_TEST_SURFACE_HITTEST_TEST_HELPERS_H_ +#include <map> + +#include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "cc/quads/render_pass.h" #include "cc/surfaces/surface_factory_client.h" +#include "cc/surfaces/surface_hittest_delegate.h" +#include "ui/gfx/geometry/insets.h" namespace gfx { class Transform; @@ -60,6 +65,27 @@ scoped_ptr<CompositorFrame> CreateCompositorFrame(const gfx::Rect& root_rect, RenderPass** render_pass); +class TestSurfaceHittestDelegate : public SurfaceHittestDelegate { + public: + TestSurfaceHittestDelegate(); + ~TestSurfaceHittestDelegate(); + + int target_overrides() const { return target_overrides_; } + + void AddInsetsForSurface(const SurfaceId& surface_id, + const gfx::Insets& inset); + + // SurfaceHittestDelegate implementation. + bool RejectHitTarget(const SurfaceDrawQuad* surface_quad, + const gfx::Point& point_in_quad_space) override; + + private: + int target_overrides_; + std::map<SurfaceId, gfx::Insets> insets_for_surface_; + + DISALLOW_COPY_AND_ASSIGN(TestSurfaceHittestDelegate); +}; + } // namespace test } // namespace cc
diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc index 9ab91f03..b155373 100644 --- a/cc/trees/layer_tree_host_common.cc +++ b/cc/trees/layer_tree_host_common.cc
@@ -128,7 +128,7 @@ true, false, true, - false, + true, render_surface_layer_list, current_render_surface_layer_list_id, GetPropertyTrees(root_layer)) {
diff --git a/cc/trees/layer_tree_settings.cc b/cc/trees/layer_tree_settings.cc index 7ff78b3..1a978fb 100644 --- a/cc/trees/layer_tree_settings.cc +++ b/cc/trees/layer_tree_settings.cc
@@ -59,7 +59,7 @@ scheduled_raster_task_limit(32), use_occlusion_for_tile_prioritization(false), verify_property_trees(false), - use_property_trees(false), + use_property_trees(true), image_decode_tasks_enabled(false), use_compositor_animation_timelines(false), wait_for_beginframe_interval(true),
diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc index 627ee4b..e2a1584f 100644 --- a/chrome/browser/chromeos/login/chrome_restart_request.cc +++ b/chrome/browser/chromeos/login/chrome_restart_request.cc
@@ -189,10 +189,10 @@ // content/browser/renderer_host/render_process_host_impl.cc. cc::switches::kDisableCachedPictureRaster, cc::switches::kDisableCompositedAntialiasing, + cc::switches::kDisableCompositorPropertyTrees, cc::switches::kDisableMainFrameBeforeActivation, cc::switches::kDisableThreadedAnimation, cc::switches::kEnableBeginFrameScheduling, - cc::switches::kEnableCompositorPropertyTrees, cc::switches::kEnableGpuBenchmarking, cc::switches::kEnablePropertyTreeVerification, cc::switches::kEnableMainFrameBeforeActivation,
diff --git a/chrome/browser/chromeos/power/cpu_data_collector.cc b/chrome/browser/chromeos/power/cpu_data_collector.cc index 3166c60..21c65fa4 100644 --- a/chrome/browser/chromeos/power/cpu_data_collector.cc +++ b/chrome/browser/chromeos/power/cpu_data_collector.cc
@@ -94,7 +94,8 @@ std::string cpu_online_string; if (base::ReadFileToString(base::FilePath(cpu_online_file), &cpu_online_string)) { - base::TrimWhitespace(cpu_online_string, base::TRIM_ALL, &cpu_online_string); + base::TrimWhitespaceASCII(cpu_online_string, base::TRIM_ALL, + &cpu_online_string); if (base::StringToInt(cpu_online_string, &online)) return online == kCpuOnlineStatus; } @@ -159,9 +160,9 @@ return; } - base::TrimWhitespace(state_name, base::TRIM_ALL, &state_name); - base::TrimWhitespace( - occupancy_time_string, base::TRIM_ALL, &occupancy_time_string); + base::TrimWhitespaceASCII(state_name, base::TRIM_ALL, &state_name); + base::TrimWhitespaceASCII(occupancy_time_string, base::TRIM_ALL, + &occupancy_time_string); if (base::StringToInt64(occupancy_time_string, &occupancy_time_usec)) { // idle state occupancy time in sysfs is recorded in microseconds. int64 time_in_state_ms = occupancy_time_usec / 1000; @@ -324,7 +325,8 @@ int max_cpu; // The possible CPUs are listed in the format "0-N". Hence, N is present // in the substring starting at offset 2. - base::TrimWhitespace(possible_string, base::TRIM_ALL, &possible_string); + base::TrimWhitespaceASCII(possible_string, base::TRIM_ALL, + &possible_string); if (possible_string.find("-") != std::string::npos && possible_string.length() > 2 && base::StringToInt(possible_string.substr(2), &max_cpu)) {
diff --git a/chrome/browser/devtools/device/android_device_manager.cc b/chrome/browser/devtools/device/android_device_manager.cc index 3426726d..e7c58b6 100644 --- a/chrome/browser/devtools/device/android_device_manager.cc +++ b/chrome/browser/devtools/device/android_device_manager.cc
@@ -223,7 +223,7 @@ std::string value = response_.substr( start_pos + header.length(), endline_pos - start_pos - header.length()); - base::TrimWhitespace(value, base::TRIM_ALL, &value); + base::TrimWhitespaceASCII(value, base::TRIM_ALL, &value); return value; }
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_apitest.cc b/chrome/browser/extensions/api/developer_private/developer_private_apitest.cc index 68f1b2f..ec28633 100644 --- a/chrome/browser/extensions/api/developer_private/developer_private_apitest.cc +++ b/chrome/browser/extensions/api/developer_private/developer_private_apitest.cc
@@ -8,7 +8,9 @@ #include "chrome/browser/extensions/api/developer_private/developer_private_api.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/extensions/extension_function_test_utils.h" +#include "chrome/browser/extensions/extension_tab_util.h" #include "chrome/common/chrome_paths.h" +#include "content/public/browser/render_frame_host.h" #include "extensions/browser/app_window/app_window.h" #include "extensions/browser/app_window/app_window_registry.h" @@ -81,4 +83,52 @@ (*app_windows.begin())->web_contents())); } +IN_PROC_BROWSER_TEST_F(DeveloperPrivateApiTest, InspectEmbeddedOptionsPage) { + base::FilePath dir; + PathService::Get(chrome::DIR_TEST_DATA, &dir); + // Load an extension that only has an embedded options_ui page. + const Extension* extension = LoadExtension(dir.AppendASCII("extensions") + .AppendASCII("delayed_install") + .AppendASCII("v1")); + ASSERT_TRUE(extension); + + // Open the embedded options page. + ASSERT_TRUE(ExtensionTabUtil::OpenOptionsPage(extension, browser())); + WaitForExtensionNotIdle(extension->id()); + + // Get the info about the extension, including the inspectable views. + scoped_refptr<UIThreadExtensionFunction> function( + new api::DeveloperPrivateGetExtensionInfoFunction()); + scoped_ptr<base::Value> result( + extension_function_test_utils::RunFunctionAndReturnSingleResult( + function.get(), + base::StringPrintf("[\"%s\"]", extension->id().c_str()), browser())); + ASSERT_TRUE(result); + scoped_ptr<api::developer_private::ExtensionInfo> info = + api::developer_private::ExtensionInfo::FromValue(*result); + ASSERT_TRUE(info); + + // The embedded options page should show up. + ASSERT_EQ(1u, info->views.size()); + api::developer_private::ExtensionView* view = info->views[0].get(); + ASSERT_TRUE(view); + ASSERT_EQ(api::developer_private::VIEW_TYPE_EXTENSION_GUEST, view->type); + + // Inspect the embedded options page. + function = new api::DeveloperPrivateOpenDevToolsFunction(); + extension_function_test_utils::RunFunction( + function.get(), + base::StringPrintf("[{\"renderViewId\": %d, \"renderProcessId\": %d}]", + view->render_view_id, view->render_process_id), + browser(), extension_function_test_utils::NONE); + + // Verify that dev tools opened. + content::RenderFrameHost* rfh = content::RenderFrameHost::FromID( + view->render_process_id, view->render_view_id); + ASSERT_TRUE(rfh); + content::WebContents* wc = content::WebContents::FromRenderFrameHost(rfh); + ASSERT_TRUE(wc); + EXPECT_TRUE(DevToolsWindow::GetInstanceForInspectedWebContents(wc)); +} + } // namespace extensions
diff --git a/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc b/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc index 93d90f4..e588caf 100644 --- a/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc +++ b/chrome/browser/extensions/api/developer_private/inspectable_views_finder.cc
@@ -60,6 +60,9 @@ case VIEW_TYPE_EXTENSION_DIALOG: view->type = api::developer_private::VIEW_TYPE_EXTENSION_DIALOG; break; + case VIEW_TYPE_EXTENSION_GUEST: + view->type = api::developer_private::VIEW_TYPE_EXTENSION_GUEST; + break; case VIEW_TYPE_EXTENSION_POPUP: view->type = api::developer_private::VIEW_TYPE_EXTENSION_POPUP; break; @@ -148,8 +151,10 @@ content::WebContents* web_contents = content::WebContents::FromRenderFrameHost(host); ViewType host_type = GetViewType(web_contents); - if (host_type == VIEW_TYPE_EXTENSION_POPUP || - host_type == VIEW_TYPE_EXTENSION_DIALOG) { + if (host_type == VIEW_TYPE_INVALID || + host_type == VIEW_TYPE_EXTENSION_POPUP || + host_type == VIEW_TYPE_EXTENSION_DIALOG || + host_type == VIEW_TYPE_APP_WINDOW) { continue; }
diff --git a/chrome/browser/extensions/chrome_extensions_browser_client.cc b/chrome/browser/extensions/chrome_extensions_browser_client.cc index abae1f8..14999a8 100644 --- a/chrome/browser/extensions/chrome_extensions_browser_client.cc +++ b/chrome/browser/extensions/chrome_extensions_browser_client.cc
@@ -366,10 +366,12 @@ return; case VIEW_TYPE_BACKGROUND_CONTENTS: + case VIEW_TYPE_EXTENSION_GUEST: case VIEW_TYPE_PANEL: case VIEW_TYPE_TAB_CONTENTS: // Those types are tracked by other tags: // BACKGROUND_CONTENTS --> task_management::BackgroundContentsTag. + // GUEST --> extensions::ChromeGuestViewManagerDelegate. // PANEL --> task_management::PanelTag. // TAB_CONTENTS --> task_management::TabContentsTag. // These tags are created and attached to the web_contents in other
diff --git a/chrome/browser/extensions/extension_messages_apitest.cc b/chrome/browser/extensions/extension_messages_apitest.cc index 9419781..54c44fe 100644 --- a/chrome/browser/extensions/extension_messages_apitest.cc +++ b/chrome/browser/extensions/extension_messages_apitest.cc
@@ -123,6 +123,14 @@ ASSERT_TRUE(RunExtensionTest("messaging/connect_external")) << message_; } +// Tests that a content script can exchange messages with a tab even if there is +// no background page. +IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MessagingNoBackground) { + ASSERT_TRUE(StartEmbeddedTestServer()); + ASSERT_TRUE(RunExtensionSubtest("messaging/connect_nobackground", + "page_in_main_frame.html")) << message_; +} + // Tests that messages with event_urls are only passed to extensions with // appropriate permissions. IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MessagingEventURL) {
diff --git a/chrome/browser/extensions/process_manager_browsertest.cc b/chrome/browser/extensions/process_manager_browsertest.cc index 3596cbc..d1e3013 100644 --- a/chrome/browser/extensions/process_manager_browsertest.cc +++ b/chrome/browser/extensions/process_manager_browsertest.cc
@@ -4,23 +4,182 @@ #include "extensions/browser/process_manager.h" +#include "base/callback.h" +#include "base/memory/scoped_ptr.h" +#include "base/run_loop.h" +#include "base/strings/stringprintf.h" #include "chrome/browser/extensions/browser_action_test_util.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/extensions/test_extension_dir.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/common/extensions/extension_process_policy.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/notification_service.h" +#include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" +#include "content/public/test/browser_test_utils.h" #include "content/public/test/test_utils.h" +#include "extensions/common/value_builder.h" +#include "extensions/test/background_page_watcher.h" +#include "extensions/test/extension_test_message_listener.h" #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" namespace extensions { +namespace { + +void AddFrameToSet(std::set<content::RenderFrameHost*>* frames, + content::RenderFrameHost* rfh) { + if (rfh->IsRenderFrameLive()) + frames->insert(rfh); +} + +} // namespace + +// Takes a snapshot of all frames upon construction. When Wait() is called, a +// MessageLoop is created and Quit when all previously recorded frames are +// either present in the tab, or deleted. If a navigation happens between the +// construction and the Wait() call, then this logic ensures that all obsolete +// RenderFrameHosts have been destructed when Wait() returns. +// See also the comment at ProcessManagerBrowserTest::NavigateToURL. +class NavigationCompletedObserver : public content::WebContentsObserver { + public: + explicit NavigationCompletedObserver(content::WebContents* web_contents) + : content::WebContentsObserver(web_contents), + message_loop_runner_(new content::MessageLoopRunner) { + web_contents->ForEachFrame( + base::Bind(&AddFrameToSet, base::Unretained(&frames_))); + } + + void Wait() { + if (!AreAllFramesInTab()) + message_loop_runner_->Run(); + } + + void RenderFrameDeleted(content::RenderFrameHost* rfh) override { + if (frames_.erase(rfh) != 0 && message_loop_runner_->loop_running() && + AreAllFramesInTab()) + message_loop_runner_->Quit(); + } + + private: + // Check whether all frames that were recorded at the construction of this + // class are still part of the tab. + bool AreAllFramesInTab() { + std::set<content::RenderFrameHost*> current_frames; + web_contents()->ForEachFrame( + base::Bind(&AddFrameToSet, base::Unretained(¤t_frames))); + for (content::RenderFrameHost* frame : frames_) { + if (current_frames.find(frame) == current_frames.end()) + return false; + } + return true; + } + + std::set<content::RenderFrameHost*> frames_; + scoped_refptr<content::MessageLoopRunner> message_loop_runner_; + + DISALLOW_COPY_AND_ASSIGN(NavigationCompletedObserver); +}; + // Exists as a browser test because ExtensionHosts are hard to create without // a real browser. -typedef ExtensionBrowserTest ProcessManagerBrowserTest; +class ProcessManagerBrowserTest : public ExtensionBrowserTest { + public: + // Create an extension with web-accessible frames and an optional background + // page. + const Extension* CreateExtension(const std::string& name, + bool has_background_process) { + scoped_ptr<TestExtensionDir> dir(new TestExtensionDir()); + + DictionaryBuilder manifest; + manifest.Set("name", name) + .Set("version", "1") + .Set("manifest_version", 2) + // To allow ExecuteScript* to work. + .Set("content_security_policy", + "script-src 'self' 'unsafe-eval'; object-src 'self'") + .Set("sandbox", DictionaryBuilder().Set( + "pages", ListBuilder().Append("sandboxed.html"))) + .Set("web_accessible_resources", ListBuilder().Append("*")); + + if (has_background_process) { + manifest.Set("background", DictionaryBuilder().Set("page", "bg.html")); + dir->WriteFile(FILE_PATH_LITERAL("bg.html"), + "<iframe id='bgframe' src='empty.html'></iframe>"); + } + + dir->WriteFile(FILE_PATH_LITERAL("blank_iframe.html"), + "<iframe id='frame0' src='about:blank'></iframe>"); + + dir->WriteFile(FILE_PATH_LITERAL("srcdoc_iframe.html"), + "<iframe id='frame0' srcdoc='Hello world'></iframe>"); + + dir->WriteFile(FILE_PATH_LITERAL("two_iframes.html"), + "<iframe id='frame1' src='empty.html'></iframe>" + "<iframe id='frame2' src='empty.html'></iframe>"); + + dir->WriteFile(FILE_PATH_LITERAL("sandboxed.html"), "Some sandboxed page"); + + dir->WriteFile(FILE_PATH_LITERAL("empty.html"), ""); + + dir->WriteManifest(manifest.ToJSON()); + + const Extension* extension = LoadExtension(dir->unpacked_path()); + EXPECT_TRUE(extension); + temp_dirs_.push_back(dir.Pass()); + return extension; + } + + // ui_test_utils::NavigateToURL sometimes returns too early: It returns as + // soon as the StopLoading notification has been triggered. This does not + // imply that RenderFrameDeleted was called, so the test may continue too + // early and fail when ProcessManager::GetAllFrames() returns too many frames + // (namely frames that are in the process of being deleted). To work around + // this problem, we also wait until all previous frames have been deleted. + void NavigateToURL(const GURL& url) { + NavigationCompletedObserver observer( + browser()->tab_strip_model()->GetActiveWebContents()); + + ui_test_utils::NavigateToURL(browser(), url); + + // Wait until the last RenderFrameHosts are deleted. This wait doesn't take + // long. + observer.Wait(); + } + + void NavigateIframeToURLAndWait(content::WebContents* web_contents, + const std::string iframe_id, + const GURL& url) { + // This is an improved version of content::NavigateIframeToURL. Unlike the + // other method, this does actually wait until the load of all child frames + // completes. + std::string script = base::StringPrintf( + "var frame = document.getElementById('%s');" + "frame.onload = frame.onerror = function(event) {" + " frame.onload = frame.onerror = null;" + " domAutomationController.send(event.type === 'load');" + "};" + "frame.src = '%s';", + iframe_id.c_str(), url.spec().c_str()); + bool is_loaded = false; + EXPECT_TRUE(ExecuteScriptAndExtractBool(web_contents, script, &is_loaded)); + EXPECT_TRUE(is_loaded); + } + + size_t IfExtensionsIsolated(size_t if_enabled, size_t if_disabled) { + return content::AreAllSitesIsolatedForTesting() || + IsIsolateExtensionsEnabled() + ? if_enabled + : if_disabled; + } + + private: + std::vector<scoped_ptr<TestExtensionDir>> temp_dirs_; +}; // Test that basic extension loading creates the appropriate ExtensionHosts // and background pages. @@ -157,6 +316,193 @@ EXPECT_TRUE(pm->GetBackgroundHostForExtension(extension->id())); } +IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, NoBackgroundPage) { + ASSERT_TRUE(embedded_test_server()->Start()); + + ProcessManager* pm = ProcessManager::Get(profile()); + const Extension* extension = + LoadExtension(test_data_dir_.AppendASCII("api_test") + .AppendASCII("messaging") + .AppendASCII("connect_nobackground")); + ASSERT_TRUE(extension); + + // The extension has no background page. + EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension->id()).size()); + + // Start in a non-extension process, then navigate to an extension process. + NavigateToURL(embedded_test_server()->GetURL("/empty.html")); + EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension->id()).size()); + + const GURL extension_url = extension->url().Resolve("manifest.json"); + NavigateToURL(extension_url); + EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension->id()).size()); + + NavigateToURL(GURL("about:blank")); + EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension->id()).size()); + + ui_test_utils::NavigateToURLWithDisposition( + browser(), extension_url, NEW_FOREGROUND_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); + EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension->id()).size()); +} + +// Tests whether frames are correctly classified. Non-extension frames should +// never appear in the list. Top-level extension frames should always appear. +// Child extension frames should only appear if it is hosted in an extension +// process (i.e. if the top-level frame is an extension page, or if OOP frames +// are enabled for extensions). +IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, FrameClassification) { + const Extension* extension1 = CreateExtension("Extension 1", false); + const Extension* extension2 = CreateExtension("Extension 2", true); + embedded_test_server()->ServeFilesFromDirectory(extension1->path()); + ASSERT_TRUE(embedded_test_server()->Start()); + + const GURL kExt1TwoFramesUrl(extension1->url().Resolve("two_iframes.html")); + const GURL kExt1EmptyUrl(extension1->url().Resolve("empty.html")); + const GURL kExt2TwoFramesUrl(extension2->url().Resolve("two_iframes.html")); + const GURL kExt2EmptyUrl(extension2->url().Resolve("empty.html")); + + ProcessManager* pm = ProcessManager::Get(profile()); + + // 1 background page + 1 frame in background page from Extension 2. + BackgroundPageWatcher(pm, extension2).WaitForOpen(); + EXPECT_EQ(2u, pm->GetAllFrames().size()); + EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); + EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); + + ExecuteScriptInBackgroundPageNoWait(extension2->id(), + "setTimeout(window.close, 0)"); + BackgroundPageWatcher(pm, extension2).WaitForClose(); + EXPECT_EQ(0u, pm->GetAllFrames().size()); + EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); + + NavigateToURL(embedded_test_server()->GetURL("/two_iframes.html")); + EXPECT_EQ(0u, pm->GetAllFrames().size()); + + content::WebContents* tab = + browser()->tab_strip_model()->GetActiveWebContents(); + + // Tests extension frames in non-extension page. + NavigateIframeToURLAndWait(tab, "frame1", kExt1EmptyUrl); + EXPECT_EQ(IfExtensionsIsolated(1, 0), + pm->GetRenderFrameHostsForExtension(extension1->id()).size()); + EXPECT_EQ(IfExtensionsIsolated(1, 0), pm->GetAllFrames().size()); + + NavigateIframeToURLAndWait(tab, "frame2", kExt2EmptyUrl); + EXPECT_EQ(IfExtensionsIsolated(1, 0), + pm->GetRenderFrameHostsForExtension(extension2->id()).size()); + EXPECT_EQ(IfExtensionsIsolated(2, 0), pm->GetAllFrames().size()); + + // Tests non-extension page in extension frame. + NavigateToURL(kExt1TwoFramesUrl); + // 1 top-level + 2 child frames from Extension 1. + EXPECT_EQ(3u, pm->GetAllFrames().size()); + EXPECT_EQ(3u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); + EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); + + NavigateIframeToURLAndWait(tab, "frame1", + embedded_test_server()->GetURL("/empty.html")); + // 1 top-level + 1 child frame from Extension 1. + EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); + EXPECT_EQ(2u, pm->GetAllFrames().size()); + + NavigateIframeToURLAndWait(tab, "frame1", kExt1EmptyUrl); + // 1 top-level + 2 child frames from Extension 1. + EXPECT_EQ(3u, pm->GetAllFrames().size()); + EXPECT_EQ(3u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); + + // Load a frame from another extension. + NavigateIframeToURLAndWait(tab, "frame1", kExt2EmptyUrl); + // 1 top-level + 1 child frame from Extension 1, + // 1 child frame from Extension 2. + EXPECT_EQ(IfExtensionsIsolated(3, 2), pm->GetAllFrames().size()); + EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); + EXPECT_EQ(IfExtensionsIsolated(1, 0), + pm->GetRenderFrameHostsForExtension(extension2->id()).size()); + + // Destroy all existing frames by navigating to another extension. + NavigateToURL(extension2->url().Resolve("empty.html")); + EXPECT_EQ(1u, pm->GetAllFrames().size()); + EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); + EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); + + // Test about:blank and about:srcdoc child frames. + NavigateToURL(extension2->url().Resolve("srcdoc_iframe.html")); + // 1 top-level frame + 1 child frame from Extension 2. + EXPECT_EQ(2u, pm->GetAllFrames().size()); + EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); + + NavigateToURL(extension2->url().Resolve("blank_iframe.html")); + // 1 top-level frame + 1 child frame from Extension 2. + EXPECT_EQ(2u, pm->GetAllFrames().size()); + EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); + + // Sandboxed frames are not viewed as extension frames. + NavigateIframeToURLAndWait(tab, "frame0", + extension2->url().Resolve("sandboxed.html")); + // 1 top-level frame from Extension 2. + EXPECT_EQ(1u, pm->GetAllFrames().size()); + EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); + + NavigateToURL(extension2->url().Resolve("sandboxed.html")); + EXPECT_EQ(0u, pm->GetAllFrames().size()); + EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); + + // Test nested frames (same extension). + NavigateToURL(kExt2TwoFramesUrl); + // 1 top-level + 2 child frames from Extension 2. + EXPECT_EQ(3u, pm->GetAllFrames().size()); + EXPECT_EQ(3u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); + + NavigateIframeToURLAndWait(tab, "frame1", kExt2TwoFramesUrl); + // 1 top-level + 2 child frames from Extension 1, + // 2 child frames in frame1 from Extension 2. + EXPECT_EQ(5u, pm->GetAllFrames().size()); + EXPECT_EQ(5u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); + + // The extension frame from the other extension should not be classified as an + // extension (unless out-of-process frames are enabled). + NavigateIframeToURLAndWait(tab, "frame1", kExt1EmptyUrl); + // 1 top-level + 1 child frames from Extension 2, + // 1 child frame from Extension 1. + EXPECT_EQ(IfExtensionsIsolated(3, 2), pm->GetAllFrames().size()); + EXPECT_EQ(IfExtensionsIsolated(1, 0), + pm->GetRenderFrameHostsForExtension(extension1->id()).size()); + EXPECT_EQ(2u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); + + NavigateIframeToURLAndWait(tab, "frame2", kExt1TwoFramesUrl); + // 1 top-level + 1 child frames from Extension 2, + // 1 child frame + 2 child frames in frame2 from Extension 1. + EXPECT_EQ(IfExtensionsIsolated(5, 1), pm->GetAllFrames().size()); + EXPECT_EQ(IfExtensionsIsolated(4, 0), + pm->GetRenderFrameHostsForExtension(extension1->id()).size()); + EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); + + // Crash tab where the top-level frame is an extension frame. + content::CrashTab(tab); + EXPECT_EQ(0u, pm->GetAllFrames().size()); + EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); + EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension2->id()).size()); + + // Now load an extension page and a non-extension page... + ui_test_utils::NavigateToURLWithDisposition( + browser(), kExt1EmptyUrl, NEW_BACKGROUND_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); + NavigateToURL(embedded_test_server()->GetURL("/two_iframes.html")); + EXPECT_EQ(1u, pm->GetAllFrames().size()); + + // ... load an extension frame in the non-extension process + NavigateIframeToURLAndWait(tab, "frame1", kExt1EmptyUrl); + EXPECT_EQ(IfExtensionsIsolated(2, 1), + pm->GetRenderFrameHostsForExtension(extension1->id()).size()); + + // ... and take down the tab. The extension process is not part of the tab, + // so it should be kept alive (minus the frames that died). + content::CrashTab(tab); + EXPECT_EQ(1u, pm->GetAllFrames().size()); + EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension1->id()).size()); +} + // Verify correct keepalive count behavior on network request events. // Regression test for http://crbug.com/535716. IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, KeepaliveOnNetworkRequest) {
diff --git a/chrome/browser/google/google_brand_chromeos.cc b/chrome/browser/google/google_brand_chromeos.cc index 8ccec25a..ddde682e 100644 --- a/chrome/browser/google/google_brand_chromeos.cc +++ b/chrome/browser/google/google_brand_chromeos.cc
@@ -31,7 +31,7 @@ base::FilePath brand_file_path(kRLZBrandFilePath); if (!base::ReadFileToString(brand_file_path, &brand)) LOG(WARNING) << "Brand code file missing: " << brand_file_path.value(); - base::TrimWhitespace(brand, base::TRIM_ALL, &brand); + base::TrimWhitespaceASCII(brand, base::TRIM_ALL, &brand); return brand; }
diff --git a/chrome/browser/net/firefox_proxy_settings.cc b/chrome/browser/net/firefox_proxy_settings.cc index 203d9557..16b3618 100644 --- a/chrome/browser/net/firefox_proxy_settings.cc +++ b/chrome/browser/net/firefox_proxy_settings.cc
@@ -102,7 +102,7 @@ } std::string value = line.substr(start_value + 1, stop_value - start_value - 1); - base::TrimWhitespace(value, base::TRIM_ALL, &value); + base::TrimWhitespaceASCII(value, base::TRIM_ALL, &value); // Value could be a boolean. bool is_value_true = base::LowerCaseEqualsASCII(value, "true"); if (is_value_true || base::LowerCaseEqualsASCII(value, "false")) {
diff --git a/chrome/browser/speech/chrome_speech_recognition_manager_delegate.cc b/chrome/browser/speech/chrome_speech_recognition_manager_delegate.cc index 99b336ef..a9099abf 100644 --- a/chrome/browser/speech/chrome_speech_recognition_manager_delegate.cc +++ b/chrome/browser/speech/chrome_speech_recognition_manager_delegate.cc
@@ -423,6 +423,7 @@ view_type == extensions::VIEW_TYPE_APP_WINDOW || view_type == extensions::VIEW_TYPE_LAUNCHER_PAGE || view_type == extensions::VIEW_TYPE_VIRTUAL_KEYBOARD || + view_type == extensions::VIEW_TYPE_EXTENSION_POPUP || view_type == extensions::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { // If it is a tab, we can check for permission. For apps, this means // manifest would be checked for permission.
diff --git a/chrome/browser/ui/search_engines/edit_search_engine_controller.cc b/chrome/browser/ui/search_engines/edit_search_engine_controller.cc index b81e9cb..837c8ea 100644 --- a/chrome/browser/ui/search_engines/edit_search_engine_controller.cc +++ b/chrome/browser/ui/search_engines/edit_search_engine_controller.cc
@@ -127,9 +127,9 @@ std::string EditSearchEngineController::GetFixedUpURL( const std::string& url_input) const { std::string url; - base::TrimWhitespace(TemplateURLRef::DisplayURLToURLRef( - base::UTF8ToUTF16(url_input)), - base::TRIM_ALL, &url); + base::TrimWhitespaceASCII( + TemplateURLRef::DisplayURLToURLRef(base::UTF8ToUTF16(url_input)), + base::TRIM_ALL, &url); if (url.empty()) return url;
diff --git a/chrome/common/extensions/api/developer_private.idl b/chrome/common/extensions/api/developer_private.idl index 15e7dc0..882c7db 100644 --- a/chrome/common/extensions/api/developer_private.idl +++ b/chrome/common/extensions/api/developer_private.idl
@@ -64,6 +64,7 @@ BACKGROUND_CONTENTS, EXTENSION_BACKGROUND_PAGE, EXTENSION_DIALOG, + EXTENSION_GUEST, EXTENSION_POPUP, LAUNCHER_PAGE, PANEL,
diff --git a/chrome/test/chromedriver/net/adb_client_socket.cc b/chrome/test/chromedriver/net/adb_client_socket.cc index 14a10ba..752dde2 100644 --- a/chrome/test/chromedriver/net/adb_client_socket.cc +++ b/chrome/test/chromedriver/net/adb_client_socket.cc
@@ -185,7 +185,7 @@ if (endline_pos != std::string::npos) { std::string len = response_.substr(content_pos + 15, endline_pos - content_pos - 15); - base::TrimWhitespace(len, base::TRIM_ALL, &len); + base::TrimWhitespaceASCII(len, base::TRIM_ALL, &len); if (!base::StringToInt(len, &expected_length)) { CheckNetResultOrDie(net::ERR_FAILED); return;
diff --git a/chrome/test/data/extensions/api_test/messaging/connect_nobackground/contentscript.js b/chrome/test/data/extensions/api_test/messaging/connect_nobackground/contentscript.js new file mode 100644 index 0000000..ed5955a7 --- /dev/null +++ b/chrome/test/data/extensions/api_test/messaging/connect_nobackground/contentscript.js
@@ -0,0 +1,12 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) { + chrome.test.assertEq('msg from tab', message); + sendResponse('Reply here'); +}); + +var port = chrome.runtime.connect(); +port.postMessage('Hello from content script'); +port.disconnect();
diff --git a/chrome/test/data/extensions/api_test/messaging/connect_nobackground/manifest.json b/chrome/test/data/extensions/api_test/messaging/connect_nobackground/manifest.json new file mode 100644 index 0000000..55df682 --- /dev/null +++ b/chrome/test/data/extensions/api_test/messaging/connect_nobackground/manifest.json
@@ -0,0 +1,10 @@ +{ + "name": "connect_nobackground", + "version": "1.0", + "manifest_version": 2, + "description": "Tests that a content script can notify an extension in a tab.", + "content_scripts": [{ + "matches": ["*://*/*?will_test_connect_and_sendMessage"], + "js": ["contentscript.js"] + }] +}
diff --git a/chrome/test/data/extensions/api_test/messaging/connect_nobackground/page_in_main_frame.html b/chrome/test/data/extensions/api_test/messaging/connect_nobackground/page_in_main_frame.html new file mode 100644 index 0000000..3fb274a --- /dev/null +++ b/chrome/test/data/extensions/api_test/messaging/connect_nobackground/page_in_main_frame.html
@@ -0,0 +1,6 @@ +<!-- + * Copyright 2015 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. +--> +<script src="test.js"></script>
diff --git a/chrome/test/data/extensions/api_test/messaging/connect_nobackground/test.js b/chrome/test/data/extensions/api_test/messaging/connect_nobackground/test.js new file mode 100644 index 0000000..af1732f --- /dev/null +++ b/chrome/test/data/extensions/api_test/messaging/connect_nobackground/test.js
@@ -0,0 +1,35 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +chrome.runtime.onConnect.addListener(function(port) { + var succeed1 = chrome.test.callbackAdded(); + var succeed2 = chrome.test.callbackAdded(); + var succeed3 = chrome.test.callbackAdded(); + + port.onMessage.addListener(function(msg) { + chrome.test.log('port.onMessage was triggered.'); + chrome.test.assertEq('Hello from content script', msg); + succeed1(); + }); + + port.onDisconnect.addListener(function() { + chrome.test.log('port.onDisconnect was triggered.'); + succeed2(); + }); + + chrome.tabs.sendMessage(port.sender.tab.id, 'msg from tab', function(reply) { + chrome.test.log('tab.sendMessage\'s response callback was invoked'); + chrome.test.assertEq('Reply here', reply); + succeed3(); + }); +}); + +chrome.test.getConfig(function(config) { + var url = 'http://localhost:' + config.testServer.port + + '/extensions/test_file.html?will_test_connect_and_sendMessage'; + // Content script will try to connect and trigger onConnect. + chrome.tabs.create({ + url: url + }); +});
diff --git a/chrome/tools/convert_dict/hunspell_reader.cc b/chrome/tools/convert_dict/hunspell_reader.cc index 6555fb7be..5232443 100644 --- a/chrome/tools/convert_dict/hunspell_reader.cc +++ b/chrome/tools/convert_dict/hunspell_reader.cc
@@ -23,7 +23,7 @@ // Treat this text as an ASCII text and trim whitespace characters as // hunspell does. The returned text is to be converted into UTF-8 text with // the encoding defined in an affix file. - base::TrimWhitespace(*line, base::TRIM_ALL, line); + base::TrimWhitespaceASCII(*line, base::TRIM_ALL, line); } std::string ReadLine(FILE* file) {
diff --git a/chromeos/dbus/power_policy_controller.cc b/chromeos/dbus/power_policy_controller.cc index 336b72e..49c76c2 100644 --- a/chromeos/dbus/power_policy_controller.cc +++ b/chromeos/dbus/power_policy_controller.cc
@@ -152,7 +152,7 @@ } if (policy.has_reason()) str += base::StringPrintf("reason=\"%s\" ", policy.reason().c_str()); - base::TrimWhitespace(str, base::TRIM_TRAILING, &str); + base::TrimWhitespaceASCII(str, base::TRIM_TRAILING, &str); return str; }
diff --git a/components/cdm/browser/cdm_message_filter_android.cc b/components/cdm/browser/cdm_message_filter_android.cc index e9399f6..14043e1 100644 --- a/components/cdm/browser/cdm_message_filter_android.cc +++ b/components/cdm/browser/cdm_message_filter_android.cc
@@ -9,11 +9,10 @@ #include "components/cdm/common/cdm_messages_android.h" #include "ipc/ipc_message_macros.h" -#include "media/base/android/media_codec_bridge.h" +#include "media/base/android/media_codec_util.h" #include "media/base/android/media_drm_bridge.h" using content::BrowserThread; -using media::MediaCodecBridge; using media::MediaDrmBridge; using media::SupportedCodecs; @@ -59,7 +58,7 @@ if ((request.codecs & info.codec) && MediaDrmBridge::IsKeySystemSupportedWithType( key_system, info.container_mime_type) && - MediaCodecBridge::CanDecode(info.codec_name, is_secure)) { + media::MediaCodecUtil::CanDecode(info.codec_name, is_secure)) { supported_codecs |= info.codec; } }
diff --git a/components/google/core/browser/google_url_tracker.cc b/components/google/core/browser/google_url_tracker.cc index fa0d140..f503265e 100644 --- a/components/google/core/browser/google_url_tracker.cc +++ b/components/google/core/browser/google_url_tracker.cc
@@ -97,7 +97,7 @@ // See if the response data was valid. It should be ".google.<TLD>". std::string url_str; source->GetResponseAsString(&url_str); - base::TrimWhitespace(url_str, base::TRIM_ALL, &url_str); + base::TrimWhitespaceASCII(url_str, base::TRIM_ALL, &url_str); if (!base::StartsWith(url_str, ".google.", base::CompareCase::INSENSITIVE_ASCII)) return;
diff --git a/components/mus/surfaces/surfaces_state.cc b/components/mus/surfaces/surfaces_state.cc index ea203ba6..51b7358 100644 --- a/components/mus/surfaces/surfaces_state.cc +++ b/components/mus/surfaces/surfaces_state.cc
@@ -7,9 +7,7 @@ namespace mus { SurfacesState::SurfacesState() - : next_id_namespace_(1u), - hit_tester_(&manager_) { -} + : next_id_namespace_(1u), hit_tester_(nullptr, &manager_) {} SurfacesState::~SurfacesState() {}
diff --git a/components/nacl/BUILD.gn b/components/nacl/BUILD.gn index ad200c93..7e20ecc0 100644 --- a/components/nacl/BUILD.gn +++ b/components/nacl/BUILD.gn
@@ -144,6 +144,7 @@ deps = [ ":nacl_common", ":nacl_switches", + "renderer/plugin:nacl_trusted_plugin", "//base", "//content/public/common", "//content/public/renderer", @@ -153,7 +154,6 @@ "//ppapi/proxy:ipc", "//ppapi/shared_impl", "//third_party/WebKit/public:blink", - "renderer/plugin:nacl_trusted_plugin", ] }
diff --git a/components/plugins/renderer/plugin_placeholder.cc b/components/plugins/renderer/plugin_placeholder.cc index bfb3ef15..96fb0bb 100644 --- a/components/plugins/renderer/plugin_placeholder.cc +++ b/components/plugins/renderer/plugin_placeholder.cc
@@ -81,7 +81,7 @@ if (base::EndsWith(width_str, "px", base::CompareCase::INSENSITIVE_ASCII)) { width_str = width_str.substr(0, width_str.length() - 2); } - base::TrimWhitespace(width_str, base::TRIM_TRAILING, &width_str); + base::TrimWhitespaceASCII(width_str, base::TRIM_TRAILING, &width_str); width_str += "[\\s]*px"; std::string height_str("height:[\\s]*"); height_str += element.getAttribute("height").utf8().data(); @@ -89,7 +89,7 @@ base::CompareCase::INSENSITIVE_ASCII)) { height_str = height_str.substr(0, height_str.length() - 2); } - base::TrimWhitespace(height_str, base::TRIM_TRAILING, &height_str); + base::TrimWhitespaceASCII(height_str, base::TRIM_TRAILING, &height_str); height_str += "[\\s]*px"; blink::WebNode parent = element; while (!parent.parentNode().isNull()) {
diff --git a/components/safe_browsing_db/prefix_set_unittest.cc b/components/safe_browsing_db/prefix_set_unittest.cc index 181efc7..d1de0db4 100644 --- a/components/safe_browsing_db/prefix_set_unittest.cc +++ b/components/safe_browsing_db/prefix_set_unittest.cc
@@ -199,7 +199,7 @@ while (fgets(buf, sizeof(buf), file.get())) { std::string trimmed; if (base::TRIM_TRAILING != - base::TrimWhitespace(buf, base::TRIM_ALL, &trimmed)) + base::TrimWhitespaceASCII(buf, base::TRIM_ALL, &trimmed)) return false; unsigned prefix; if (!base::StringToUint(trimmed, &prefix))
diff --git a/components/variations/BUILD.gn b/components/variations/BUILD.gn index 3f9c7c7d..a65148a 100644 --- a/components/variations/BUILD.gn +++ b/components/variations/BUILD.gn
@@ -62,6 +62,7 @@ } deps = [ + "proto", "//base", "//base:prefs", "//components/compression", @@ -69,7 +70,6 @@ "//crypto", "//third_party/mt19937ar", "//third_party/protobuf:protobuf_lite", - "proto", ] if (is_android) { @@ -111,11 +111,11 @@ deps = [ ":variations", + "net", + "proto", "//base:prefs_test_support", "//base/test:test_support", "//components/compression", "//testing/gtest", - "net", - "proto", ] }
diff --git a/content/browser/compositor/delegated_frame_host.cc b/content/browser/compositor/delegated_frame_host.cc index 2650a76..bf39969 100644 --- a/content/browser/compositor/delegated_frame_host.cc +++ b/content/browser/compositor/delegated_frame_host.cc
@@ -211,7 +211,7 @@ gfx::Point* transformed_point) { if (surface_id_.is_null()) return surface_id_; - cc::SurfaceHittest hittest(GetSurfaceManager()); + cc::SurfaceHittest hittest(nullptr, GetSurfaceManager()); gfx::Transform target_transform; cc::SurfaceId target_surface_id = hittest.GetTargetSurfaceAtPoint(surface_id_, point, &target_transform); @@ -230,7 +230,7 @@ return; gfx::Transform transform; - cc::SurfaceHittest hittest(GetSurfaceManager()); + cc::SurfaceHittest hittest(nullptr, GetSurfaceManager()); if (hittest.GetTransformToTargetSurface(surface_id_, original_surface, &transform) && transform.GetInverse(&transform)) {
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc index 789c5ea3..70646c1 100644 --- a/content/browser/renderer_host/compositor_impl_android.cc +++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -444,8 +444,8 @@ command_line->HasSwitch(cc::switches::kEnableGpuBenchmarking)); settings.initial_debug_state.show_fps_counter = command_line->HasSwitch(cc::switches::kUIShowFPSCounter); - settings.use_property_trees = - command_line->HasSwitch(cc::switches::kEnableCompositorPropertyTrees); + if (command_line->HasSwitch(cc::switches::kDisableCompositorPropertyTrees)) + settings.use_property_trees = false; // TODO(enne): Update this this compositor to use the scheduler. settings.single_thread_proxy_scheduler = false;
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 60b94257..c695f6f 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1445,10 +1445,10 @@ // also be added to chrome/browser/chromeos/login/chrome_restart_request.cc. cc::switches::kDisableCachedPictureRaster, cc::switches::kDisableCompositedAntialiasing, + cc::switches::kDisableCompositorPropertyTrees, cc::switches::kDisableMainFrameBeforeActivation, cc::switches::kDisableThreadedAnimation, cc::switches::kEnableBeginFrameScheduling, - cc::switches::kEnableCompositorPropertyTrees, cc::switches::kEnableGpuBenchmarking, cc::switches::kEnableMainFrameBeforeActivation, cc::switches::kShowCompositedLayerBorders,
diff --git a/content/child/npapi/plugin_host.cc b/content/child/npapi/plugin_host.cc index 4f3006e0..7f03896c 100644 --- a/content/child/npapi/plugin_host.cc +++ b/content/child/npapi/plugin_host.cc
@@ -259,7 +259,7 @@ case GETNAME: // Got a value. value = std::string(start, ptr - start); - base::TrimWhitespace(value, base::TRIM_ALL, &value); + base::TrimWhitespaceASCII(value, base::TRIM_ALL, &value); // If the name field is empty, we'll skip this header // but we won't error out. if (!name.empty() && name != "content-length") { @@ -271,7 +271,7 @@ case GETVALUE: // Got a header. name = base::ToLowerASCII(base::StringPiece(start, ptr - start)); - base::TrimWhitespace(name, base::TRIM_ALL, &name); + base::TrimWhitespaceASCII(name, base::TRIM_ALL, &name); start = ptr + 1; break; case GETDATA: {
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index be71402..691b8b9 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -19,7 +19,7 @@ #include <cpu-features.h> #include "base/android/build_info.h" #include "base/metrics/field_trial.h" -#include "media/base/android/media_codec_bridge.h" +#include "media/base/android/media_codec_util.h" #elif defined(OS_WIN) #include "base/win/windows_version.h" #endif @@ -34,7 +34,7 @@ #if defined(OS_ANDROID) // MSE/EME implementation needs Android MediaCodec API. - if (!media::MediaCodecBridge::IsAvailable()) { + if (!media::MediaCodecUtil::IsMediaCodecAvailable()) { WebRuntimeFeatures::enableMediaSource(false); WebRuntimeFeatures::enablePrefixedEncryptedMedia(false); WebRuntimeFeatures::enableEncryptedMedia(false); @@ -43,7 +43,7 @@ // is available. AndroidCpuFamily cpu_family = android_getCpuFamily(); WebRuntimeFeatures::enableWebAudio( - media::MediaCodecBridge::IsAvailable() && + media::MediaCodecUtil::IsMediaCodecAvailable() && ((cpu_family == ANDROID_CPU_FAMILY_ARM) || (cpu_family == ANDROID_CPU_FAMILY_ARM64) || (cpu_family == ANDROID_CPU_FAMILY_X86) || @@ -121,7 +121,7 @@ // API is available. WebRuntimeFeatures::enableWebAudio( !command_line.HasSwitch(switches::kDisableWebAudio) && - media::MediaCodecBridge::IsAvailable()); + media::MediaCodecUtil::IsMediaCodecAvailable()); #else if (command_line.HasSwitch(switches::kDisableWebAudio)) WebRuntimeFeatures::enableWebAudio(false);
diff --git a/content/common/gpu/media/android_video_decode_accelerator.h b/content/common/gpu/media/android_video_decode_accelerator.h index 2e8058af..945a4d0a 100644 --- a/content/common/gpu/media/android_video_decode_accelerator.h +++ b/content/common/gpu/media/android_video_decode_accelerator.h
@@ -17,7 +17,7 @@ #include "content/common/content_export.h" #include "content/common/gpu/media/avda_state_provider.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" -#include "media/base/android/media_codec_bridge.h" +#include "media/base/android/sdk_media_codec_bridge.h" #include "media/video/video_decode_accelerator.h" namespace gfx {
diff --git a/content/common/gpu/media/android_video_decode_accelerator_unittest.cc b/content/common/gpu/media/android_video_decode_accelerator_unittest.cc index 2e0e7ac2..c1e91f12 100644 --- a/content/common/gpu/media/android_video_decode_accelerator_unittest.cc +++ b/content/common/gpu/media/android_video_decode_accelerator_unittest.cc
@@ -12,7 +12,7 @@ #include "content/common/gpu/media/android_copying_backing_strategy.h" #include "content/common/gpu/media/android_video_decode_accelerator.h" #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" -#include "media/base/android/media_codec_bridge.h" +#include "media/base/android/media_codec_util.h" #include "media/base/android/media_jni_registrar.h" #include "media/video/picture.h" #include "media/video/video_decode_accelerator.h" @@ -92,7 +92,7 @@ } TEST_F(AndroidVideoDecodeAcceleratorTest, ConfigureSupportedCodec) { - if (!media::MediaCodecBridge::IsAvailable()) + if (!media::MediaCodecUtil::IsMediaCodecAvailable()) return; EXPECT_TRUE(Configure(media::kCodecVP8)); }
diff --git a/content/common/gpu/media/android_video_encode_accelerator.cc b/content/common/gpu/media/android_video_encode_accelerator.cc index 1cb6e549..e439203 100644 --- a/content/common/gpu/media/android_video_encode_accelerator.cc +++ b/content/common/gpu/media/android_video_encode_accelerator.cc
@@ -14,7 +14,7 @@ #include "content/common/gpu/gpu_channel.h" #include "content/public/common/content_switches.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" -#include "media/base/android/media_codec_bridge.h" +#include "media/base/android/media_codec_util.h" #include "media/base/bitstream_buffer.h" #include "media/base/limits.h" #include "media/video/picture.h" @@ -22,7 +22,6 @@ #include "ui/gl/android/scoped_java_surface.h" #include "ui/gl/gl_bindings.h" -using media::MediaCodecBridge; using media::VideoCodecBridge; using media::VideoFrame; @@ -83,7 +82,7 @@ if (mime.empty()) return false; - std::set<int> formats = MediaCodecBridge::GetEncoderColorFormats(mime); + std::set<int> formats = media::MediaCodecUtil::GetEncoderColorFormats(mime); if (formats.count(COLOR_FORMAT_YUV420_SEMIPLANAR) > 0) *pixel_format = COLOR_FORMAT_YUV420_SEMIPLANAR; else if (formats.count(COLOR_FORMAT_YUV420_PLANAR) > 0) @@ -157,8 +156,8 @@ client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); - if (!(media::MediaCodecBridge::SupportsSetParameters() && - format == media::PIXEL_FORMAT_I420)) { + if (!(media::MediaCodecUtil::SupportsSetParameters() && + format == media::PIXEL_FORMAT_I420)) { DLOG(ERROR) << "Unexpected combo: " << format << ", " << output_profile; return false; }
diff --git a/content/common/gpu/media/android_video_encode_accelerator.h b/content/common/gpu/media/android_video_encode_accelerator.h index 98fa3c2b9..367ecf88 100644 --- a/content/common/gpu/media/android_video_encode_accelerator.h +++ b/content/common/gpu/media/android_video_encode_accelerator.h
@@ -14,7 +14,7 @@ #include "base/timer/timer.h" #include "base/tuple.h" #include "content/common/content_export.h" -#include "media/base/android/media_codec_bridge.h" +#include "media/base/android/sdk_media_codec_bridge.h" #include "media/video/video_encode_accelerator.h" namespace media {
diff --git a/content/common/gpu/media/avda_shared_state.h b/content/common/gpu/media/avda_shared_state.h index a64bf3a..474037d 100644 --- a/content/common/gpu/media/avda_shared_state.h +++ b/content/common/gpu/media/avda_shared_state.h
@@ -6,7 +6,7 @@ #define CONTENT_COMMON_GPU_AVDA_SHARED_STATE_H_ #include "gpu/command_buffer/service/gles2_cmd_decoder.h" -#include "media/base/android/media_codec_bridge.h" +#include "media/base/android/sdk_media_codec_bridge.h" #include "ui/gl/gl_image.h" namespace gfx {
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc index 15dbc68..83093288 100644 --- a/content/renderer/gpu/render_widget_compositor.cc +++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -331,8 +331,8 @@ settings.verify_property_trees = cmd->HasSwitch(cc::switches::kEnablePropertyTreeVerification); - settings.use_property_trees = - cmd->HasSwitch(cc::switches::kEnableCompositorPropertyTrees); + if (cmd->HasSwitch(cc::switches::kDisableCompositorPropertyTrees)) + settings.use_property_trees = false; settings.renderer_settings.allow_antialiasing &= !cmd->HasSwitch(cc::switches::kDisableCompositedAntialiasing); // The means the renderer compositor has 2 possible modes:
diff --git a/content/renderer/media/webrtc/peer_connection_dependency_factory.cc b/content/renderer/media/webrtc/peer_connection_dependency_factory.cc index 4d20f5e..869a4a5 100644 --- a/content/renderer/media/webrtc/peer_connection_dependency_factory.cc +++ b/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
@@ -62,7 +62,7 @@ #include "third_party/webrtc/base/ssladapter.h" #if defined(OS_ANDROID) -#include "media/base/android/media_codec_bridge.h" +#include "media/base/android/media_codec_util.h" #endif namespace content { @@ -415,7 +415,7 @@ } #if defined(OS_ANDROID) - if (!media::MediaCodecBridge::SupportsSetParameters()) + if (!media::MediaCodecUtil::SupportsSetParameters()) encoder_factory.reset(); #endif
diff --git a/content/renderer/npapi/webplugin_impl_unittest.cc b/content/renderer/npapi/webplugin_impl_unittest.cc index 4576ea4..760c874 100644 --- a/content/renderer/npapi/webplugin_impl_unittest.cc +++ b/content/renderer/npapi/webplugin_impl_unittest.cc
@@ -19,7 +19,7 @@ std::string GetHeader(const WebURLRequest& request, const char* name) { std::string result; - base::TrimWhitespace( + base::TrimWhitespaceASCII( request.httpHeaderField(WebString::fromUTF8(name)).utf8(), base::TRIM_ALL, &result);
diff --git a/extensions/browser/extension_web_contents_observer.cc b/extensions/browser/extension_web_contents_observer.cc index 665fc08..ea1104a 100644 --- a/extensions/browser/extension_web_contents_observer.cc +++ b/extensions/browser/extension_web_contents_observer.cc
@@ -5,6 +5,7 @@ #include "extensions/browser/extension_web_contents_observer.h" #include "content/public/browser/child_process_security_policy.h" +#include "content/public/browser/navigation_details.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" @@ -50,18 +51,25 @@ DCHECK(render_frame_host); DCHECK(render_frame_host->IsRenderFrameLive()); + // At the initialization of the render frame, the last committed URL is not + // reliable, so do not take it into account in determining whether it is an + // extension frame. + const Extension* frame_extension = + GetExtensionFromFrame(render_frame_host, false); + // This observer is attached to every WebContents, so we are also notified of + // frames that are not in an extension process. + if (!frame_extension) + return; + // Notify the render frame of the view type. render_frame_host->Send(new ExtensionMsg_NotifyRenderViewType( render_frame_host->GetRoutingID(), GetViewType(web_contents()))); - const Extension* frame_extension = GetExtensionFromFrame(render_frame_host); - if (frame_extension) { - ExtensionsBrowserClient::Get()->RegisterMojoServices(render_frame_host, - frame_extension); - ProcessManager::Get(browser_context_) - ->RegisterRenderFrameHost(web_contents(), render_frame_host, - frame_extension); - } + ExtensionsBrowserClient::Get()->RegisterMojoServices(render_frame_host, + frame_extension); + ProcessManager::Get(browser_context_) + ->RegisterRenderFrameHost(web_contents(), render_frame_host, + frame_extension); } content::WebContents* ExtensionWebContentsObserver::GetAssociatedWebContents() @@ -110,6 +118,49 @@ ->UnregisterRenderFrameHost(render_frame_host); } +void ExtensionWebContentsObserver::DidCommitProvisionalLoadForFrame( + content::RenderFrameHost* render_frame_host, + const GURL& url, + ui::PageTransition transition_type) { + ProcessManager* pm = ProcessManager::Get(browser_context_); + + if (pm->IsRenderFrameHostRegistered(render_frame_host)) { + const Extension* frame_extension = + GetExtensionFromFrame(render_frame_host, true); + + if (!frame_extension) + pm->UnregisterRenderFrameHost(render_frame_host); + } +} + +void ExtensionWebContentsObserver::DidNavigateAnyFrame( + content::RenderFrameHost* render_frame_host, + const content::LoadCommittedDetails& details, + const content::FrameNavigateParams& params) { + if (details.is_in_page) + return; + + const Extension* frame_extension = + GetExtensionFromFrame(render_frame_host, true); + ProcessManager* pm = ProcessManager::Get(browser_context_); + + if (!frame_extension) { + // Should have been unregistered by DidCommitProvisionalLoadForFrame. + DCHECK(!pm->IsRenderFrameHostRegistered(render_frame_host)); + return; + } + + if (pm->IsRenderFrameHostRegistered(render_frame_host)) { + // Notify ProcessManager, because some clients do not just want to know + // whether the frame is in an extension process, but also whether the frame + // was navigated. + pm->DidNavigateRenderFrameHost(render_frame_host); + } else { + pm->RegisterRenderFrameHost(web_contents(), render_frame_host, + frame_extension); + } +} + bool ExtensionWebContentsObserver::OnMessageReceived( const IPC::Message& message, content::RenderFrameHost* render_frame_host) { @@ -146,24 +197,38 @@ std::string ExtensionWebContentsObserver::GetExtensionIdFromFrame( content::RenderFrameHost* render_frame_host) const { - content::SiteInstance* site_instance = render_frame_host->GetSiteInstance(); - GURL url = render_frame_host->GetLastCommittedURL(); - if (!url.is_empty()) { - if (site_instance->GetSiteURL().GetOrigin() != url.GetOrigin()) - return std::string(); - } else { - url = site_instance->GetSiteURL(); - } - - return url.SchemeIs(kExtensionScheme) ? url.host() : std::string(); + const Extension* extension = GetExtensionFromFrame(render_frame_host, true); + return extension ? extension->id() : std::string(); } const Extension* ExtensionWebContentsObserver::GetExtensionFromFrame( - content::RenderFrameHost* render_frame_host) const { - return ExtensionRegistry::Get( - render_frame_host->GetProcess()->GetBrowserContext()) - ->enabled_extensions() - .GetByID(GetExtensionIdFromFrame(render_frame_host)); + content::RenderFrameHost* render_frame_host, + bool verify_url) const { + const GURL site_url(render_frame_host->GetSiteInstance()->GetSiteURL()); + if (!site_url.SchemeIs(kExtensionScheme)) + return nullptr; + + const std::string& extension_id = site_url.host(); + content::BrowserContext* browser_context = + render_frame_host->GetProcess()->GetBrowserContext(); + const Extension* extension = ExtensionRegistry::Get(browser_context) + ->enabled_extensions() + .GetByID(extension_id); + if (!extension) + return nullptr; + + if (verify_url) { + const url::Origin& origin(render_frame_host->GetLastCommittedOrigin()); + // Without site isolation, this check is needed to eliminate non-extension + // schemes. With site isolation, this is still needed to exclude sandboxed + // extension frames with a unique origin. + if (origin.unique() || + site_url != content::SiteInstance::GetSiteForURL( + browser_context, GURL(origin.Serialize()))) + return nullptr; + } + + return extension; } const Extension* ExtensionWebContentsObserver::GetExtension(
diff --git a/extensions/browser/extension_web_contents_observer.h b/extensions/browser/extension_web_contents_observer.h index c92ad9c..5b86dc0 100644 --- a/extensions/browser/extension_web_contents_observer.h +++ b/extensions/browser/extension_web_contents_observer.h
@@ -29,6 +29,23 @@ // WebContents. It must be a subclass so that creating an instance via // content::WebContentsUserData::CreateForWebContents() provides an object of // the correct type. For an example, see ChromeExtensionWebContentsObserver. +// +// This class is responsible for maintaining the registrations of extension +// frames with the ProcessManager. Only frames in an extension process are +// registered. If out-of-process frames are enabled, every frame hosts a +// chrome-extension: page. Otherwise non-extension frames may erroneously be +// registered, but only briefly until they are correctly classified. This is +// achieved using the following notifications: +// 1. RenderFrameCreated - registers all new frames in extension processes. +// 2. DidCommitProvisionalLoadForFrame - unregisters non-extension frames. +// 3. DidNavigateAnyFrame - registers extension frames if they had been +// unregistered. +// +// Without OOPIF, non-extension frames created by the Chrome extension are also +// registered at RenderFrameCreated. When the non-extension page is committed, +// we detect that the unexpected URL and unregister the frame. +// With OOPIF only the first notification is sufficient in most cases, except +// for sandboxed frames with a unique origin. class ExtensionWebContentsObserver : public content::WebContentsObserver, public ExtensionFunctionDispatcher::Delegate { @@ -60,6 +77,13 @@ void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override; void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override; + void DidCommitProvisionalLoadForFrame( + content::RenderFrameHost* render_frame_host, + const GURL& url, + ui::PageTransition transition_type) override; + void DidNavigateAnyFrame(content::RenderFrameHost* render_frame_host, + const content::LoadCommittedDetails& details, + const content::FrameNavigateParams& params) override; // Subclasses should call this first before doing their own message handling. bool OnMessageReceived(const IPC::Message& message, @@ -77,8 +101,12 @@ // Returns the extension associated with the given |render_frame_host|, or // null if there is none. + // If |verify_url| is false, only the SiteInstance is taken into account. + // If |verify_url| is true, the frame's last committed URL is also used to + // improve the classification of the frame. const Extension* GetExtensionFromFrame( - content::RenderFrameHost* render_frame_host) const; + content::RenderFrameHost* render_frame_host, + bool verify_url) const; // TODO(devlin): Remove these once callers are updated to use the FromFrame // equivalents.
diff --git a/extensions/browser/guest_view/extension_options/extension_options_guest.cc b/extensions/browser/guest_view/extension_options/extension_options_guest.cc index 6a34aa0..5806540 100644 --- a/extensions/browser/guest_view/extension_options/extension_options_guest.cc +++ b/extensions/browser/guest_view/extension_options/extension_options_guest.cc
@@ -19,6 +19,7 @@ #include "extensions/browser/extension_registry.h" #include "extensions/browser/guest_view/extension_options/extension_options_constants.h" #include "extensions/browser/guest_view/extension_options/extension_options_guest_delegate.h" +#include "extensions/browser/view_type_utils.h" #include "extensions/common/api/extension_options_internal.h" #include "extensions/common/constants.h" #include "extensions/common/extension.h" @@ -108,7 +109,9 @@ content::SiteInstance::CreateForURL(browser_context(), extension_url); WebContents::CreateParams params(browser_context(), options_site_instance); params.guest_delegate = this; - callback.Run(WebContents::Create(params)); + WebContents* wc = WebContents::Create(params); + SetViewType(wc, VIEW_TYPE_EXTENSION_GUEST); + callback.Run(wc); } void ExtensionOptionsGuest::DidInitialize(
diff --git a/extensions/browser/process_manager.cc b/extensions/browser/process_manager.cc index 8b2b4b534..581219b6 100644 --- a/extensions/browser/process_manager.cc +++ b/extensions/browser/process_manager.cc
@@ -166,6 +166,7 @@ case VIEW_TYPE_APP_WINDOW: case VIEW_TYPE_BACKGROUND_CONTENTS: case VIEW_TYPE_EXTENSION_DIALOG: + case VIEW_TYPE_EXTENSION_GUEST: case VIEW_TYPE_EXTENSION_POPUP: case VIEW_TYPE_LAUNCHER_PAGE: case VIEW_TYPE_PANEL: @@ -309,6 +310,21 @@ } } +void ProcessManager::DidNavigateRenderFrameHost( + content::RenderFrameHost* render_frame_host) { + ExtensionRenderFrames::iterator frame = + all_extension_frames_.find(render_frame_host); + + if (frame != all_extension_frames_.end()) { + std::string extension_id = GetExtensionID(render_frame_host); + + FOR_EACH_OBSERVER(ProcessManagerObserver, + observer_list_, + OnExtensionFrameNavigated(extension_id, + render_frame_host)); + } +} + scoped_refptr<content::SiteInstance> ProcessManager::GetSiteInstanceForURL( const GURL& url) { return make_scoped_refptr(site_instance_->GetRelatedSiteInstance(url)); @@ -324,20 +340,19 @@ ProcessManager::FrameSet ProcessManager::GetRenderFrameHostsForExtension( const std::string& extension_id) { FrameSet result; - scoped_refptr<content::SiteInstance> site_instance(GetSiteInstanceForURL( - Extension::GetBaseURLFromExtensionId(extension_id))); - if (!site_instance.get()) - return result; - - // Gather up all the frames for that site. for (const auto& key_value : all_extension_frames_) { - if (key_value.first->GetSiteInstance() == site_instance) + if (GetExtensionID(key_value.first) == extension_id) result.insert(key_value.first); } - return result; } +bool ProcessManager::IsRenderFrameHostRegistered( + content::RenderFrameHost* render_frame_host) { + return all_extension_frames_.find(render_frame_host) != + all_extension_frames_.end(); +} + void ProcessManager::AddObserver(ProcessManagerObserver* observer) { observer_list_.AddObserver(observer); }
diff --git a/extensions/browser/process_manager.h b/extensions/browser/process_manager.h index 9d44453..c93bd80 100644 --- a/extensions/browser/process_manager.h +++ b/extensions/browser/process_manager.h
@@ -56,6 +56,7 @@ content::RenderFrameHost* render_frame_host, const Extension* extension); void UnregisterRenderFrameHost(content::RenderFrameHost* render_frame_host); + void DidNavigateRenderFrameHost(content::RenderFrameHost* render_frame_host); // Returns the SiteInstance that the given URL belongs to. // TODO(aa): This only returns correct results for extensions and packaged @@ -71,6 +72,8 @@ ProcessManager::FrameSet GetRenderFrameHostsForExtension( const std::string& extension_id); + bool IsRenderFrameHostRegistered(content::RenderFrameHost* render_frame_host); + void AddObserver(ProcessManagerObserver* observer); void RemoveObserver(ProcessManagerObserver* observer);
diff --git a/extensions/browser/process_manager_observer.h b/extensions/browser/process_manager_observer.h index 668b3df..47883ef 100644 --- a/extensions/browser/process_manager_observer.h +++ b/extensions/browser/process_manager_observer.h
@@ -30,13 +30,21 @@ // Called immediately after the extension background host is destroyed. virtual void OnBackgroundHostClose(const std::string& extension_id) {} + // Called when a RenderFrameHost has been registered in an extension process. virtual void OnExtensionFrameRegistered( const std::string& extension_id, content::RenderFrameHost* render_frame_host) {} + // Called when a RenderFrameHost is no longer part of an extension process. virtual void OnExtensionFrameUnregistered( const std::string& extension_id, content::RenderFrameHost* render_frame_host) {} + + // Called when a RenderFrameHost was navigated to another page within the + // extension process. + virtual void OnExtensionFrameNavigated( + const std::string& extension_id, + content::RenderFrameHost* render_frame_host) {} }; } // namespace extensions
diff --git a/extensions/common/view_type.h b/extensions/common/view_type.h index 82c906b5..bbe498d 100644 --- a/extensions/common/view_type.h +++ b/extensions/common/view_type.h
@@ -18,6 +18,7 @@ VIEW_TYPE_BACKGROUND_CONTENTS, VIEW_TYPE_EXTENSION_BACKGROUND_PAGE, VIEW_TYPE_EXTENSION_DIALOG, + VIEW_TYPE_EXTENSION_GUEST, VIEW_TYPE_EXTENSION_POPUP, VIEW_TYPE_LAUNCHER_PAGE, VIEW_TYPE_PANEL,
diff --git a/extensions/renderer/extension_frame_helper.cc b/extensions/renderer/extension_frame_helper.cc index fe581c33..c063f84a 100644 --- a/extensions/renderer/extension_frame_helper.cc +++ b/extensions/renderer/extension_frame_helper.cc
@@ -4,6 +4,7 @@ #include "extensions/renderer/extension_frame_helper.h" +#include "base/strings/string_util.h" #include "content/public/renderer/render_frame.h" #include "extensions/common/api/messaging/message.h" #include "extensions/common/constants.h" @@ -14,6 +15,7 @@ #include "extensions/renderer/dispatcher.h" #include "extensions/renderer/messaging_bindings.h" #include "extensions/renderer/script_context.h" +#include "third_party/WebKit/public/platform/WebSecurityOrigin.h" #include "third_party/WebKit/public/web/WebConsoleMessage.h" #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebLocalFrame.h" @@ -34,11 +36,22 @@ if (match_view_type != VIEW_TYPE_INVALID && frame_helper->view_type() != match_view_type) return false; - GURL url = frame_helper->render_frame()->GetWebFrame()->document().url(); - if (!url.SchemeIs(kExtensionScheme)) + + // Not all frames have a valid ViewType, e.g. devtools, most GuestViews, and + // unclassified detached WebContents. + if (frame_helper->view_type() == VIEW_TYPE_INVALID) return false; - if (url.host() != match_extension_id) + + // This logic matches ExtensionWebContentsObserver::GetExtensionFromFrame. + blink::WebSecurityOrigin origin = + frame_helper->render_frame()->GetWebFrame()->securityOrigin(); + if (origin.isUnique() || + !base::EqualsASCII(base::StringPiece16(origin.protocol()), + kExtensionScheme) || + !base::EqualsASCII(base::StringPiece16(origin.host()), + match_extension_id.c_str())) return false; + if (match_window_id != extension_misc::kUnknownWindowId && frame_helper->browser_window_id() != match_window_id) return false;
diff --git a/mandoline/ui/desktop_ui/BUILD.gn b/mandoline/ui/desktop_ui/BUILD.gn index f5aa86bf..e84c565 100644 --- a/mandoline/ui/desktop_ui/BUILD.gn +++ b/mandoline/ui/desktop_ui/BUILD.gn
@@ -35,6 +35,7 @@ ] deps = [ + "public/interfaces", "//base", "//components/web_view/public/cpp", "//components/web_view/public/interfaces", @@ -51,7 +52,6 @@ "//ui/views", "//ui/views/mus:for_mojo_application", "//url", - "public/interfaces", ] }
diff --git a/media/BUILD.gn b/media/BUILD.gn index 4d7e198..d53cb64 100644 --- a/media/BUILD.gn +++ b/media/BUILD.gn
@@ -395,6 +395,16 @@ "//media/base/android:media_jni_headers", "//media/base/android:video_capture_jni_headers", ] + + # Only 64 bit builds are using android-21 NDK library, check common.gypi + if (current_cpu == "arm64" || current_cpu == "x64" || + current_cpu == "mips64el") { + sources += [ + "base/android/ndk_media_codec_bridge.cc", + "base/android/ndk_media_codec_bridge.h", + ] + libs += [ "-lmediandk" ] + } allow_circular_includes_from = [ "//media/base/android" ] }
diff --git a/media/base/android/BUILD.gn b/media/base/android/BUILD.gn index c51ee6b..75c6717c 100644 --- a/media/base/android/BUILD.gn +++ b/media/base/android/BUILD.gn
@@ -31,6 +31,8 @@ "media_codec_decoder.h", "media_codec_player.cc", "media_codec_player.h", + "media_codec_util.cc", + "media_codec_util.h", "media_codec_video_decoder.cc", "media_codec_video_decoder.h", "media_decoder_job.cc", @@ -58,6 +60,8 @@ "media_task_runner.h", "media_url_interceptor.h", "provision_fetcher.h", + "sdk_media_codec_bridge.cc", + "sdk_media_codec_bridge.h", "video_decoder_job.cc", "video_decoder_job.h", "webaudio_media_codec_bridge.cc", @@ -81,12 +85,12 @@ testonly = true sources = [ "access_unit_queue_unittest.cc", - "media_codec_bridge_unittest.cc", "media_codec_decoder_unittest.cc", "media_codec_player_unittest.cc", "media_drm_bridge_unittest.cc", "media_player_bridge_unittest.cc", "media_source_player_unittest.cc", + "sdk_media_codec_bridge_unittest.cc", "test_data_factory.cc", "test_data_factory.h", "test_statistics.h", @@ -106,6 +110,7 @@ "java/src/org/chromium/media/AudioManagerAndroid.java", "java/src/org/chromium/media/AudioRecordInput.java", "java/src/org/chromium/media/MediaCodecBridge.java", + "java/src/org/chromium/media/MediaCodecUtil.java", "java/src/org/chromium/media/MediaDrmBridge.java", "java/src/org/chromium/media/MediaPlayerBridge.java", "java/src/org/chromium/media/MediaPlayerListener.java",
diff --git a/media/base/android/audio_decoder_job.cc b/media/base/android/audio_decoder_job.cc index 4ef622a..06f728a2 100644 --- a/media/base/android/audio_decoder_job.cc +++ b/media/base/android/audio_decoder_job.cc
@@ -7,7 +7,7 @@ #include "base/bind.h" #include "base/lazy_instance.h" #include "base/threading/thread.h" -#include "media/base/android/media_codec_bridge.h" +#include "media/base/android/sdk_media_codec_bridge.h" #include "media/base/audio_timestamp_helper.h" #include "media/base/timestamp_constants.h" @@ -161,10 +161,12 @@ if (!media_codec_bridge_) return STATUS_FAILURE; - if (!(static_cast<AudioCodecBridge*>(media_codec_bridge_.get()))->Start( - audio_codec_, config_sampling_rate_, num_channels_, &audio_extra_data_[0], - audio_extra_data_.size(), audio_codec_delay_ns_, audio_seek_preroll_ns_, - true, GetMediaCrypto().obj())) { + if (!(static_cast<AudioCodecBridge*>(media_codec_bridge_.get())) + ->ConfigureAndStart(audio_codec_, config_sampling_rate_, + num_channels_, &audio_extra_data_[0], + audio_extra_data_.size(), audio_codec_delay_ns_, + audio_seek_preroll_ns_, true, + GetMediaCrypto().obj())) { media_codec_bridge_.reset(); return STATUS_FAILURE; }
diff --git a/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java b/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java index 72c3964..3a62582 100644 --- a/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java +++ b/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java
@@ -22,9 +22,6 @@ import org.chromium.base.annotations.JNINamespace; import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; /** * A wrapper of the MediaCodec class to facilitate exception capturing and @@ -47,10 +44,6 @@ private static final int MEDIA_CODEC_ABORT = 8; private static final int MEDIA_CODEC_ERROR = 9; - // Codec direction. Keep this in sync with media_codec_bridge.h. - private static final int MEDIA_CODEC_DECODER = 0; - private static final int MEDIA_CODEC_ENCODER = 1; - // Max adaptive playback size to be supplied to the decoder. private static final int MAX_ADAPTIVE_PLAYBACK_WIDTH = 1920; private static final int MAX_ADAPTIVE_PLAYBACK_HEIGHT = 1080; @@ -100,37 +93,6 @@ } } - /** - * This class represents supported android codec information. - */ - private static class CodecInfo { - private final String mCodecType; // e.g. "video/x-vnd.on2.vp8". - private final String mCodecName; // e.g. "OMX.google.vp8.decoder". - private final int mDirection; - - private CodecInfo(String codecType, String codecName, - int direction) { - mCodecType = codecType; - mCodecName = codecName; - mDirection = direction; - } - - @CalledByNative("CodecInfo") - private String codecType() { - return mCodecType; - } - - @CalledByNative("CodecInfo") - private String codecName() { - return mCodecName; - } - - @CalledByNative("CodecInfo") - private int direction() { - return mDirection; - } - } - private static class DequeueOutputResult { private final int mStatus; private final int mIndex; @@ -180,105 +142,6 @@ } } - /** - * Get a list of supported android codec mimes. - */ - @SuppressWarnings("deprecation") - @CalledByNative - private static CodecInfo[] getCodecsInfo() { - // Return the first (highest-priority) codec for each MIME type. - Map<String, CodecInfo> encoderInfoMap = new HashMap<String, CodecInfo>(); - Map<String, CodecInfo> decoderInfoMap = new HashMap<String, CodecInfo>(); - int count = MediaCodecList.getCodecCount(); - for (int i = 0; i < count; ++i) { - MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i); - int direction = - info.isEncoder() ? MEDIA_CODEC_ENCODER : MEDIA_CODEC_DECODER; - String codecString = info.getName(); - String[] supportedTypes = info.getSupportedTypes(); - for (int j = 0; j < supportedTypes.length; ++j) { - Map<String, CodecInfo> map = info.isEncoder() ? encoderInfoMap : decoderInfoMap; - if (!map.containsKey(supportedTypes[j])) { - map.put(supportedTypes[j], new CodecInfo( - supportedTypes[j], codecString, direction)); - } - } - } - ArrayList<CodecInfo> codecInfos = new ArrayList<CodecInfo>( - decoderInfoMap.size() + encoderInfoMap.size()); - codecInfos.addAll(encoderInfoMap.values()); - codecInfos.addAll(decoderInfoMap.values()); - return codecInfos.toArray(new CodecInfo[codecInfos.size()]); - } - - /** - * Get a name of default android codec. - */ - @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) - @SuppressWarnings("deprecation") - @CalledByNative - private static String getDefaultCodecName(String mime, int direction) { - String codecName = ""; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { - try { - MediaCodec mediaCodec = null; - if (direction == MEDIA_CODEC_ENCODER) { - mediaCodec = MediaCodec.createEncoderByType(mime); - } else { - mediaCodec = MediaCodec.createDecoderByType(mime); - } - codecName = mediaCodec.getName(); - mediaCodec.release(); - } catch (Exception e) { - Log.w(TAG, "getDefaultCodecName: Failed to create MediaCodec: %s, direction: %d", - mime, direction, e); - } - } - return codecName; - } - - /** - * Get a list of encoder supported color formats for specified mime type. - */ - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - @SuppressWarnings("deprecation") - @CalledByNative - private static int[] getEncoderColorFormatsForMime(String mime) { - MediaCodecInfo[] codecs = null; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - MediaCodecList mediaCodecList = new MediaCodecList(MediaCodecList.ALL_CODECS); - codecs = mediaCodecList.getCodecInfos(); - } else { - int count = MediaCodecList.getCodecCount(); - if (count <= 0) { - return null; - } - codecs = new MediaCodecInfo[count]; - for (int i = 0; i < count; ++i) { - MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i); - codecs[i] = info; - } - } - - for (int i = 0; i < codecs.length; i++) { - if (!codecs[i].isEncoder()) { - continue; - } - - String[] supportedTypes = codecs[i].getSupportedTypes(); - for (int j = 0; j < supportedTypes.length; ++j) { - if (!supportedTypes[j].equalsIgnoreCase(mime)) { - continue; - } - - MediaCodecInfo.CodecCapabilities capabilities = - codecs[i].getCapabilitiesForType(mime); - return capabilities.colorFormats; - } - } - return null; - } - @SuppressWarnings("deprecation") private static String getDecoderNameForMime(String mime) { int count = MediaCodecList.getCodecCount(); @@ -321,8 +184,9 @@ boolean adaptivePlaybackSupported = false; try { // |isSecure| only applies to video decoders. - if (mime.startsWith("video") && isSecure && direction == MEDIA_CODEC_DECODER) { - String decoderName = getDecoderNameForMime(mime); + if (mime.startsWith("video") && isSecure + && direction == MediaCodecUtil.MEDIA_CODEC_DECODER) { + String decoderName = MediaCodecUtil.getDecoderNameForMime(mime); if (decoderName == null) { return null; } @@ -336,7 +200,7 @@ } mediaCodec = MediaCodec.createByCodecName(decoderName + ".secure"); } else { - if (direction == MEDIA_CODEC_ENCODER) { + if (direction == MediaCodecUtil.MEDIA_CODEC_ENCODER) { mediaCodec = MediaCodec.createEncoderByType(mime); } else { mediaCodec = MediaCodec.createDecoderByType(mime);
diff --git a/media/base/android/java/src/org/chromium/media/MediaCodecUtil.java b/media/base/android/java/src/org/chromium/media/MediaCodecUtil.java new file mode 100644 index 0000000..b498b29 --- /dev/null +++ b/media/base/android/java/src/org/chromium/media/MediaCodecUtil.java
@@ -0,0 +1,231 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.media; + +import android.annotation.TargetApi; +import android.media.MediaCodec; +import android.media.MediaCodecInfo; +import android.media.MediaCodecList; +import android.os.Build; + +import org.chromium.base.Log; +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.JNINamespace; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +/** + * A collection of MediaCodec utility functions. + */ +@JNINamespace("media") +class MediaCodecUtil { + private static final String TAG = "MediaCodecUtil"; + + // Codec direction. Keep this in sync with media_codec_bridge.h. + static final int MEDIA_CODEC_DECODER = 0; + static final int MEDIA_CODEC_ENCODER = 1; + + /** + * This class represents supported android codec information. + */ + private static class CodecInfo { + private final String mCodecType; // e.g. "video/x-vnd.on2.vp8". + private final String mCodecName; // e.g. "OMX.google.vp8.decoder". + private final int mDirection; + + private CodecInfo(String codecType, String codecName, int direction) { + mCodecType = codecType; + mCodecName = codecName; + mDirection = direction; + } + + @CalledByNative("CodecInfo") + private String codecType() { + return mCodecType; + } + + @CalledByNative("CodecInfo") + private String codecName() { + return mCodecName; + } + + @CalledByNative("CodecInfo") + private int direction() { + return mDirection; + } + } + + /** + * @return a list of supported android codec information. + */ + @SuppressWarnings("deprecation") + @CalledByNative + private static CodecInfo[] getCodecsInfo() { + // Return the first (highest-priority) codec for each MIME type. + Map<String, CodecInfo> encoderInfoMap = new HashMap<String, CodecInfo>(); + Map<String, CodecInfo> decoderInfoMap = new HashMap<String, CodecInfo>(); + int count = MediaCodecList.getCodecCount(); + for (int i = 0; i < count; ++i) { + MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i); + int direction = info.isEncoder() ? MEDIA_CODEC_ENCODER : MEDIA_CODEC_DECODER; + String codecString = info.getName(); + String[] supportedTypes = info.getSupportedTypes(); + for (int j = 0; j < supportedTypes.length; ++j) { + Map<String, CodecInfo> map = info.isEncoder() ? encoderInfoMap : decoderInfoMap; + if (!map.containsKey(supportedTypes[j])) { + map.put(supportedTypes[j], + new CodecInfo(supportedTypes[j], codecString, direction)); + } + } + } + ArrayList<CodecInfo> codecInfos = + new ArrayList<CodecInfo>(decoderInfoMap.size() + encoderInfoMap.size()); + codecInfos.addAll(encoderInfoMap.values()); + codecInfos.addAll(decoderInfoMap.values()); + return codecInfos.toArray(new CodecInfo[codecInfos.size()]); + } + + /** + * Get a name of default android codec. + * @param mime MIME type of the media. + * @param direction Whether this is encoder or decoder. + * @return name of the codec. + */ + @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) + @SuppressWarnings("deprecation") + @CalledByNative + private static String getDefaultCodecName(String mime, int direction) { + String codecName = ""; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { + try { + MediaCodec mediaCodec = null; + if (direction == MEDIA_CODEC_ENCODER) { + mediaCodec = MediaCodec.createEncoderByType(mime); + } else { + mediaCodec = MediaCodec.createDecoderByType(mime); + } + codecName = mediaCodec.getName(); + mediaCodec.release(); + } catch (Exception e) { + Log.w(TAG, "getDefaultCodecName: Failed to create MediaCodec: %s, direction: %d", + mime, direction, e); + } + } + return codecName; + } + + /** + * Get a list of encoder supported color formats for specified MIME type. + * @param mime MIME type of the media format. + * @return a list of encoder supported color formats. + */ + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + @SuppressWarnings("deprecation") + @CalledByNative + private static int[] getEncoderColorFormatsForMime(String mime) { + MediaCodecInfo[] codecs = null; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + MediaCodecList mediaCodecList = new MediaCodecList(MediaCodecList.ALL_CODECS); + codecs = mediaCodecList.getCodecInfos(); + } else { + int count = MediaCodecList.getCodecCount(); + if (count <= 0) { + return null; + } + codecs = new MediaCodecInfo[count]; + for (int i = 0; i < count; ++i) { + MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i); + codecs[i] = info; + } + } + + for (int i = 0; i < codecs.length; i++) { + if (!codecs[i].isEncoder()) { + continue; + } + + String[] supportedTypes = codecs[i].getSupportedTypes(); + for (int j = 0; j < supportedTypes.length; ++j) { + if (!supportedTypes[j].equalsIgnoreCase(mime)) { + continue; + } + + MediaCodecInfo.CodecCapabilities capabilities = + codecs[i].getCapabilitiesForType(mime); + return capabilities.colorFormats; + } + } + return null; + } + + /** + * Get decoder name for the input MIME type. + * @param mime MIME type of the media. + * @return name of the decoder. + */ + @SuppressWarnings("deprecation") + protected static String getDecoderNameForMime(String mime) { + int count = MediaCodecList.getCodecCount(); + for (int i = 0; i < count; ++i) { + MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i); + if (info.isEncoder()) { + continue; + } + + String[] supportedTypes = info.getSupportedTypes(); + for (int j = 0; j < supportedTypes.length; ++j) { + if (supportedTypes[j].equalsIgnoreCase(mime)) { + return info.getName(); + } + } + } + return null; + } + + /** + * Check if a given MIME type can be decoded. + * @param mime MIME type of the media. + * @param secure Whether secure decoder is required. + * @return true if system is able to decode, or false otherwise. + */ + @CalledByNative + private static boolean canDecode(String mime, boolean isSecure) { + // Creation of ".secure" codecs sometimes crash instead of throwing exceptions + // on pre-JBMR2 devices. + if (isSecure && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) { + return false; + } + MediaCodec mediaCodec = null; + try { + // |isSecure| only applies to video decoders. + if (mime.startsWith("video") && isSecure) { + String decoderName = getDecoderNameForMime(mime); + if (decoderName == null) return false; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + // To work around an issue that we cannot get the codec info from the secure + // decoder, create an insecure decoder first so that we can query its codec + // info. http://b/15587335. + MediaCodec insecureCodec = MediaCodec.createByCodecName(decoderName); + insecureCodec.release(); + } + mediaCodec = MediaCodec.createByCodecName(decoderName + ".secure"); + } else { + mediaCodec = MediaCodec.createDecoderByType(mime); + } + } catch (Exception e) { + Log.e(TAG, "Failed to create MediaCodec: %s, isSecure: %s", mime, isSecure, e); + } + + if (mediaCodec == null) return false; + try { + mediaCodec.release(); + } catch (IllegalStateException e) { + Log.e(TAG, "Cannot release media codec", e); + } + return true; + } +}
diff --git a/media/base/android/media_codec_audio_decoder.cc b/media/base/android/media_codec_audio_decoder.cc index 4b8a076..f68a07e 100644 --- a/media/base/android/media_codec_audio_decoder.cc +++ b/media/base/android/media_codec_audio_decoder.cc
@@ -6,8 +6,8 @@ #include "base/bind.h" #include "base/logging.h" -#include "media/base/android/media_codec_bridge.h" #include "media/base/android/media_statistics.h" +#include "media/base/android/sdk_media_codec_bridge.h" #include "media/base/audio_timestamp_helper.h" #include "media/base/demuxer_stream.h" @@ -144,16 +144,11 @@ return kConfigFailure; if (!(static_cast<AudioCodecBridge*>(media_codec_bridge_.get())) - ->Start( - configs_.audio_codec, - configs_.audio_sampling_rate, - configs_.audio_channels, - &configs_.audio_extra_data[0], - configs_.audio_extra_data.size(), - configs_.audio_codec_delay_ns, - configs_.audio_seek_preroll_ns, - true, - media_crypto)) { + ->ConfigureAndStart( + configs_.audio_codec, configs_.audio_sampling_rate, + configs_.audio_channels, &configs_.audio_extra_data[0], + configs_.audio_extra_data.size(), configs_.audio_codec_delay_ns, + configs_.audio_seek_preroll_ns, true, media_crypto)) { DVLOG(0) << class_name() << "::" << __FUNCTION__ << " failed: cannot start audio codec";
diff --git a/media/base/android/media_codec_bridge.cc b/media/base/android/media_codec_bridge.cc index 9bae69edd..c242dba3 100644 --- a/media/base/android/media_codec_bridge.cc +++ b/media/base/android/media_codec_bridge.cc
@@ -11,13 +11,8 @@ #include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "base/basictypes.h" -#include "base/lazy_instance.h" #include "base/logging.h" -#include "base/numerics/safe_conversions.h" #include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "jni/MediaCodecBridge_jni.h" -#include "media/base/bit_reader.h" #include "media/base/decrypt_config.h" using base::android::AttachCurrentThread; @@ -26,320 +21,11 @@ using base::android::JavaIntArrayToIntVector; using base::android::ScopedJavaLocalRef; -#define RETURN_ON_ERROR(condition) \ - do { \ - if (!(condition)) { \ - LOG(ERROR) << "Unable to parse AAC header: " #condition; \ - return false; \ - } \ - } while (0) - namespace media { -enum { - kBufferFlagSyncFrame = 1, // BUFFER_FLAG_SYNC_FRAME - kBufferFlagEndOfStream = 4, // BUFFER_FLAG_END_OF_STREAM - kConfigureFlagEncode = 1, // CONFIGURE_FLAG_ENCODE -}; +MediaCodecBridge::MediaCodecBridge() {} -static const std::string AudioCodecToAndroidMimeType(const AudioCodec& codec) { - switch (codec) { - case kCodecMP3: - return "audio/mpeg"; - case kCodecVorbis: - return "audio/vorbis"; - case kCodecOpus: - return "audio/opus"; - case kCodecAAC: - return "audio/mp4a-latm"; - default: - return std::string(); - } -} - -static const std::string VideoCodecToAndroidMimeType(const VideoCodec& codec) { - switch (codec) { - case kCodecH264: - return "video/avc"; - case kCodecHEVC: - return "video/hevc"; - case kCodecVP8: - return "video/x-vnd.on2.vp8"; - case kCodecVP9: - return "video/x-vnd.on2.vp9"; - default: - return std::string(); - } -} - -static const std::string CodecTypeToAndroidMimeType(const std::string& codec) { - // TODO(xhwang): Shall we handle more detailed strings like "mp4a.40.2"? - if (codec == "avc1") - return "video/avc"; - if (codec == "hvc1") - return "video/hevc"; - if (codec == "mp4a") - return "audio/mp4a-latm"; - if (codec == "vp8" || codec == "vp8.0") - return "video/x-vnd.on2.vp8"; - if (codec == "vp9" || codec == "vp9.0") - return "video/x-vnd.on2.vp9"; - if (codec == "vorbis") - return "audio/vorbis"; - if (codec == "opus") - return "audio/opus"; - return std::string(); -} - -// TODO(qinmin): using a map to help all the conversions in this class. -static const std::string AndroidMimeTypeToCodecType(const std::string& mime) { - if (mime == "video/mp4v-es") - return "mp4v"; - if (mime == "video/avc") - return "avc1"; - if (mime == "video/hevc") - return "hvc1"; - if (mime == "video/x-vnd.on2.vp8") - return "vp8"; - if (mime == "video/x-vnd.on2.vp9") - return "vp9"; - if (mime == "audio/mp4a-latm") - return "mp4a"; - if (mime == "audio/mpeg") - return "mp3"; - if (mime == "audio/vorbis") - return "vorbis"; - if (mime == "audio/opus") - return "opus"; - return std::string(); -} - -static ScopedJavaLocalRef<jintArray> -ToJavaIntArray(JNIEnv* env, scoped_ptr<jint[]> native_array, int size) { - ScopedJavaLocalRef<jintArray> j_array(env, env->NewIntArray(size)); - env->SetIntArrayRegion(j_array.obj(), 0, size, native_array.get()); - return j_array; -} - -// static -bool MediaCodecBridge::IsAvailable() { - // MediaCodec is only available on JB and greater. - if (base::android::BuildInfo::GetInstance()->sdk_int() < 16) - return false; - // Blacklist some devices on Jellybean as for MediaCodec support is buggy. - // http://crbug.com/365494. - if (base::android::BuildInfo::GetInstance()->sdk_int() == 16) { - std::string model(base::android::BuildInfo::GetInstance()->model()); - return model != "GT-I9100" && model != "GT-I9300" && model != "GT-N7000"; - } - return true; -} - -// static -bool MediaCodecBridge::SupportsSetParameters() { - // MediaCodec.setParameters() is only available starting with K. - return base::android::BuildInfo::GetInstance()->sdk_int() >= 19; -} - -// static -bool MediaCodecBridge::SupportsGetName() { - // MediaCodec.getName() is only available on JB MR2 and greater. - return base::android::BuildInfo::GetInstance()->sdk_int() >= 18; -} - -// static -std::vector<MediaCodecBridge::CodecsInfo> MediaCodecBridge::GetCodecsInfo() { - std::vector<CodecsInfo> codecs_info; - if (!IsAvailable()) - return codecs_info; - - JNIEnv* env = AttachCurrentThread(); - std::string mime_type; - ScopedJavaLocalRef<jobjectArray> j_codec_info_array = - Java_MediaCodecBridge_getCodecsInfo(env); - jsize len = env->GetArrayLength(j_codec_info_array.obj()); - for (jsize i = 0; i < len; ++i) { - ScopedJavaLocalRef<jobject> j_info( - env, env->GetObjectArrayElement(j_codec_info_array.obj(), i)); - ScopedJavaLocalRef<jstring> j_codec_type = - Java_CodecInfo_codecType(env, j_info.obj()); - ConvertJavaStringToUTF8(env, j_codec_type.obj(), &mime_type); - ScopedJavaLocalRef<jstring> j_codec_name = - Java_CodecInfo_codecName(env, j_info.obj()); - CodecsInfo info; - info.codecs = AndroidMimeTypeToCodecType(mime_type); - ConvertJavaStringToUTF8(env, j_codec_name.obj(), &info.name); - info.direction = static_cast<MediaCodecDirection>( - Java_CodecInfo_direction(env, j_info.obj())); - codecs_info.push_back(info); - } - return codecs_info; -} - -// static -std::string MediaCodecBridge::GetDefaultCodecName( - const std::string& mime_type, - MediaCodecDirection direction) { - if (!IsAvailable()) - return std::string(); - - JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime_type); - ScopedJavaLocalRef<jstring> j_codec_name = - Java_MediaCodecBridge_getDefaultCodecName(env, j_mime.obj(), direction); - return ConvertJavaStringToUTF8(env, j_codec_name.obj()); -} - -// static -std::set<int> MediaCodecBridge::GetEncoderColorFormats( - const std::string& mime_type) { - std::set<int> color_formats; - if (!IsAvailable()) - return color_formats; - - JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime_type); - ScopedJavaLocalRef<jintArray> j_color_format_array = - Java_MediaCodecBridge_getEncoderColorFormatsForMime(env, j_mime.obj()); - - if (j_color_format_array.obj()) { - std::vector<int> formats; - JavaIntArrayToIntVector(env, j_color_format_array.obj(), &formats); - color_formats = std::set<int>(formats.begin(), formats.end()); - } - - return color_formats; -} - -// static -bool MediaCodecBridge::CanDecode(const std::string& codec, bool is_secure) { - if (!IsAvailable()) - return false; - - JNIEnv* env = AttachCurrentThread(); - std::string mime = CodecTypeToAndroidMimeType(codec); - if (mime.empty()) - return false; - ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime); - ScopedJavaLocalRef<jobject> j_media_codec_bridge = - Java_MediaCodecBridge_create(env, j_mime.obj(), is_secure, false); - if (!j_media_codec_bridge.is_null()) { - Java_MediaCodecBridge_release(env, j_media_codec_bridge.obj()); - return true; - } - return false; -} - -// static -bool MediaCodecBridge::IsKnownUnaccelerated(const std::string& mime_type, - MediaCodecDirection direction) { - if (!IsAvailable()) - return true; - - std::string codec_name; - if (SupportsGetName()) { - codec_name = GetDefaultCodecName(mime_type, direction); - } else { - std::string codec_type = AndroidMimeTypeToCodecType(mime_type); - std::vector<media::MediaCodecBridge::CodecsInfo> codecs_info = - MediaCodecBridge::GetCodecsInfo(); - for (size_t i = 0; i < codecs_info.size(); ++i) { - if (codecs_info[i].codecs == codec_type && - codecs_info[i].direction == direction) { - codec_name = codecs_info[i].name; - break; - } - } - } - DVLOG(1) << __PRETTY_FUNCTION__ << "Default codec for " << mime_type << - " : " << codec_name; - // It would be nice if MediaCodecInfo externalized some notion of - // HW-acceleration but it doesn't. Android Media guidance is that the - // "OMX.google" prefix is always used for SW decoders, so that's what we - // use. "OMX.SEC.*" codec is Samsung software implementation - report it - // as unaccelerated as well. Also temporary blacklist Exynos and MediaTek - // devices while HW decoder video freezes and distortions are - // investigated - http://crbug.com/446974. - if (codec_name.length() > 0) { - return (base::StartsWith(codec_name, "OMX.google.", - base::CompareCase::SENSITIVE) || - base::StartsWith(codec_name, "OMX.SEC.", - base::CompareCase::SENSITIVE) || - base::StartsWith(codec_name, "OMX.MTK.", - base::CompareCase::SENSITIVE) || - base::StartsWith(codec_name, "OMX.Exynos.", - base::CompareCase::SENSITIVE)); - } - return true; -} - -MediaCodecBridge::MediaCodecBridge(const std::string& mime, - bool is_secure, - MediaCodecDirection direction) { - JNIEnv* env = AttachCurrentThread(); - CHECK(env); - DCHECK(!mime.empty()); - ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime); - j_media_codec_.Reset( - Java_MediaCodecBridge_create(env, j_mime.obj(), is_secure, direction)); -} - -MediaCodecBridge::~MediaCodecBridge() { - JNIEnv* env = AttachCurrentThread(); - CHECK(env); - if (j_media_codec_.obj()) - Java_MediaCodecBridge_release(env, j_media_codec_.obj()); -} - -bool MediaCodecBridge::StartInternal() { - JNIEnv* env = AttachCurrentThread(); - return Java_MediaCodecBridge_start(env, j_media_codec_.obj()); -} - -MediaCodecStatus MediaCodecBridge::Reset() { - JNIEnv* env = AttachCurrentThread(); - return static_cast<MediaCodecStatus>( - Java_MediaCodecBridge_flush(env, j_media_codec_.obj())); -} - -void MediaCodecBridge::Stop() { - JNIEnv* env = AttachCurrentThread(); - Java_MediaCodecBridge_stop(env, j_media_codec_.obj()); -} - -void MediaCodecBridge::GetOutputFormat(int* width, int* height) { - JNIEnv* env = AttachCurrentThread(); - - *width = Java_MediaCodecBridge_getOutputWidth(env, j_media_codec_.obj()); - *height = Java_MediaCodecBridge_getOutputHeight(env, j_media_codec_.obj()); -} - -int MediaCodecBridge::GetOutputSamplingRate() { - JNIEnv* env = AttachCurrentThread(); - - return Java_MediaCodecBridge_getOutputSamplingRate(env, j_media_codec_.obj()); -} - -MediaCodecStatus MediaCodecBridge::QueueInputBuffer( - int index, - const uint8* data, - size_t data_size, - const base::TimeDelta& presentation_time) { - DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size; - if (data_size > base::checked_cast<size_t>(kint32max)) - return MEDIA_CODEC_ERROR; - if (data && !FillInputBuffer(index, data, data_size)) - return MEDIA_CODEC_ERROR; - JNIEnv* env = AttachCurrentThread(); - return static_cast<MediaCodecStatus>( - Java_MediaCodecBridge_queueInputBuffer(env, - j_media_codec_.obj(), - index, - 0, - data_size, - presentation_time.InMicroseconds(), - 0)); -} +MediaCodecBridge::~MediaCodecBridge() {} MediaCodecStatus MediaCodecBridge::QueueSecureInputBuffer( int index, @@ -349,204 +35,25 @@ const std::string& iv, const std::vector<SubsampleEntry>& subsamples, const base::TimeDelta& presentation_time) { - return QueueSecureInputBuffer( - index, data, data_size, reinterpret_cast<const uint8_t*>(key_id.data()), - key_id.size(), reinterpret_cast<const uint8_t*>(iv.data()), iv.size(), - subsamples.empty() ? nullptr : &subsamples[0], subsamples.size(), - presentation_time); -} - -// TODO(timav): Combine this and above methods together keeping only the first -// interface after we switch to Spitzer pipeline. -MediaCodecStatus MediaCodecBridge::QueueSecureInputBuffer( - int index, - const uint8* data, - size_t data_size, - const uint8* key_id, - int key_id_size, - const uint8* iv, - int iv_size, - const SubsampleEntry* subsamples, - int subsamples_size, - const base::TimeDelta& presentation_time) { - DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size; - if (data_size > base::checked_cast<size_t>(kint32max)) - return MEDIA_CODEC_ERROR; - if (data && !FillInputBuffer(index, data, data_size)) - return MEDIA_CODEC_ERROR; - - JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jbyteArray> j_key_id = - base::android::ToJavaByteArray(env, key_id, key_id_size); - ScopedJavaLocalRef<jbyteArray> j_iv = - base::android::ToJavaByteArray(env, iv, iv_size); - - // MediaCodec.CryptoInfo documentations says passing NULL for |clear_array| - // to indicate that all data is encrypted. But it doesn't specify what - // |cypher_array| and |subsamples_size| should be in that case. Passing - // one subsample here just to be on the safe side. - int new_subsamples_size = subsamples_size == 0 ? 1 : subsamples_size; - - scoped_ptr<jint[]> native_clear_array(new jint[new_subsamples_size]); - scoped_ptr<jint[]> native_cypher_array(new jint[new_subsamples_size]); - - if (subsamples_size == 0) { - DCHECK(!subsamples); - native_clear_array[0] = 0; - native_cypher_array[0] = data_size; - } else { - DCHECK_GT(subsamples_size, 0); - DCHECK(subsamples); - for (int i = 0; i < subsamples_size; ++i) { - DCHECK(subsamples[i].clear_bytes <= std::numeric_limits<uint16>::max()); - if (subsamples[i].cypher_bytes > - static_cast<uint32>(std::numeric_limits<jint>::max())) { - return MEDIA_CODEC_ERROR; - } - - native_clear_array[i] = subsamples[i].clear_bytes; - native_cypher_array[i] = subsamples[i].cypher_bytes; - } - } - - ScopedJavaLocalRef<jintArray> clear_array = - ToJavaIntArray(env, native_clear_array.Pass(), new_subsamples_size); - ScopedJavaLocalRef<jintArray> cypher_array = - ToJavaIntArray(env, native_cypher_array.Pass(), new_subsamples_size); - - return static_cast<MediaCodecStatus>( - Java_MediaCodecBridge_queueSecureInputBuffer( - env, - j_media_codec_.obj(), - index, - 0, - j_iv.obj(), - j_key_id.obj(), - clear_array.obj(), - cypher_array.obj(), - new_subsamples_size, - presentation_time.InMicroseconds())); -} - -void MediaCodecBridge::QueueEOS(int input_buffer_index) { - DVLOG(3) << __PRETTY_FUNCTION__ << ": " << input_buffer_index; - JNIEnv* env = AttachCurrentThread(); - Java_MediaCodecBridge_queueInputBuffer(env, - j_media_codec_.obj(), - input_buffer_index, - 0, - 0, - 0, - kBufferFlagEndOfStream); -} - -MediaCodecStatus MediaCodecBridge::DequeueInputBuffer( - const base::TimeDelta& timeout, - int* index) { - JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jobject> result = Java_MediaCodecBridge_dequeueInputBuffer( - env, j_media_codec_.obj(), timeout.InMicroseconds()); - *index = Java_DequeueInputResult_index(env, result.obj()); - MediaCodecStatus status = static_cast<MediaCodecStatus>( - Java_DequeueInputResult_status(env, result.obj())); - DVLOG(3) << __PRETTY_FUNCTION__ << ": status: " << status - << ", index: " << *index; - return status; -} - -MediaCodecStatus MediaCodecBridge::DequeueOutputBuffer( - const base::TimeDelta& timeout, - int* index, - size_t* offset, - size_t* size, - base::TimeDelta* presentation_time, - bool* end_of_stream, - bool* key_frame) { - JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jobject> result = - Java_MediaCodecBridge_dequeueOutputBuffer( - env, j_media_codec_.obj(), timeout.InMicroseconds()); - *index = Java_DequeueOutputResult_index(env, result.obj()); - *offset = base::checked_cast<size_t>( - Java_DequeueOutputResult_offset(env, result.obj())); - *size = base::checked_cast<size_t>( - Java_DequeueOutputResult_numBytes(env, result.obj())); - if (presentation_time) { - *presentation_time = base::TimeDelta::FromMicroseconds( - Java_DequeueOutputResult_presentationTimeMicroseconds(env, - result.obj())); - } - int flags = Java_DequeueOutputResult_flags(env, result.obj()); - if (end_of_stream) - *end_of_stream = flags & kBufferFlagEndOfStream; - if (key_frame) - *key_frame = flags & kBufferFlagSyncFrame; - MediaCodecStatus status = static_cast<MediaCodecStatus>( - Java_DequeueOutputResult_status(env, result.obj())); - DVLOG(3) << __PRETTY_FUNCTION__ << ": status: " << status - << ", index: " << *index << ", offset: " << *offset - << ", size: " << *size << ", flags: " << flags; - return status; -} - -void MediaCodecBridge::ReleaseOutputBuffer(int index, bool render) { - DVLOG(3) << __PRETTY_FUNCTION__ << ": " << index; - JNIEnv* env = AttachCurrentThread(); - CHECK(env); - - Java_MediaCodecBridge_releaseOutputBuffer( - env, j_media_codec_.obj(), index, render); + const std::vector<char> key_vec(key_id.begin(), key_id.end()); + const std::vector<char> iv_vec(iv.begin(), iv.end()); + return QueueSecureInputBuffer(index, data, data_size, key_vec, iv_vec, + subsamples.empty() ? nullptr : &subsamples[0], + subsamples.size(), presentation_time); } int MediaCodecBridge::GetOutputBuffersCount() { - JNIEnv* env = AttachCurrentThread(); - return Java_MediaCodecBridge_getOutputBuffersCount(env, j_media_codec_.obj()); + return 0; } size_t MediaCodecBridge::GetOutputBuffersCapacity() { - JNIEnv* env = AttachCurrentThread(); - return Java_MediaCodecBridge_getOutputBuffersCapacity(env, - j_media_codec_.obj()); -} - -void MediaCodecBridge::GetInputBuffer(int input_buffer_index, - uint8** data, - size_t* capacity) { - JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jobject> j_buffer(Java_MediaCodecBridge_getInputBuffer( - env, j_media_codec_.obj(), input_buffer_index)); - *data = static_cast<uint8*>(env->GetDirectBufferAddress(j_buffer.obj())); - *capacity = base::checked_cast<size_t>( - env->GetDirectBufferCapacity(j_buffer.obj())); -} - -bool MediaCodecBridge::CopyFromOutputBuffer(int index, - size_t offset, - void* dst, - int dst_size) { - void* src_data = nullptr; - int src_capacity = GetOutputBufferAddress(index, offset, &src_data); - if (src_capacity < dst_size) - return false; - memcpy(dst, src_data, dst_size); - return true; -} - -int MediaCodecBridge::GetOutputBufferAddress(int index, - size_t offset, - void** addr) { - JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jobject> j_buffer( - Java_MediaCodecBridge_getOutputBuffer(env, j_media_codec_.obj(), index)); - *addr = reinterpret_cast<uint8*>( - env->GetDirectBufferAddress(j_buffer.obj())) + offset; - return env->GetDirectBufferCapacity(j_buffer.obj()) - offset; + return 0; } bool MediaCodecBridge::FillInputBuffer(int index, const uint8* data, size_t size) { - uint8* dst = NULL; + uint8* dst = nullptr; size_t capacity = 0; GetInputBuffer(index, &dst, &capacity); CHECK(dst); @@ -561,334 +68,4 @@ return true; } -AudioCodecBridge::AudioCodecBridge(const std::string& mime) - // Audio codec doesn't care about security level and there is no need for - // audio encoding yet. - : MediaCodecBridge(mime, false, MEDIA_CODEC_DECODER) {} - -bool AudioCodecBridge::Start(const AudioCodec& codec, - int sample_rate, - int channel_count, - const uint8* extra_data, - size_t extra_data_size, - int64 codec_delay_ns, - int64 seek_preroll_ns, - bool play_audio, - jobject media_crypto) { - JNIEnv* env = AttachCurrentThread(); - - if (!media_codec()) - return false; - - std::string codec_string = AudioCodecToAndroidMimeType(codec); - if (codec_string.empty()) - return false; - - ScopedJavaLocalRef<jstring> j_mime = - ConvertUTF8ToJavaString(env, codec_string); - ScopedJavaLocalRef<jobject> j_format(Java_MediaCodecBridge_createAudioFormat( - env, j_mime.obj(), sample_rate, channel_count)); - DCHECK(!j_format.is_null()); - - if (!ConfigureMediaFormat(j_format.obj(), codec, extra_data, extra_data_size, - codec_delay_ns, seek_preroll_ns)) { - return false; - } - - if (!Java_MediaCodecBridge_configureAudio( - env, media_codec(), j_format.obj(), media_crypto, 0, play_audio)) { - return false; - } - - return StartInternal(); -} - -bool AudioCodecBridge::ConfigureMediaFormat(jobject j_format, - const AudioCodec& codec, - const uint8* extra_data, - size_t extra_data_size, - int64 codec_delay_ns, - int64 seek_preroll_ns) { - if (extra_data_size == 0 && codec != kCodecOpus) - return true; - - JNIEnv* env = AttachCurrentThread(); - switch (codec) { - case kCodecVorbis: { - if (extra_data[0] != 2) { - LOG(ERROR) << "Invalid number of vorbis headers before the codec " - << "header: " << extra_data[0]; - return false; - } - - size_t header_length[2]; - // |total_length| keeps track of the total number of bytes before the last - // header. - size_t total_length = 1; - const uint8* current_pos = extra_data; - // Calculate the length of the first 2 headers. - for (int i = 0; i < 2; ++i) { - header_length[i] = 0; - while (total_length < extra_data_size) { - size_t size = *(++current_pos); - total_length += 1 + size; - if (total_length > 0x80000000) { - LOG(ERROR) << "Vorbis header size too large"; - return false; - } - header_length[i] += size; - if (size < 0xFF) - break; - } - if (total_length >= extra_data_size) { - LOG(ERROR) << "Invalid vorbis header size in the extra data"; - return false; - } - } - current_pos++; - // The first header is identification header. - ScopedJavaLocalRef<jbyteArray> first_header = - base::android::ToJavaByteArray(env, current_pos, header_length[0]); - Java_MediaCodecBridge_setCodecSpecificData( - env, j_format, 0, first_header.obj()); - // The last header is codec header. - ScopedJavaLocalRef<jbyteArray> last_header = - base::android::ToJavaByteArray( - env, extra_data + total_length, extra_data_size - total_length); - Java_MediaCodecBridge_setCodecSpecificData( - env, j_format, 1, last_header.obj()); - break; - } - case kCodecAAC: { - media::BitReader reader(extra_data, extra_data_size); - - // The following code is copied from aac.cc - // TODO(qinmin): refactor the code in aac.cc to make it more reusable. - uint8 profile = 0; - uint8 frequency_index = 0; - uint8 channel_config = 0; - RETURN_ON_ERROR(reader.ReadBits(5, &profile)); - RETURN_ON_ERROR(reader.ReadBits(4, &frequency_index)); - - if (0xf == frequency_index) - RETURN_ON_ERROR(reader.SkipBits(24)); - RETURN_ON_ERROR(reader.ReadBits(4, &channel_config)); - - if (profile == 5 || profile == 29) { - // Read extension config. - RETURN_ON_ERROR(reader.ReadBits(4, &frequency_index)); - if (frequency_index == 0xf) - RETURN_ON_ERROR(reader.SkipBits(24)); - RETURN_ON_ERROR(reader.ReadBits(5, &profile)); - } - - if (profile < 1 || profile > 4 || frequency_index == 0xf || - channel_config > 7) { - LOG(ERROR) << "Invalid AAC header"; - return false; - } - const size_t kCsdLength = 2; - uint8 csd[kCsdLength]; - csd[0] = profile << 3 | frequency_index >> 1; - csd[1] = (frequency_index & 0x01) << 7 | channel_config << 3; - ScopedJavaLocalRef<jbyteArray> byte_array = - base::android::ToJavaByteArray(env, csd, kCsdLength); - Java_MediaCodecBridge_setCodecSpecificData( - env, j_format, 0, byte_array.obj()); - - // TODO(qinmin): pass an extra variable to this function to determine - // whether we need to call this. - Java_MediaCodecBridge_setFrameHasADTSHeader(env, j_format); - break; - } - case kCodecOpus: { - if (!extra_data || extra_data_size == 0 || - codec_delay_ns < 0 || seek_preroll_ns < 0) { - LOG(ERROR) << "Invalid Opus Header"; - return false; - } - - // csd0 - Opus Header - ScopedJavaLocalRef<jbyteArray> csd0 = - base::android::ToJavaByteArray(env, extra_data, extra_data_size); - Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, csd0.obj()); - - // csd1 - Codec Delay - ScopedJavaLocalRef<jbyteArray> csd1 = - base::android::ToJavaByteArray( - env, reinterpret_cast<const uint8*>(&codec_delay_ns), - sizeof(int64_t)); - Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 1, csd1.obj()); - - // csd2 - Seek Preroll - ScopedJavaLocalRef<jbyteArray> csd2 = - base::android::ToJavaByteArray( - env, reinterpret_cast<const uint8*>(&seek_preroll_ns), - sizeof(int64_t)); - Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 2, csd2.obj()); - break; - } - default: - LOG(ERROR) << "Invalid header encountered for codec: " - << AudioCodecToAndroidMimeType(codec); - return false; - } - return true; -} - -int64 AudioCodecBridge::PlayOutputBuffer(int index, - size_t size, - size_t offset, - bool postpone) { - DCHECK_LE(0, index); - int numBytes = base::checked_cast<int>(size); - - void* buffer = nullptr; - int capacity = GetOutputBufferAddress(index, offset, &buffer); - numBytes = std::min(capacity, numBytes); - CHECK_GE(numBytes, 0); - - JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jbyteArray> byte_array = base::android::ToJavaByteArray( - env, static_cast<uint8*>(buffer), numBytes); - return Java_MediaCodecBridge_playOutputBuffer(env, media_codec(), - byte_array.obj(), postpone); -} - -void AudioCodecBridge::SetVolume(double volume) { - JNIEnv* env = AttachCurrentThread(); - Java_MediaCodecBridge_setVolume(env, media_codec(), volume); -} - -// static -AudioCodecBridge* AudioCodecBridge::Create(const AudioCodec& codec) { - if (!MediaCodecBridge::IsAvailable()) - return NULL; - - const std::string mime = AudioCodecToAndroidMimeType(codec); - return mime.empty() ? NULL : new AudioCodecBridge(mime); -} - -// static -bool AudioCodecBridge::IsKnownUnaccelerated(const AudioCodec& codec) { - return MediaCodecBridge::IsKnownUnaccelerated( - AudioCodecToAndroidMimeType(codec), MEDIA_CODEC_DECODER); -} - -// static -bool VideoCodecBridge::IsKnownUnaccelerated(const VideoCodec& codec, - MediaCodecDirection direction) { - return MediaCodecBridge::IsKnownUnaccelerated( - VideoCodecToAndroidMimeType(codec), direction); -} - -// static -VideoCodecBridge* VideoCodecBridge::CreateDecoder(const VideoCodec& codec, - bool is_secure, - const gfx::Size& size, - jobject surface, - jobject media_crypto) { - if (!MediaCodecBridge::IsAvailable()) - return NULL; - - const std::string mime = VideoCodecToAndroidMimeType(codec); - if (mime.empty()) - return NULL; - - scoped_ptr<VideoCodecBridge> bridge( - new VideoCodecBridge(mime, is_secure, MEDIA_CODEC_DECODER)); - if (!bridge->media_codec()) - return NULL; - - JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime); - ScopedJavaLocalRef<jobject> j_format( - Java_MediaCodecBridge_createVideoDecoderFormat( - env, j_mime.obj(), size.width(), size.height())); - DCHECK(!j_format.is_null()); - if (!Java_MediaCodecBridge_configureVideo(env, - bridge->media_codec(), - j_format.obj(), - surface, - media_crypto, - 0)) { - return NULL; - } - - return bridge->StartInternal() ? bridge.release() : NULL; -} - -// static -VideoCodecBridge* VideoCodecBridge::CreateEncoder(const VideoCodec& codec, - const gfx::Size& size, - int bit_rate, - int frame_rate, - int i_frame_interval, - int color_format) { - if (!MediaCodecBridge::IsAvailable()) - return NULL; - - const std::string mime = VideoCodecToAndroidMimeType(codec); - if (mime.empty()) - return NULL; - - scoped_ptr<VideoCodecBridge> bridge( - new VideoCodecBridge(mime, false, MEDIA_CODEC_ENCODER)); - if (!bridge->media_codec()) - return NULL; - - JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime); - ScopedJavaLocalRef<jobject> j_format( - Java_MediaCodecBridge_createVideoEncoderFormat(env, - j_mime.obj(), - size.width(), - size.height(), - bit_rate, - frame_rate, - i_frame_interval, - color_format)); - DCHECK(!j_format.is_null()); - if (!Java_MediaCodecBridge_configureVideo(env, - bridge->media_codec(), - j_format.obj(), - NULL, - NULL, - kConfigureFlagEncode)) { - return NULL; - } - - return bridge->StartInternal() ? bridge.release() : NULL; -} - -VideoCodecBridge::VideoCodecBridge(const std::string& mime, - bool is_secure, - MediaCodecDirection direction) - : MediaCodecBridge(mime, is_secure, direction), - adaptive_playback_supported_for_testing_(-1) {} - -void VideoCodecBridge::SetVideoBitrate(int bps) { - JNIEnv* env = AttachCurrentThread(); - Java_MediaCodecBridge_setVideoBitrate(env, media_codec(), bps); -} - -void VideoCodecBridge::RequestKeyFrameSoon() { - JNIEnv* env = AttachCurrentThread(); - Java_MediaCodecBridge_requestKeyFrameSoon(env, media_codec()); -} - -bool VideoCodecBridge::IsAdaptivePlaybackSupported(int width, int height) { - if (adaptive_playback_supported_for_testing_ == 0) - return false; - else if (adaptive_playback_supported_for_testing_ > 0) - return true; - JNIEnv* env = AttachCurrentThread(); - return Java_MediaCodecBridge_isAdaptivePlaybackSupported( - env, media_codec(), width, height); -} - -bool MediaCodecBridge::RegisterMediaCodecBridge(JNIEnv* env) { - return RegisterNativesImpl(env); -} - } // namespace media
diff --git a/media/base/android/media_codec_bridge.h b/media/base/android/media_codec_bridge.h index 73f070d..0719448f3 100644 --- a/media/base/android/media_codec_bridge.h +++ b/media/base/android/media_codec_bridge.h
@@ -5,15 +5,14 @@ #ifndef MEDIA_BASE_ANDROID_MEDIA_CODEC_BRIDGE_H_ #define MEDIA_BASE_ANDROID_MEDIA_CODEC_BRIDGE_H_ -#include <jni.h> #include <set> #include <string> +#include <vector> -#include "base/android/scoped_java_ref.h" +#include "base/compiler_specific.h" #include "base/time/time.h" -#include "media/base/audio_decoder_config.h" -#include "media/base/video_decoder_config.h" -#include "ui/gfx/geometry/size.h" +#include "media/base/android/media_codec_util.h" +#include "media/base/media_export.h" namespace media { @@ -34,59 +33,12 @@ MEDIA_CODEC_ERROR }; -// Codec direction. Keep this in sync with MediaCodecBridge.java. -enum MediaCodecDirection { - MEDIA_CODEC_DECODER, - MEDIA_CODEC_ENCODER, -}; - -// This class serves as a bridge for native code to call java functions inside -// Android MediaCodec class. For more information on Android MediaCodec, check +// Interface for wrapping different Android MediaCodec implementations. For +// more information on Android MediaCodec, check // http://developer.android.com/reference/android/media/MediaCodec.html // Note: MediaCodec is only available on JB and greater. -// Use AudioCodecBridge or VideoCodecBridge to create an instance of this -// object. -// -// TODO(fischman,xhwang): replace this (and the enums that go with it) with -// chromium's JNI auto-generation hotness. class MEDIA_EXPORT MediaCodecBridge { public: - // Returns true if MediaCodec is available on the device. - // All other static methods check IsAvailable() internally. There's no need - // to check IsAvailable() explicitly before calling them. - static bool IsAvailable(); - - // Returns true if MediaCodec.setParameters() is available on the device. - static bool SupportsSetParameters(); - - // Returns true if MediaCodec.getName() is available on the device. - static bool SupportsGetName(); - - // Returns whether MediaCodecBridge has a decoder that |is_secure| and can - // decode |codec| type. - static bool CanDecode(const std::string& codec, bool is_secure); - - // Represents supported codecs on android. - // TODO(qinmin): Currently the codecs string only contains one codec. Do we - // need to support codecs separated by comma. (e.g. "vp8" -> "vp8, vp8.0")? - struct CodecsInfo { - std::string codecs; // E.g. "vp8" or "avc1". - std::string name; // E.g. "OMX.google.vp8.decoder". - MediaCodecDirection direction; - }; - - // Get a list of supported codecs. - static std::vector<CodecsInfo> GetCodecsInfo(); - - // Get default codec name for |mime_type|. - static std::string GetDefaultCodecName(const std::string& mime_type, - MediaCodecDirection direction); - - // Get a list of encoder supported color formats for |mime_type|. - // The mapping of color format name and its value refers to - // MediaCodecInfo.CodecCapabilities. - static std::set<int> GetEncoderColorFormats(const std::string& mime_type); - virtual ~MediaCodecBridge(); // Resets both input and output, all indices previously returned in calls to @@ -95,31 +47,36 @@ // words, there will be no outputs until new input is provided. // Returns MEDIA_CODEC_ERROR if an unexpected error happens, or Media_CODEC_OK // otherwise. - MediaCodecStatus Reset(); + virtual MediaCodecStatus Reset() = 0; + + // Calls start() against the media codec instance. Returns whether media + // codec was successfully started. + virtual bool Start() = 0; // Finishes the decode/encode session. The instance remains active // and ready to be StartAudio/Video()ed again. HOWEVER, due to the buggy // vendor's implementation , b/8125974, Stop() -> StartAudio/Video() may not // work on some devices. For reliability, Stop() -> delete and recreate new // instance -> StartAudio/Video() is recommended. - void Stop(); + virtual void Stop() = 0; // Used for getting output format. This is valid after DequeueInputBuffer() // returns a format change by returning INFO_OUTPUT_FORMAT_CHANGED - void GetOutputFormat(int* width, int* height); + virtual void GetOutputFormat(int* width, int* height) = 0; // Used for checking for new sampling rate after DequeueInputBuffer() returns // INFO_OUTPUT_FORMAT_CHANGED - int GetOutputSamplingRate(); + virtual int GetOutputSamplingRate() = 0; // Submits a byte array to the given input buffer. Call this after getting an - // available buffer from DequeueInputBuffer(). If |data| is NULL, assume the + // available buffer from DequeueInputBuffer(). If |data| is NULL, assume the // input buffer has already been populated (but still obey |size|). // |data_size| must be less than kint32max (because Java). - MediaCodecStatus QueueInputBuffer(int index, - const uint8* data, - size_t data_size, - const base::TimeDelta& presentation_time); + virtual MediaCodecStatus QueueInputBuffer( + int index, + const uint8* data, + size_t data_size, + const base::TimeDelta& presentation_time) = 0; // Similar to the above call, but submits a buffer that is encrypted. Note: // NULL |subsamples| indicates the whole buffer is encrypted. If |data| is @@ -138,20 +95,18 @@ // and MediaCodecPlayer. // TODO(timav): remove this method and keep only the one above after we // switch to the Spitzer pipeline. - MediaCodecStatus QueueSecureInputBuffer( + virtual MediaCodecStatus QueueSecureInputBuffer( int index, const uint8* data, size_t data_size, - const uint8* key_id, - int key_id_size, - const uint8* iv, - int iv_size, + const std::vector<char>& key_id, + const std::vector<char>& iv, const SubsampleEntry* subsamples, int subsamples_size, - const base::TimeDelta& presentation_time); + const base::TimeDelta& presentation_time) = 0; // Submits an empty buffer with a EOS (END OF STREAM) flag. - void QueueEOS(int input_buffer_index); + virtual void QueueEOS(int input_buffer_index) = 0; // Returns: // MEDIA_CODEC_OK if an input buffer is ready to be filled with valid data, @@ -159,8 +114,8 @@ // MEDIA_CODEC_ERROR if unexpected error happens. // Note: Never use infinite timeout as this would block the decoder thread and // prevent the decoder job from being released. - MediaCodecStatus DequeueInputBuffer(const base::TimeDelta& timeout, - int* index); + virtual MediaCodecStatus DequeueInputBuffer(const base::TimeDelta& timeout, + int* index) = 0; // Dequeues an output buffer, block at most timeout_us microseconds. // Returns the status of this operation. If OK is returned, the output @@ -171,159 +126,51 @@ // prevent the decoder job from being released. // TODO(xhwang): Can we drop |end_of_stream| and return // MEDIA_CODEC_OUTPUT_END_OF_STREAM? - MediaCodecStatus DequeueOutputBuffer(const base::TimeDelta& timeout, - int* index, - size_t* offset, - size_t* size, - base::TimeDelta* presentation_time, - bool* end_of_stream, - bool* key_frame); + virtual MediaCodecStatus DequeueOutputBuffer( + const base::TimeDelta& timeout, + int* index, + size_t* offset, + size_t* size, + base::TimeDelta* presentation_time, + bool* end_of_stream, + bool* key_frame) = 0; // Returns the buffer to the codec. If you previously specified a surface when // configuring this video decoder you can optionally render the buffer. - void ReleaseOutputBuffer(int index, bool render); + virtual void ReleaseOutputBuffer(int index, bool render) = 0; // Returns the number of output buffers used by the codec. // TODO(qinmin): this call is deprecated in Lollipop. - int GetOutputBuffersCount(); + virtual int GetOutputBuffersCount(); // Returns the capacity of each output buffer used by the codec. // TODO(qinmin): this call is deprecated in Lollipop. - size_t GetOutputBuffersCapacity(); + virtual size_t GetOutputBuffersCapacity(); // Returns an input buffer's base pointer and capacity. - void GetInputBuffer(int input_buffer_index, uint8** data, size_t* capacity); + virtual void GetInputBuffer(int input_buffer_index, + uint8** data, + size_t* capacity) = 0; // Copy |dst_size| bytes from output buffer |index|'s |offset| onwards into // |*dst|. - bool CopyFromOutputBuffer(int index, size_t offset, void* dst, int dst_size); - - static bool RegisterMediaCodecBridge(JNIEnv* env); + virtual bool CopyFromOutputBuffer(int index, + size_t offset, + void* dst, + int dst_size) = 0; protected: - // Returns true if |mime_type| is known to be unaccelerated (i.e. backed by a - // software codec instead of a hardware one). - static bool IsKnownUnaccelerated(const std::string& mime_type, - MediaCodecDirection direction); + MediaCodecBridge(); - MediaCodecBridge(const std::string& mime, - bool is_secure, - MediaCodecDirection direction); - - // Calls start() against the media codec instance. Used in StartXXX() after - // configuring media codec. Returns whether media codec was successfully - // started. - bool StartInternal() WARN_UNUSED_RESULT; - - // Called to get the buffer address given the output buffer index and offset. - // This function returns the size of the output and |addr| is the pointer to - // the address to read. - int GetOutputBufferAddress(int index, size_t offset, void** addr); - - jobject media_codec() { return j_media_codec_.obj(); } - MediaCodecDirection direction_; - - private: // Fills a particular input buffer; returns false if |data_size| exceeds the // input buffer's capacity (and doesn't touch the input buffer in that case). bool FillInputBuffer(int index, const uint8* data, size_t data_size) WARN_UNUSED_RESULT; - // Java MediaCodec instance. - base::android::ScopedJavaGlobalRef<jobject> j_media_codec_; - DISALLOW_COPY_AND_ASSIGN(MediaCodecBridge); }; -class AudioCodecBridge : public MediaCodecBridge { - public: - // Returns an AudioCodecBridge instance if |codec| is supported, or a NULL - // pointer otherwise. - static AudioCodecBridge* Create(const AudioCodec& codec); - - // See MediaCodecBridge::IsKnownUnaccelerated(). - static bool IsKnownUnaccelerated(const AudioCodec& codec); - - // Start the audio codec bridge. - bool Start(const AudioCodec& codec, int sample_rate, int channel_count, - const uint8* extra_data, size_t extra_data_size, - int64 codec_delay_ns, int64 seek_preroll_ns, - bool play_audio, jobject media_crypto) WARN_UNUSED_RESULT; - - // Plays the output buffer right away or save for later playback if |postpone| - // is set to true. This call must be called after DequeueOutputBuffer() and - // before ReleaseOutputBuffer. The data is extracted from the output buffers - // using |index|, |size| and |offset|. Returns the playback head position - // expressed in frames. - // When |postpone| is set to true, the next PlayOutputBuffer() should have - // postpone == false, and it will play two buffers: the postponed one and - // the one identified by |index|. - int64 PlayOutputBuffer(int index, - size_t size, - size_t offset, - bool postpone = false); - - // Set the volume of the audio output. - void SetVolume(double volume); - - private: - explicit AudioCodecBridge(const std::string& mime); - - // Configure the java MediaFormat object with the extra codec data passed in. - bool ConfigureMediaFormat(jobject j_format, const AudioCodec& codec, - const uint8* extra_data, size_t extra_data_size, - int64 codec_delay_ns, int64 seek_preroll_ns); -}; - -class MEDIA_EXPORT VideoCodecBridge : public MediaCodecBridge { - public: - // See MediaCodecBridge::IsKnownUnaccelerated(). - static bool IsKnownUnaccelerated(const VideoCodec& codec, - MediaCodecDirection direction); - - // Create, start, and return a VideoCodecBridge decoder or NULL on failure. - static VideoCodecBridge* CreateDecoder( - const VideoCodec& codec, // e.g. media::kCodecVP8 - bool is_secure, - const gfx::Size& size, // Output frame size. - jobject surface, // Output surface, optional. - jobject media_crypto); // MediaCrypto object, optional. - - // Create, start, and return a VideoCodecBridge encoder or NULL on failure. - static VideoCodecBridge* CreateEncoder( - const VideoCodec& codec, // e.g. media::kCodecVP8 - const gfx::Size& size, // input frame size - int bit_rate, // bits/second - int frame_rate, // frames/second - int i_frame_interval, // count - int color_format); // MediaCodecInfo.CodecCapabilities. - - void SetVideoBitrate(int bps); - void RequestKeyFrameSoon(); - - // Returns whether adaptive playback is supported for this object given - // the new size. - bool IsAdaptivePlaybackSupported(int width, int height); - - // Test-only method to set the return value of IsAdaptivePlaybackSupported(). - // Without this function, the return value of that function will be device - // dependent. If |adaptive_playback_supported| is equal to 0, the return value - // will be false. If |adaptive_playback_supported| is larger than 0, the - // return value will be true. - void set_adaptive_playback_supported_for_testing( - int adaptive_playback_supported) { - adaptive_playback_supported_for_testing_ = adaptive_playback_supported; - } - - private: - VideoCodecBridge(const std::string& mime, - bool is_secure, - MediaCodecDirection direction); - - int adaptive_playback_supported_for_testing_; -}; - } // namespace media #endif // MEDIA_BASE_ANDROID_MEDIA_CODEC_BRIDGE_H_
diff --git a/media/base/android/media_codec_bridge_unittest.cc b/media/base/android/media_codec_bridge_unittest.cc deleted file mode 100644 index f1c04711..0000000 --- a/media/base/android/media_codec_bridge_unittest.cc +++ /dev/null
@@ -1,319 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <string> - -#include "base/basictypes.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "media/base/android/media_codec_bridge.h" -#include "media/base/decoder_buffer.h" -#include "media/base/test_data_util.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace { - -// The first frame of -// http://www.html5rocks.com/en/tutorials/audio/quick/test.mp3 -unsigned char test_mp3[] = { - 0xff, 0xfb, 0xd2, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x05, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0d, 0x20, 0x00, 0x00, 0x00, 0x2a, 0x7e, 0x40, - 0xc0, 0x19, 0x4a, 0x80, 0x0d, 0x60, 0x48, 0x1b, 0x40, 0xf7, 0xbd, 0xb9, - 0xd9, 0x40, 0x6f, 0x82, 0x01, 0x8b, 0x17, 0xa0, 0x80, 0xc5, 0x01, 0xad, - 0x9a, 0xd3, 0x00, 0x12, 0xc0, 0x72, 0x93, 0x67, 0xd0, 0x03, 0x6f, 0xa4, - 0xc0, 0xc3, 0x23, 0xee, 0x9b, 0xc0, 0xcc, 0x02, 0xa0, 0xa1, 0x30, 0x0c, - 0x52, 0x2d, 0xfd, 0x6e, 0x08, 0x83, 0x60, 0x40, 0x46, 0x06, 0x4b, 0x20, - 0x82, 0x82, 0x7f, 0xd4, 0x81, 0xe7, 0x00, 0x64, 0x20, 0x18, 0xec, 0xc2, - 0x06, 0x57, 0x0f, 0x81, 0x93, 0x0b, 0x00, 0x66, 0xe3, 0xb7, 0xe8, 0x32, - 0x6e, 0xf0, 0x32, 0xb0, 0x58, 0x0c, 0x7c, 0x3a, 0x03, 0x22, 0x14, 0x80, - 0xc9, 0x01, 0x80, 0x30, 0x20, 0x14, 0x0c, 0x96, 0x73, 0xfe, 0x9f, 0x6c, - 0x0c, 0xd2, 0x25, 0x0f, 0xdc, 0x0c, 0x32, 0x43, 0x03, 0x27, 0x87, 0xc0, - 0xc2, 0xc0, 0x20, 0xfc, 0x42, 0xc5, 0xff, 0xff, 0xd4, 0x80, 0x01, 0x01, - 0x80, 0xc3, 0x81, 0x01, 0x95, 0x03, 0x28, 0x82, 0xc0, 0xc3, 0x01, 0xa1, - 0x06, 0x81, 0x87, 0xc2, 0x40, 0x64, 0xc1, 0xf0, 0x12, 0x02, 0xff, 0xf6, - 0x5b, 0x9f, 0x44, 0xdc, 0xdd, 0x0b, 0x38, 0x59, 0xe0, 0x31, 0x71, 0x60, - 0x0c, 0xb4, 0x22, 0x03, 0x3b, 0x96, 0x40, 0xc8, 0x63, 0x90, 0x0a, 0x23, - 0x81, 0x9e, 0x4c, 0x20, 0x65, 0xb3, 0x18, 0x19, 0x6c, 0x42, 0x06, 0x36, - 0x1d, 0x01, 0x90, 0x87, 0xdf, 0xff, 0xd0, 0x65, 0xa6, 0xea, 0x66, 0xfd, - 0x40, 0x0c, 0x48, 0x03, 0x1a, 0x09, 0x01, 0x21, 0x98, 0x19, 0x2c, 0x36, - 0x06, 0x43, 0x21, 0x81, 0x92, 0xca, 0x60, 0x64, 0x70, 0xb8, 0x19, 0x20, - 0x6c, 0x02, 0x83, 0x80, 0xcb, 0x60, 0x65, 0x32, 0x28, 0x18, 0x64, 0x24, - 0x06, 0x3a, 0x0c, 0x00, 0xe1, 0x00, 0x18, 0xd0, 0x35, 0xff, 0xff, 0xff, - 0xe8, 0x32, 0xef, 0xb2, 0x90, 0x65, 0xbb, 0xdd, 0x94, 0x82, 0x0b, 0x4c, - 0xfa, 0x25, 0xf3, 0x74, 0x13, 0x0f, 0xf8, 0x19, 0x28, 0x84, 0x06, 0x36, - 0x11, 0x01, 0x20, 0x80, 0x18, 0xb4, 0x52, 0x0e, 0x15, 0x00, 0x30, 0x50, - 0x0c, 0x84, 0x32, 0x03, 0x11, 0x04, 0x03, 0x48, 0x04, 0x00, 0x00, 0x31, - 0x21, 0x00, 0x0c, 0x84, 0x18, 0x03, 0x07, 0x85, 0x40, 0xc6, 0xa5, 0x70, - 0x32, 0xb8, 0x7c, 0x0c, 0x54, 0x04, 0x00, 0xd0, 0x08, 0x59, 0x58, 0x18, - 0x20, 0x14, 0x06, 0x30, 0x30, 0x01, 0x9b, 0x86, 0x00, 0x6b, 0x54, 0xa8, - 0x19, 0x8c, 0x2a, 0x06, 0x16, 0x09, 0x01, 0xa0, 0xd0, 0xa0, 0x69, 0x74, - 0xb8, 0x19, 0xc4, 0x4a, 0xa3, 0xda, 0x9d, 0x1e, 0x4f, 0x05, 0xc0, 0x5b, - 0x0b, 0x03, 0xc2, 0x76, 0xa3, 0x4f, 0xb9, 0x16, 0xc2, 0x70, 0x41, 0x07, - 0xa0, 0x84, 0x16, 0x38, 0x4a, 0xc8, 0xaf, 0xee, 0x7f, 0x93, 0xb5, 0x5c, - 0x39, 0x1e, 0x29, 0xd9, 0x8c, 0x80, 0xb5, 0x80, 0xe6, 0x85, 0xb2, 0x99, - 0x68, 0x85, 0x46, 0x91, 0x60, 0xdb, 0x06, 0xfa, 0x38, 0x7a, 0xc7, 0xac, - 0x85, 0xa8, 0xd3, 0xe6, 0x99, 0x3b, 0x66, 0x43, 0x23, 0x1f, 0x84, 0xe1, - 0x65, 0x5e, 0xbc, 0x84, 0x18, 0x62, 0xe6, 0x42, 0x0b, 0x82, 0xe4, 0xd3, - 0x42, 0xd2, 0x05, 0x81, 0x4e, 0xe4, 0x9f, 0x8c, 0xc8, 0x7f, 0xa3, 0xe0, - 0x8d, 0xf1, 0x0f, 0x38, 0xe5, 0x3f, 0xc4, 0x2c, 0x24, 0x65, 0x8d, 0xb9, - 0x58, 0xac, 0x39, 0x0e, 0x37, 0x99, 0x2e, 0x85, 0xe0, 0xb7, 0x98, 0x41, - 0x20, 0x38, 0x1b, 0x95, 0x07, 0xfa, 0xa8, 0x9c, 0x21, 0x0f, 0x13, 0x8c, - 0xa5, 0xc1, 0x76, 0xae, 0x0b, 0xc1, 0x30, 0x27, 0x08, 0xc1, 0xf6, 0x4d, - 0xce, 0xb4, 0x41, 0x38, 0x1e, 0x82, 0x10, 0x74, 0x45, 0x91, 0x90, 0xff, - 0x41, 0x8b, 0x62, 0x1a, 0x71, 0xb6, 0x45, 0x63, 0x8c, 0xce, 0xb8, 0x54, - 0x1b, 0xe8, 0x5d, 0x9e, 0x35, 0x9d, 0x6c, 0xac, 0xe8, 0x83, 0xa1, 0xe9, - 0x3f, 0x13, 0x74, 0x11, 0x04, 0x10, 0xf1, 0x37, 0x38, 0xc6, 0x00, 0x60, - 0x27, 0x48, 0x38, 0x85, 0x92, 0x76, 0xb7, 0xf3, 0xa7, 0x1c, 0x4b, 0xf9, - 0x3b, 0x5a, 0x88, 0xac, 0x60, 0x1b, 0x85, 0x81, 0x16, 0xab, 0x44, 0x17, - 0x08, 0x2e, 0x0f, 0xd4, 0xe2, 0xde, 0x49, 0xc9, 0xe1, 0xc0, 0xc0, 0xa0, - 0x7e, 0x73, 0xa1, 0x67, 0xf8, 0xf5, 0x9f, 0xc4, 0x21, 0x50, 0x4f, 0x05, - 0x2c, 0xfc, 0x5c, 0xaa, 0x85, 0xb0, 0xfa, 0x67, 0x80, 0x7e, 0x0f, 0xfd, - 0x92, 0x30, 0xd5, 0xa0, 0xd4, 0x05, 0xdd, 0x06, 0x68, 0x1d, 0x6e, 0x4e, - 0x8b, 0x79, 0xd6, 0xfc, 0xff, 0x2e, 0x6e, 0x7c, 0xba, 0x03, 0x90, 0xd4, - 0x25, 0x65, 0x8e, 0xe7, 0x3a, 0xd1, 0xd6, 0xdc, 0xf0, 0xbe, 0x12, 0xc4, - 0x31, 0x08, 0x16, 0x70, 0x31, 0x85, 0x61, 0x38, 0x27, 0x0a, 0x91, 0x5f, - 0x03, 0x38, 0xeb, 0x37, 0x13, 0x48, 0x41, 0xbe, 0x7f, 0x04, 0x70, 0x62, - 0x2b, 0x15, 0x91, 0x67, 0x63, 0x4f, 0xad, 0xa7, 0x1d, 0x3f, 0x44, 0x17, - 0x02, 0x08, 0x0d, 0xf2, 0xfc, 0x03, 0xa0, 0x74, 0x21, 0x8b, 0x07, 0x3a, - 0x8d, 0x0f, 0x54, 0x58, 0x94, 0x12, 0xc5, 0x62, 0x18, 0xb9, 0x42, 0xf0, - 0x6c, 0x73, 0xa0, 0x92, 0xad, 0x27, 0x1c, 0x20, 0x0f, 0xc1, 0xca, 0x44, - 0x87, 0x47, 0xc5, 0x43, 0x23, 0x01, 0xda, 0x23, 0xe2, 0x89, 0x38, 0x9f, - 0x1f, 0x8d, 0x8c, 0xc6, 0x95, 0xa3, 0x34, 0x21, 0x21, 0x2d, 0x49, 0xea, - 0x4b, 0x05, 0x85, 0xf5, 0x58, 0x25, 0x13, 0xcd, 0x51, 0x19, 0x1a, 0x88, - 0xa6, 0x83, 0xd6, 0xd0, 0xbc, 0x25, 0x19, 0x1c, 0x92, 0x12, 0x44, 0x5d, - 0x1c, 0x04, 0xf1, 0x99, 0xdf, 0x92, 0x8e, 0x09, 0x85, 0xf3, 0x88, 0x82, - 0x4c, 0x22, 0x17, 0xc5, 0x25, 0x23, 0xed, 0x78, 0xf5, 0x41, 0xd1, 0xe9, - 0x8a, 0xb3, 0x52, 0xd1, 0x3d, 0x79, 0x81, 0x4d, 0x31, 0x24, 0xf9, 0x38, - 0x96, 0xbc, 0xf4, 0x8c, 0x25, 0xe9, 0xf2, 0x73, 0x94, 0x85, 0xc2, 0x61, - 0x6a, 0x34, 0x68, 0x65, 0x78, 0x87, 0xa6, 0x4f -}; - -} // namespace - -namespace media { - -// Helper macro to skip the test if MediaCodecBridge isn't available. -#define SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE() \ - do { \ - if (!MediaCodecBridge::IsAvailable()) { \ - VLOG(0) << "Could not run test - not supported on device."; \ - return; \ - } \ - } while (0) - -static const int kPresentationTimeBase = 100; - -static inline const base::TimeDelta InfiniteTimeOut() { - return base::TimeDelta::FromMicroseconds(-1); -} - -void DecodeMediaFrame( - VideoCodecBridge* media_codec, const uint8* data, size_t data_size, - const base::TimeDelta input_presentation_timestamp, - const base::TimeDelta initial_timestamp_lower_bound) { - base::TimeDelta input_pts = input_presentation_timestamp; - base::TimeDelta timestamp = initial_timestamp_lower_bound; - base::TimeDelta new_timestamp; - for (int i = 0; i < 10; ++i) { - int input_buf_index = -1; - MediaCodecStatus status = - media_codec->DequeueInputBuffer(InfiniteTimeOut(), &input_buf_index); - ASSERT_EQ(MEDIA_CODEC_OK, status); - - media_codec->QueueInputBuffer( - input_buf_index, data, data_size, input_presentation_timestamp); - - size_t unused_offset = 0; - size_t size = 0; - bool eos = false; - int output_buf_index = -1; - status = media_codec->DequeueOutputBuffer(InfiniteTimeOut(), - &output_buf_index, - &unused_offset, - &size, - &new_timestamp, - &eos, - NULL); - - if (status == MEDIA_CODEC_OK && output_buf_index > 0) { - media_codec->ReleaseOutputBuffer(output_buf_index, false); - } - // Output time stamp should not be smaller than old timestamp. - ASSERT_TRUE(new_timestamp >= timestamp); - input_pts += base::TimeDelta::FromMicroseconds(33000); - timestamp = new_timestamp; - } -} - -TEST(MediaCodecBridgeTest, Initialize) { - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); - - scoped_ptr<media::MediaCodecBridge> media_codec; - media_codec.reset(VideoCodecBridge::CreateDecoder( - kCodecH264, false, gfx::Size(640, 480), NULL, NULL)); -} - -TEST(MediaCodecBridgeTest, DoNormal) { - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); - - scoped_ptr<media::AudioCodecBridge> media_codec; - media_codec.reset(AudioCodecBridge::Create(kCodecMP3)); - - ASSERT_TRUE(media_codec->Start( - kCodecMP3, 44100, 2, NULL, 0, 0, 0, false, NULL)); - - int input_buf_index = -1; - MediaCodecStatus status = - media_codec->DequeueInputBuffer(InfiniteTimeOut(), &input_buf_index); - ASSERT_EQ(MEDIA_CODEC_OK, status); - ASSERT_GE(input_buf_index, 0); - - int64 input_pts = kPresentationTimeBase; - media_codec->QueueInputBuffer(input_buf_index, - test_mp3, - sizeof(test_mp3), - base::TimeDelta::FromMicroseconds(++input_pts)); - - status = media_codec->DequeueInputBuffer(InfiniteTimeOut(), &input_buf_index); - media_codec->QueueInputBuffer( - input_buf_index, test_mp3, sizeof(test_mp3), - base::TimeDelta::FromMicroseconds(++input_pts)); - - status = media_codec->DequeueInputBuffer(InfiniteTimeOut(), &input_buf_index); - media_codec->QueueEOS(input_buf_index); - - input_pts = kPresentationTimeBase; - bool eos = false; - while (!eos) { - size_t unused_offset = 0; - size_t size = 0; - base::TimeDelta timestamp; - int output_buf_index = -1; - status = media_codec->DequeueOutputBuffer(InfiniteTimeOut(), - &output_buf_index, - &unused_offset, - &size, - ×tamp, - &eos, - NULL); - switch (status) { - case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: - FAIL(); - return; - - case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: - continue; - - case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: - continue; - - default: - break; - } - ASSERT_GE(output_buf_index, 0); - EXPECT_LE(1u, size); - if (!eos) - EXPECT_EQ(++input_pts, timestamp.InMicroseconds()); - ASSERT_LE(input_pts, kPresentationTimeBase + 2); - } - ASSERT_EQ(input_pts, kPresentationTimeBase + 2); -} - -TEST(MediaCodecBridgeTest, InvalidVorbisHeader) { - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); - - scoped_ptr<media::AudioCodecBridge> media_codec; - media_codec.reset(AudioCodecBridge::Create(kCodecVorbis)); - - // The first byte of the header is not 0x02. - uint8 invalid_first_byte[] = { 0x00, 0xff, 0xff, 0xff, 0xff }; - EXPECT_FALSE(media_codec->Start( - kCodecVorbis, 44100, 2, invalid_first_byte, sizeof(invalid_first_byte), - 0, 0, false, NULL)); - - // Size of the header does not match with the data we passed in. - uint8 invalid_size[] = { 0x02, 0x01, 0xff, 0x01, 0xff }; - EXPECT_FALSE(media_codec->Start( - kCodecVorbis, 44100, 2, invalid_size, sizeof(invalid_size), - 0, 0, false, NULL)); - - // Size of the header is too large. - size_t large_size = 8 * 1024 * 1024 + 2; - uint8* very_large_header = new uint8[large_size]; - very_large_header[0] = 0x02; - for (size_t i = 1; i < large_size - 1; ++i) - very_large_header[i] = 0xff; - very_large_header[large_size - 1] = 0xfe; - EXPECT_FALSE(media_codec->Start( - kCodecVorbis, 44100, 2, very_large_header, 0x80000000, - 0, 0, false, NULL)); - delete[] very_large_header; -} - -TEST(MediaCodecBridgeTest, InvalidOpusHeader) { - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); - - scoped_ptr<media::AudioCodecBridge> media_codec; - media_codec.reset(AudioCodecBridge::Create(kCodecOpus)); - uint8 dummy_extra_data[] = { 0, 0 }; - - // Extra Data is NULL. - EXPECT_FALSE(media_codec->Start( - kCodecOpus, 48000, 2, NULL, 0, -1, 0, false, NULL)); - - // Codec Delay is < 0. - EXPECT_FALSE(media_codec->Start( - kCodecOpus, 48000, 2, dummy_extra_data, sizeof(dummy_extra_data), - -1, 0, false, NULL)); - - // Seek Preroll is < 0. - EXPECT_FALSE(media_codec->Start( - kCodecOpus, 48000, 2, dummy_extra_data, sizeof(dummy_extra_data), - 0, -1, false, NULL)); -} - -TEST(MediaCodecBridgeTest, PresentationTimestampsDoNotDecrease) { - SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); - - scoped_ptr<VideoCodecBridge> media_codec(VideoCodecBridge::CreateDecoder( - kCodecVP8, false, gfx::Size(320, 240), NULL, NULL)); - EXPECT_TRUE(media_codec.get()); - scoped_refptr<DecoderBuffer> buffer = - ReadTestDataFile("vp8-I-frame-320x240"); - DecodeMediaFrame(media_codec.get(), - buffer->data(), - buffer->data_size(), - base::TimeDelta(), - base::TimeDelta()); - - // Simulate a seek to 10 seconds, and each chunk has 2 I-frames. - std::vector<uint8> chunk(buffer->data(), - buffer->data() + buffer->data_size()); - chunk.insert(chunk.end(), buffer->data(), - buffer->data() + buffer->data_size()); - media_codec->Reset(); - DecodeMediaFrame(media_codec.get(), - &chunk[0], - chunk.size(), - base::TimeDelta::FromMicroseconds(10000000), - base::TimeDelta::FromMicroseconds(9900000)); - - // Simulate a seek to 5 seconds. - media_codec->Reset(); - DecodeMediaFrame(media_codec.get(), - &chunk[0], - chunk.size(), - base::TimeDelta::FromMicroseconds(5000000), - base::TimeDelta::FromMicroseconds(4900000)); -} - -TEST(MediaCodecBridgeTest, CreateUnsupportedCodec) { - EXPECT_EQ(NULL, AudioCodecBridge::Create(kUnknownAudioCodec)); - EXPECT_EQ( - NULL, - VideoCodecBridge::CreateDecoder( - kUnknownVideoCodec, false, gfx::Size(320, 240), NULL, NULL)); -} - -} // namespace media
diff --git a/media/base/android/media_codec_decoder.cc b/media/base/android/media_codec_decoder.cc index cdbaf07..67d7188 100644 --- a/media/base/android/media_codec_decoder.cc +++ b/media/base/android/media_codec_decoder.cc
@@ -738,9 +738,7 @@ << " subsamples size:" << unit->subsamples.size(); status = media_codec_bridge_->QueueSecureInputBuffer( - index, &unit->data[0], unit->data.size(), - reinterpret_cast<const uint8_t*>(&unit->key_id[0]), unit->key_id.size(), - reinterpret_cast<const uint8_t*>(&unit->iv[0]), unit->iv.size(), + index, &unit->data[0], unit->data.size(), unit->key_id, unit->iv, unit->subsamples.empty() ? nullptr : &unit->subsamples[0], unit->subsamples.size(), unit->timestamp); }
diff --git a/media/base/android/media_codec_decoder_unittest.cc b/media/base/android/media_codec_decoder_unittest.cc index 322407b..2b14820 100644 --- a/media/base/android/media_codec_decoder_unittest.cc +++ b/media/base/android/media_codec_decoder_unittest.cc
@@ -7,9 +7,10 @@ #include "base/thread_task_runner_handle.h" #include "base/timer/timer.h" #include "media/base/android/media_codec_audio_decoder.h" -#include "media/base/android/media_codec_bridge.h" +#include "media/base/android/media_codec_util.h" #include "media/base/android/media_codec_video_decoder.h" #include "media/base/android/media_statistics.h" +#include "media/base/android/sdk_media_codec_bridge.h" #include "media/base/android/test_data_factory.h" #include "media/base/android/test_statistics.h" #include "media/base/timestamp_constants.h" @@ -18,15 +19,6 @@ namespace media { -// Helper macro to skip the test if MediaCodecBridge isn't available. -#define SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE() \ - do { \ - if (!MediaCodecBridge::IsAvailable()) { \ - VLOG(0) << "Could not run test - not supported on device."; \ - return; \ - } \ - } while (0) - namespace { const base::TimeDelta kDefaultTimeout = base::TimeDelta::FromMilliseconds(200);
diff --git a/media/base/android/media_codec_player_unittest.cc b/media/base/android/media_codec_player_unittest.cc index 46b95fcb..628de1ce 100644 --- a/media/base/android/media_codec_player_unittest.cc +++ b/media/base/android/media_codec_player_unittest.cc
@@ -8,10 +8,11 @@ #include "base/logging.h" #include "base/timer/timer.h" #include "media/base/android/demuxer_android.h" -#include "media/base/android/media_codec_bridge.h" #include "media/base/android/media_codec_player.h" +#include "media/base/android/media_codec_util.h" #include "media/base/android/media_player_manager.h" #include "media/base/android/media_task_runner.h" +#include "media/base/android/sdk_media_codec_bridge.h" #include "media/base/android/test_data_factory.h" #include "media/base/android/test_statistics.h" #include "media/base/timestamp_constants.h" @@ -20,15 +21,6 @@ namespace media { -// Helper macro to skip the test if MediaCodecBridge isn't available. -#define SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE() \ - do { \ - if (!MediaCodecBridge::IsAvailable()) { \ - VLOG(0) << "Could not run test - not supported on device."; \ - return; \ - } \ - } while (0) - #define RUN_ON_MEDIA_THREAD(CLASS, METHOD, ...) \ do { \ if (!GetMediaTaskRunner()->BelongsToCurrentThread()) { \
diff --git a/media/base/android/media_codec_util.cc b/media/base/android/media_codec_util.cc new file mode 100644 index 0000000..cb31ef9 --- /dev/null +++ b/media/base/android/media_codec_util.cc
@@ -0,0 +1,225 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/base/android/media_codec_util.h" + +#include <algorithm> + +#include "base/android/build_info.h" +#include "base/android/jni_android.h" +#include "base/android/jni_array.h" +#include "base/android/jni_string.h" +#include "base/basictypes.h" +#include "base/logging.h" +#include "base/strings/string_util.h" +#include "jni/MediaCodecUtil_jni.h" + +using base::android::AttachCurrentThread; +using base::android::ConvertJavaStringToUTF8; +using base::android::ConvertUTF8ToJavaString; +using base::android::JavaIntArrayToIntVector; +using base::android::ScopedJavaLocalRef; + +namespace media { + +// static +const std::string CodecTypeToAndroidMimeType(const std::string& codec) { + // TODO(xhwang): Shall we handle more detailed strings like "mp4a.40.2"? + if (codec == "avc1") + return "video/avc"; + if (codec == "hvc1") + return "video/hevc"; + if (codec == "mp4a") + return "audio/mp4a-latm"; + if (codec == "vp8" || codec == "vp8.0") + return "video/x-vnd.on2.vp8"; + if (codec == "vp9" || codec == "vp9.0") + return "video/x-vnd.on2.vp9"; + if (codec == "vorbis") + return "audio/vorbis"; + if (codec == "opus") + return "audio/opus"; + return std::string(); +} + +// TODO(qinmin): using a map to help all the conversions in this class. +const std::string AndroidMimeTypeToCodecType(const std::string& mime) { + if (mime == "video/mp4v-es") + return "mp4v"; + if (mime == "video/avc") + return "avc1"; + if (mime == "video/hevc") + return "hvc1"; + if (mime == "video/x-vnd.on2.vp8") + return "vp8"; + if (mime == "video/x-vnd.on2.vp9") + return "vp9"; + if (mime == "audio/mp4a-latm") + return "mp4a"; + if (mime == "audio/mpeg") + return "mp3"; + if (mime == "audio/vorbis") + return "vorbis"; + if (mime == "audio/opus") + return "opus"; + return std::string(); +} + +std::string GetDefaultCodecName(const std::string& mime_type, + MediaCodecDirection direction) { + if (!MediaCodecUtil::IsMediaCodecAvailable()) + return std::string(); + + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime_type); + ScopedJavaLocalRef<jstring> j_codec_name = + Java_MediaCodecUtil_getDefaultCodecName(env, j_mime.obj(), direction); + return ConvertJavaStringToUTF8(env, j_codec_name.obj()); +} + +bool SupportsGetName() { + // MediaCodec.getName() is only available on JB MR2 and greater. + return base::android::BuildInfo::GetInstance()->sdk_int() >= 18; +} + +// Represents supported codecs on android. +// TODO(qinmin): Currently the codecs string only contains one codec. Do we +// need to support codecs separated by comma. (e.g. "vp8" -> "vp8, vp8.0")? +struct CodecsInfo { + std::string codecs; // E.g. "vp8" or "avc1". + std::string name; // E.g. "OMX.google.vp8.decoder". + MediaCodecDirection direction; +}; + +// Get a list of supported codecs. +std::vector<CodecsInfo> GetCodecsInfo() { + std::vector<CodecsInfo> codecs_info; + if (!MediaCodecUtil::IsMediaCodecAvailable()) + return codecs_info; + + JNIEnv* env = AttachCurrentThread(); + std::string mime_type; + ScopedJavaLocalRef<jobjectArray> j_codec_info_array = + Java_MediaCodecUtil_getCodecsInfo(env); + jsize len = env->GetArrayLength(j_codec_info_array.obj()); + for (jsize i = 0; i < len; ++i) { + ScopedJavaLocalRef<jobject> j_info( + env, env->GetObjectArrayElement(j_codec_info_array.obj(), i)); + ScopedJavaLocalRef<jstring> j_codec_type = + Java_CodecInfo_codecType(env, j_info.obj()); + ConvertJavaStringToUTF8(env, j_codec_type.obj(), &mime_type); + ScopedJavaLocalRef<jstring> j_codec_name = + Java_CodecInfo_codecName(env, j_info.obj()); + CodecsInfo info; + info.codecs = AndroidMimeTypeToCodecType(mime_type); + ConvertJavaStringToUTF8(env, j_codec_name.obj(), &info.name); + info.direction = static_cast<MediaCodecDirection>( + Java_CodecInfo_direction(env, j_info.obj())); + codecs_info.push_back(info); + } + return codecs_info; +} + +// static +bool MediaCodecUtil::IsMediaCodecAvailable() { + // MediaCodec is only available on JB and greater. + if (base::android::BuildInfo::GetInstance()->sdk_int() < 16) + return false; + // Blacklist some devices on Jellybean as for MediaCodec support is buggy. + // http://crbug.com/365494. + if (base::android::BuildInfo::GetInstance()->sdk_int() == 16) { + std::string model(base::android::BuildInfo::GetInstance()->model()); + return model != "GT-I9100" && model != "GT-I9300" && model != "GT-N7000"; + } + return true; +} + +// static +bool MediaCodecUtil::SupportsSetParameters() { + // MediaCodec.setParameters() is only available starting with K. + return base::android::BuildInfo::GetInstance()->sdk_int() >= 19; +} + +// static +std::set<int> MediaCodecUtil::GetEncoderColorFormats( + const std::string& mime_type) { + std::set<int> color_formats; + if (!IsMediaCodecAvailable()) + return color_formats; + + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime_type); + ScopedJavaLocalRef<jintArray> j_color_format_array = + Java_MediaCodecUtil_getEncoderColorFormatsForMime(env, j_mime.obj()); + + if (j_color_format_array.obj()) { + std::vector<int> formats; + JavaIntArrayToIntVector(env, j_color_format_array.obj(), &formats); + color_formats = std::set<int>(formats.begin(), formats.end()); + } + + return color_formats; +} + +// static +bool MediaCodecUtil::CanDecode(const std::string& codec, bool is_secure) { + if (!IsMediaCodecAvailable()) + return false; + + JNIEnv* env = AttachCurrentThread(); + std::string mime = CodecTypeToAndroidMimeType(codec); + if (mime.empty()) + return false; + ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime); + return Java_MediaCodecUtil_canDecode(env, j_mime.obj(), is_secure); +} + +// static +bool MediaCodecUtil::IsKnownUnaccelerated(const std::string& mime_type, + MediaCodecDirection direction) { + if (!IsMediaCodecAvailable()) + return true; + + std::string codec_name; + if (SupportsGetName()) { + codec_name = GetDefaultCodecName(mime_type, direction); + } else { + std::string codec_type = AndroidMimeTypeToCodecType(mime_type); + std::vector<CodecsInfo> codecs_info = GetCodecsInfo(); + for (size_t i = 0; i < codecs_info.size(); ++i) { + if (codecs_info[i].codecs == codec_type && + codecs_info[i].direction == direction) { + codec_name = codecs_info[i].name; + break; + } + } + } + DVLOG(1) << __PRETTY_FUNCTION__ << "Default codec for " << mime_type << " : " + << codec_name; + // It would be nice if MediaCodecInfo externalized some notion of + // HW-acceleration but it doesn't. Android Media guidance is that the + // "OMX.google" prefix is always used for SW decoders, so that's what we + // use. "OMX.SEC.*" codec is Samsung software implementation - report it + // as unaccelerated as well. Also temporary blacklist Exynos and MediaTek + // devices while HW decoder video freezes and distortions are + // investigated - http://crbug.com/446974. + if (codec_name.length() > 0) { + return (base::StartsWith(codec_name, "OMX.google.", + base::CompareCase::SENSITIVE) || + base::StartsWith(codec_name, "OMX.SEC.", + base::CompareCase::SENSITIVE) || + base::StartsWith(codec_name, "OMX.MTK.", + base::CompareCase::SENSITIVE) || + base::StartsWith(codec_name, "OMX.Exynos.", + base::CompareCase::SENSITIVE)); + } + return true; +} + +// static +bool MediaCodecUtil::RegisterMediaCodecUtil(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +} // namespace media
diff --git a/media/base/android/media_codec_util.h b/media/base/android/media_codec_util.h new file mode 100644 index 0000000..604ce5d2 --- /dev/null +++ b/media/base/android/media_codec_util.h
@@ -0,0 +1,63 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_BASE_ANDROID_MEDIA_CODEC_UTIL_H_ +#define MEDIA_BASE_ANDROID_MEDIA_CODEC_UTIL_H_ + +#include <jni.h> +#include <set> +#include <string> +#include <vector> + +#include "base/compiler_specific.h" +#include "base/macros.h" +#include "media/base/media_export.h" + +namespace media { + +// Helper macro to skip the test if MediaCodecBridge isn't available. +#define SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE() \ + do { \ + if (!MediaCodecUtil::IsMediaCodecAvailable()) { \ + VLOG(0) << "Could not run test - not supported on device."; \ + return; \ + } \ + } while (0) + +// Codec direction. Keep this in sync with MediaCodecUtil.java. +enum MediaCodecDirection { + MEDIA_CODEC_DECODER, + MEDIA_CODEC_ENCODER, +}; + +class MEDIA_EXPORT MediaCodecUtil { + public: + // Returns true if MediaCodec is available on the device. + // All other static methods check IsAvailable() internally. There's no need + // to check IsAvailable() explicitly before calling them. + static bool IsMediaCodecAvailable(); + + // Returns true if MediaCodec.setParameters() is available on the device. + static bool SupportsSetParameters(); + + // Returns whether MediaCodecBridge has a decoder that |is_secure| and can + // decode |codec| type. + static bool CanDecode(const std::string& codec, bool is_secure); + + // Get a list of encoder supported color formats for |mime_type|. + // The mapping of color format name and its value refers to + // MediaCodecInfo.CodecCapabilities. + static std::set<int> GetEncoderColorFormats(const std::string& mime_type); + + // Returns true if |mime_type| is known to be unaccelerated (i.e. backed by a + // software codec instead of a hardware one). + static bool IsKnownUnaccelerated(const std::string& mime_type, + MediaCodecDirection direction); + + static bool RegisterMediaCodecUtil(JNIEnv* env); +}; + +} // namespace media + +#endif // MEDIA_BASE_ANDROID_MEDIA_CODEC_UTIL_H_
diff --git a/media/base/android/media_codec_video_decoder.cc b/media/base/android/media_codec_video_decoder.cc index f20bbeb..928f2e7 100644 --- a/media/base/android/media_codec_video_decoder.cc +++ b/media/base/android/media_codec_video_decoder.cc
@@ -6,8 +6,8 @@ #include "base/bind.h" #include "base/logging.h" -#include "media/base/android/media_codec_bridge.h" #include "media/base/android/media_statistics.h" +#include "media/base/android/sdk_media_codec_bridge.h" #include "media/base/demuxer_stream.h" #include "media/base/timestamp_constants.h"
diff --git a/media/base/android/media_decoder_job.cc b/media/base/android/media_decoder_job.cc index 3bf5279..ed367d7 100644 --- a/media/base/android/media_decoder_job.cc +++ b/media/base/android/media_decoder_job.cc
@@ -285,13 +285,9 @@ } MediaCodecStatus status = media_codec_bridge_->QueueSecureInputBuffer( - input_buf_index, - &unit.data[0], unit.data.size(), - reinterpret_cast<const uint8*>(&unit.key_id[0]), unit.key_id.size(), - reinterpret_cast<const uint8*>(&unit.iv[0]), unit.iv.size(), + input_buf_index, &unit.data[0], unit.data.size(), unit.key_id, unit.iv, unit.subsamples.empty() ? NULL : &unit.subsamples[0], - unit.subsamples.size(), - unit.timestamp); + unit.subsamples.size(), unit.timestamp); // In case of MEDIA_CODEC_NO_KEY, we must reuse the |input_buf_index_|. // Otherwise MediaDrm will report errors.
diff --git a/media/base/android/media_jni_registrar.cc b/media/base/android/media_jni_registrar.cc index 2020469..cc8bc1d 100644 --- a/media/base/android/media_jni_registrar.cc +++ b/media/base/android/media_jni_registrar.cc
@@ -10,10 +10,11 @@ #include "media/audio/android/audio_manager_android.h" #include "media/audio/android/audio_record_input.h" -#include "media/base/android/media_codec_bridge.h" +#include "media/base/android/media_codec_util.h" #include "media/base/android/media_drm_bridge.h" #include "media/base/android/media_player_bridge.h" #include "media/base/android/media_player_listener.h" +#include "media/base/android/sdk_media_codec_bridge.h" #include "media/base/android/webaudio_media_codec_bridge.h" #include "media/capture/video/android/video_capture_device_android.h" #include "media/capture/video/android/video_capture_device_factory_android.h" @@ -21,24 +22,19 @@ namespace media { static base::android::RegistrationMethod kMediaRegisteredMethods[] = { - { "AudioManagerAndroid", - AudioManagerAndroid::RegisterAudioManager }, - { "AudioRecordInput", - AudioRecordInputStream::RegisterAudioRecordInput }, - { "MediaCodecBridge", - MediaCodecBridge::RegisterMediaCodecBridge }, - { "MediaDrmBridge", - MediaDrmBridge::RegisterMediaDrmBridge }, - { "MediaPlayerBridge", - MediaPlayerBridge::RegisterMediaPlayerBridge }, - { "MediaPlayerListener", - MediaPlayerListener::RegisterMediaPlayerListener }, - { "VideoCaptureDevice", - VideoCaptureDeviceAndroid::RegisterVideoCaptureDevice }, - { "VideoCaptureDeviceFactory", - VideoCaptureDeviceFactoryAndroid::RegisterVideoCaptureDeviceFactory }, - { "WebAudioMediaCodecBridge", - WebAudioMediaCodecBridge::RegisterWebAudioMediaCodecBridge }, + {"AudioManagerAndroid", AudioManagerAndroid::RegisterAudioManager}, + {"AudioRecordInput", AudioRecordInputStream::RegisterAudioRecordInput}, + {"MediaDrmBridge", MediaDrmBridge::RegisterMediaDrmBridge}, + {"MediaPlayerBridge", MediaPlayerBridge::RegisterMediaPlayerBridge}, + {"MediaPlayerListener", MediaPlayerListener::RegisterMediaPlayerListener}, + {"SdkMediaCodecBridge", SdkMediaCodecBridge::RegisterSdkMediaCodecBridge}, + {"MediaCodecUtil", MediaCodecUtil::RegisterMediaCodecUtil}, + {"VideoCaptureDevice", + VideoCaptureDeviceAndroid::RegisterVideoCaptureDevice}, + {"VideoCaptureDeviceFactory", + VideoCaptureDeviceFactoryAndroid::RegisterVideoCaptureDeviceFactory}, + {"WebAudioMediaCodecBridge", + WebAudioMediaCodecBridge::RegisterWebAudioMediaCodecBridge}, }; bool RegisterJni(JNIEnv* env) {
diff --git a/media/base/android/media_source_player_unittest.cc b/media/base/android/media_source_player_unittest.cc index fd4a725..b7cab6c 100644 --- a/media/base/android/media_source_player_unittest.cc +++ b/media/base/android/media_source_player_unittest.cc
@@ -9,11 +9,12 @@ #include "base/memory/scoped_ptr.h" #include "base/strings/stringprintf.h" #include "media/base/android/audio_decoder_job.h" -#include "media/base/android/media_codec_bridge.h" +#include "media/base/android/media_codec_util.h" #include "media/base/android/media_drm_bridge.h" #include "media/base/android/media_player_manager.h" #include "media/base/android/media_source_player.h" #include "media/base/android/media_url_interceptor.h" +#include "media/base/android/sdk_media_codec_bridge.h" #include "media/base/android/video_decoder_job.h" #include "media/base/bind_to_current_loop.h" #include "media/base/decoder_buffer.h" @@ -24,15 +25,6 @@ namespace media { -// Helper macro to skip the test if MediaCodecBridge isn't available. -#define SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE() \ - do { \ - if (!MediaCodecBridge::IsAvailable()) { \ - VLOG(0) << "Could not run test - not supported on device."; \ - return; \ - } \ - } while (0) - const base::TimeDelta kDefaultDuration = base::TimeDelta::FromMilliseconds(10000);
diff --git a/media/base/android/ndk_media_codec_bridge.cc b/media/base/android/ndk_media_codec_bridge.cc new file mode 100644 index 0000000..ae23aff --- /dev/null +++ b/media/base/android/ndk_media_codec_bridge.cc
@@ -0,0 +1,228 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/base/android/ndk_media_codec_bridge.h" + +#include <media/NdkMediaError.h> +#include <media/NdkMediaFormat.h> + +#include "base/strings/string_util.h" +#include "media/base/decrypt_config.h" + +namespace { +const char kMediaFormatKeyCropLeft[] = "crop-left"; +const char kMediaFormatKeyCropRight[] = "crop-right"; +const char kMediaFormatKeyCropBottom[] = "crop-bottom"; +const char kMediaFormatKeyCropTop[] = "crop-top"; +} + +namespace media { + +// Translate media_status_t to MediaCodecStatus. +static MediaCodecStatus TranslateMediaCodecStatus(media_status_t status) { + switch (status) { + case AMEDIA_OK: + return MEDIA_CODEC_OK; + case AMEDIA_DRM_NEED_KEY: + return MEDIA_CODEC_NO_KEY; + default: + return MEDIA_CODEC_ERROR; + } +} + +NdkMediaCodecBridge::~NdkMediaCodecBridge() {} + +NdkMediaCodecBridge::NdkMediaCodecBridge(const std::string& mime, + bool is_secure, + MediaCodecDirection direction) { + if (base::StartsWith(mime, "video", base::CompareCase::SENSITIVE) && + is_secure && direction == MEDIA_CODEC_DECODER) { + // TODO(qinmin): get the secure decoder name from java. + NOTIMPLEMENTED(); + return; + } + + if (direction == MEDIA_CODEC_DECODER) + media_codec_.reset(AMediaCodec_createDecoderByType(mime.c_str())); + else + media_codec_.reset(AMediaCodec_createEncoderByType(mime.c_str())); +} + +MediaCodecStatus NdkMediaCodecBridge::Reset() { + media_status_t status = AMediaCodec_flush(media_codec_.get()); + return TranslateMediaCodecStatus(status); +} + +bool NdkMediaCodecBridge::Start() { + return AMEDIA_OK == AMediaCodec_start(media_codec_.get()); +} + +void NdkMediaCodecBridge::Stop() { + AMediaCodec_stop(media_codec_.get()); +} + +void NdkMediaCodecBridge::GetOutputFormat(int* width, int* height) { + AMediaFormat* format = AMediaCodec_getOutputFormat(media_codec_.get()); + int left, right, bottom, top; + bool has_left = AMediaFormat_getInt32(format, kMediaFormatKeyCropLeft, &left); + bool has_right = + AMediaFormat_getInt32(format, kMediaFormatKeyCropRight, &right); + bool has_bottom = + AMediaFormat_getInt32(format, kMediaFormatKeyCropBottom, &bottom); + bool has_top = AMediaFormat_getInt32(format, kMediaFormatKeyCropTop, &top); + if (has_left && has_right && has_bottom && has_top) { + // Use crop size as it is more accurate. right and bottom are inclusive. + *width = right - left + 1; + *height = top - bottom + 1; + } else { + AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, width); + AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, height); + } +} + +int NdkMediaCodecBridge::GetOutputSamplingRate() { + AMediaFormat* format = AMediaCodec_getOutputFormat(media_codec_.get()); + int sample_rate = 0; + AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &sample_rate); + DCHECK(sample_rate != 0); + return sample_rate; +} + +MediaCodecStatus NdkMediaCodecBridge::QueueInputBuffer( + int index, + const uint8* data, + size_t data_size, + const base::TimeDelta& presentation_time) { + if (data_size > base::checked_cast<size_t>(kint32max)) + return MEDIA_CODEC_ERROR; + if (data && !FillInputBuffer(index, data, data_size)) + return MEDIA_CODEC_ERROR; + + media_status_t status = + AMediaCodec_queueInputBuffer(media_codec_.get(), index, 0, data_size, + presentation_time.InMicroseconds(), 0); + return TranslateMediaCodecStatus(status); +} + +MediaCodecStatus NdkMediaCodecBridge::QueueSecureInputBuffer( + int index, + const uint8* data, + size_t data_size, + const std::vector<char>& key_id, + const std::vector<char>& iv, + const SubsampleEntry* subsamples, + int subsamples_size, + const base::TimeDelta& presentation_time) { + if (data_size > base::checked_cast<size_t>(kint32max)) + return MEDIA_CODEC_ERROR; + if (key_id.size() > 16 || iv.size()) + return MEDIA_CODEC_ERROR; + if (data && !FillInputBuffer(index, data, data_size)) + return MEDIA_CODEC_ERROR; + + int new_subsamples_size = subsamples_size == 0 ? 1 : subsamples_size; + std::vector<size_t> clear_data, encrypted_data; + if (subsamples_size == 0) { + DCHECK(!subsamples); + clear_data.push_back(0); + encrypted_data.push_back(data_size); + } else { + DCHECK_GT(subsamples_size, 0); + DCHECK(subsamples); + for (int i = 0; i < subsamples_size; ++i) { + DCHECK(subsamples[i].clear_bytes <= std::numeric_limits<uint16>::max()); + if (subsamples[i].cypher_bytes > + static_cast<uint32>(std::numeric_limits<int32>::max())) { + return MEDIA_CODEC_ERROR; + } + clear_data.push_back(subsamples[i].clear_bytes); + encrypted_data.push_back(subsamples[i].cypher_bytes); + } + } + + AMediaCodecCryptoInfo* crypto_info = AMediaCodecCryptoInfo_new( + new_subsamples_size, + reinterpret_cast<uint8*>(const_cast<char*>(key_id.data())), + reinterpret_cast<uint8*>(const_cast<char*>(iv.data())), + AMEDIACODECRYPTOINFO_MODE_AES_CTR, clear_data.data(), + encrypted_data.data()); + + media_status_t status = AMediaCodec_queueSecureInputBuffer( + media_codec_.get(), index, 0, crypto_info, + presentation_time.InMicroseconds(), 0); + return TranslateMediaCodecStatus(status); +} + +void NdkMediaCodecBridge::QueueEOS(int input_buffer_index) { + AMediaCodec_queueInputBuffer(media_codec_.get(), input_buffer_index, 0, 0, 0, + AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM); +} + +MediaCodecStatus NdkMediaCodecBridge::DequeueInputBuffer( + const base::TimeDelta& timeout, + int* index) { + *index = AMediaCodec_dequeueInputBuffer(media_codec_.get(), + timeout.InMicroseconds()); + if (*index >= 0) + return MEDIA_CODEC_OK; + else if (*index == AMEDIACODEC_INFO_TRY_AGAIN_LATER) + return MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER; + else + return MEDIA_CODEC_ERROR; +} + +MediaCodecStatus NdkMediaCodecBridge::DequeueOutputBuffer( + const base::TimeDelta& timeout, + int* index, + size_t* offset, + size_t* size, + base::TimeDelta* presentation_time, + bool* end_of_stream, + bool* key_frame) { + AMediaCodecBufferInfo buffer_info; + *index = AMediaCodec_dequeueOutputBuffer(media_codec_.get(), &buffer_info, + timeout.InMicroseconds()); + *offset = buffer_info.offset; + *size = buffer_info.size; + *presentation_time = + base::TimeDelta::FromMicroseconds(buffer_info.presentationTimeUs); + if (end_of_stream) + *end_of_stream = buffer_info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM; + if (key_frame) + *key_frame = false; // This is deprecated. + if (*index >= 0) + return MEDIA_CODEC_OK; + else if (*index == AMEDIACODEC_INFO_TRY_AGAIN_LATER) + return MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER; + else + return MEDIA_CODEC_ERROR; +} + +void NdkMediaCodecBridge::ReleaseOutputBuffer(int index, bool render) { + AMediaCodec_releaseOutputBuffer(media_codec_.get(), index, render); +} + +void NdkMediaCodecBridge::GetInputBuffer(int input_buffer_index, + uint8** data, + size_t* capacity) { + *data = AMediaCodec_getInputBuffer(media_codec_.get(), input_buffer_index, + capacity); +} + +bool NdkMediaCodecBridge::CopyFromOutputBuffer(int index, + size_t offset, + void* dst, + int dst_size) { + size_t capacity; + uint8_t* src_data = + AMediaCodec_getOutputBuffer(media_codec_.get(), index, &capacity); + + if (capacity < offset || capacity - offset < static_cast<size_t>(dst_size)) + return false; + + memcpy(dst, src_data + offset, dst_size); + return true; +} + +} // namespace media
diff --git a/media/base/android/ndk_media_codec_bridge.h b/media/base/android/ndk_media_codec_bridge.h new file mode 100644 index 0000000..75bada9 --- /dev/null +++ b/media/base/android/ndk_media_codec_bridge.h
@@ -0,0 +1,79 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_BASE_ANDROID_NDK_MEDIA_CODEC_BRIDGE_H_ +#define MEDIA_BASE_ANDROID_NDK_MEDIA_CODEC_BRIDGE_H_ + +#include <media/NdkMediaCodec.h> + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/time/time.h" +#include "media/base/android/media_codec_bridge.h" +#include "media/base/media_export.h" + +namespace media { + +class MEDIA_EXPORT NdkMediaCodecBridge : public MediaCodecBridge { + public: + ~NdkMediaCodecBridge() override; + + // MediaCodecBridge implementation. + MediaCodecStatus Reset() override; + bool Start() override; + void Stop() override; + void GetOutputFormat(int* width, int* height) override; + int GetOutputSamplingRate() override; + MediaCodecStatus QueueInputBuffer( + int index, + const uint8* data, + size_t data_size, + const base::TimeDelta& presentation_time) override; + using MediaCodecBridge::QueueSecureInputBuffer; + MediaCodecStatus QueueSecureInputBuffer( + int index, + const uint8* data, + size_t data_size, + const std::vector<char>& key_id, + const std::vector<char>& iv, + const SubsampleEntry* subsamples, + int subsamples_size, + const base::TimeDelta& presentation_time) override; + void QueueEOS(int input_buffer_index); + MediaCodecStatus DequeueInputBuffer(const base::TimeDelta& timeout, + int* index) override; + MediaCodecStatus DequeueOutputBuffer(const base::TimeDelta& timeout, + int* index, + size_t* offset, + size_t* size, + base::TimeDelta* presentation_time, + bool* end_of_stream, + bool* key_frame) override; + void ReleaseOutputBuffer(int index, bool render) override; + void GetInputBuffer(int input_buffer_index, + uint8** data, + size_t* capacity) override; + bool CopyFromOutputBuffer(int index, + size_t offset, + void* dst, + int dst_size) override; + + protected: + NdkMediaCodecBridge(const std::string& mime, + bool is_secure, + MediaCodecDirection direction); + + private: + struct AMediaCodecDeleter { + inline void operator()(AMediaCodec* ptr) const { AMediaCodec_delete(ptr); } + }; + + scoped_ptr<AMediaCodec, AMediaCodecDeleter> media_codec_; + + DISALLOW_COPY_AND_ASSIGN(NdkMediaCodecBridge); +}; + +} // namespace media + +#endif // MEDIA_BASE_ANDROID_NDK_MEDIA_CODEC_BRIDGE_H_
diff --git a/media/base/android/sdk_media_codec_bridge.cc b/media/base/android/sdk_media_codec_bridge.cc new file mode 100644 index 0000000..01cfa3f --- /dev/null +++ b/media/base/android/sdk_media_codec_bridge.cc
@@ -0,0 +1,638 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/base/android/sdk_media_codec_bridge.h" + +#include <algorithm> + +#include "base/android/build_info.h" +#include "base/android/jni_android.h" +#include "base/android/jni_array.h" +#include "base/android/jni_string.h" +#include "base/basictypes.h" +#include "base/logging.h" +#include "base/numerics/safe_conversions.h" +#include "base/strings/string_util.h" +#include "jni/MediaCodecBridge_jni.h" +#include "media/base/bit_reader.h" +#include "media/base/decrypt_config.h" + +using base::android::AttachCurrentThread; +using base::android::ConvertJavaStringToUTF8; +using base::android::ConvertUTF8ToJavaString; +using base::android::JavaIntArrayToIntVector; +using base::android::ScopedJavaLocalRef; + +#define RETURN_ON_ERROR(condition) \ + do { \ + if (!(condition)) { \ + LOG(ERROR) << "Unable to parse AAC header: " #condition; \ + return false; \ + } \ + } while (0) + +namespace media { + +enum { + kBufferFlagSyncFrame = 1, // BUFFER_FLAG_SYNC_FRAME + kBufferFlagEndOfStream = 4, // BUFFER_FLAG_END_OF_STREAM + kConfigureFlagEncode = 1, // CONFIGURE_FLAG_ENCODE +}; + +static ScopedJavaLocalRef<jintArray> +ToJavaIntArray(JNIEnv* env, scoped_ptr<jint[]> native_array, int size) { + ScopedJavaLocalRef<jintArray> j_array(env, env->NewIntArray(size)); + env->SetIntArrayRegion(j_array.obj(), 0, size, native_array.get()); + return j_array; +} + +static const std::string AudioCodecToAndroidMimeType(const AudioCodec& codec) { + switch (codec) { + case kCodecMP3: + return "audio/mpeg"; + case kCodecVorbis: + return "audio/vorbis"; + case kCodecOpus: + return "audio/opus"; + case kCodecAAC: + return "audio/mp4a-latm"; + default: + return std::string(); + } +} + +static const std::string VideoCodecToAndroidMimeType(const VideoCodec& codec) { + switch (codec) { + case kCodecH264: + return "video/avc"; + case kCodecHEVC: + return "video/hevc"; + case kCodecVP8: + return "video/x-vnd.on2.vp8"; + case kCodecVP9: + return "video/x-vnd.on2.vp9"; + default: + return std::string(); + } +} + +SdkMediaCodecBridge::SdkMediaCodecBridge(const std::string& mime, + bool is_secure, + MediaCodecDirection direction) { + JNIEnv* env = AttachCurrentThread(); + CHECK(env); + DCHECK(!mime.empty()); + ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime); + j_media_codec_.Reset( + Java_MediaCodecBridge_create(env, j_mime.obj(), is_secure, direction)); +} + +SdkMediaCodecBridge::~SdkMediaCodecBridge() { + JNIEnv* env = AttachCurrentThread(); + CHECK(env); + if (j_media_codec_.obj()) + Java_MediaCodecBridge_release(env, j_media_codec_.obj()); +} + +MediaCodecStatus SdkMediaCodecBridge::Reset() { + JNIEnv* env = AttachCurrentThread(); + return static_cast<MediaCodecStatus>( + Java_MediaCodecBridge_flush(env, j_media_codec_.obj())); +} + +bool SdkMediaCodecBridge::Start() { + JNIEnv* env = AttachCurrentThread(); + return Java_MediaCodecBridge_start(env, j_media_codec_.obj()); +} + +void SdkMediaCodecBridge::Stop() { + JNIEnv* env = AttachCurrentThread(); + Java_MediaCodecBridge_stop(env, j_media_codec_.obj()); +} + +void SdkMediaCodecBridge::GetOutputFormat(int* width, int* height) { + JNIEnv* env = AttachCurrentThread(); + + *width = Java_MediaCodecBridge_getOutputWidth(env, j_media_codec_.obj()); + *height = Java_MediaCodecBridge_getOutputHeight(env, j_media_codec_.obj()); +} + +int SdkMediaCodecBridge::GetOutputSamplingRate() { + JNIEnv* env = AttachCurrentThread(); + + return Java_MediaCodecBridge_getOutputSamplingRate(env, j_media_codec_.obj()); +} + +MediaCodecStatus SdkMediaCodecBridge::QueueInputBuffer( + int index, + const uint8* data, + size_t data_size, + const base::TimeDelta& presentation_time) { + DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size; + if (data_size > base::checked_cast<size_t>(kint32max)) + return MEDIA_CODEC_ERROR; + if (data && !FillInputBuffer(index, data, data_size)) + return MEDIA_CODEC_ERROR; + JNIEnv* env = AttachCurrentThread(); + return static_cast<MediaCodecStatus>(Java_MediaCodecBridge_queueInputBuffer( + env, j_media_codec_.obj(), index, 0, data_size, + presentation_time.InMicroseconds(), 0)); +} + +// TODO(timav): Combine this and above methods together keeping only the first +// interface after we switch to Spitzer pipeline. +MediaCodecStatus SdkMediaCodecBridge::QueueSecureInputBuffer( + int index, + const uint8* data, + size_t data_size, + const std::vector<char>& key_id, + const std::vector<char>& iv, + const SubsampleEntry* subsamples, + int subsamples_size, + const base::TimeDelta& presentation_time) { + DVLOG(3) << __PRETTY_FUNCTION__ << index << ": " << data_size; + if (data_size > base::checked_cast<size_t>(kint32max)) + return MEDIA_CODEC_ERROR; + if (data && !FillInputBuffer(index, data, data_size)) + return MEDIA_CODEC_ERROR; + + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jbyteArray> j_key_id = base::android::ToJavaByteArray( + env, reinterpret_cast<const uint8*>(key_id.data()), key_id.size()); + ScopedJavaLocalRef<jbyteArray> j_iv = base::android::ToJavaByteArray( + env, reinterpret_cast<const uint8*>(iv.data()), iv.size()); + + // MediaCodec.CryptoInfo documentations says passing NULL for |clear_array| + // to indicate that all data is encrypted. But it doesn't specify what + // |cypher_array| and |subsamples_size| should be in that case. Passing + // one subsample here just to be on the safe side. + int new_subsamples_size = subsamples_size == 0 ? 1 : subsamples_size; + + scoped_ptr<jint[]> native_clear_array(new jint[new_subsamples_size]); + scoped_ptr<jint[]> native_cypher_array(new jint[new_subsamples_size]); + + if (subsamples_size == 0) { + DCHECK(!subsamples); + native_clear_array[0] = 0; + native_cypher_array[0] = data_size; + } else { + DCHECK_GT(subsamples_size, 0); + DCHECK(subsamples); + for (int i = 0; i < subsamples_size; ++i) { + DCHECK(subsamples[i].clear_bytes <= std::numeric_limits<uint16>::max()); + if (subsamples[i].cypher_bytes > + static_cast<uint32>(std::numeric_limits<jint>::max())) { + return MEDIA_CODEC_ERROR; + } + + native_clear_array[i] = subsamples[i].clear_bytes; + native_cypher_array[i] = subsamples[i].cypher_bytes; + } + } + + ScopedJavaLocalRef<jintArray> clear_array = + ToJavaIntArray(env, native_clear_array.Pass(), new_subsamples_size); + ScopedJavaLocalRef<jintArray> cypher_array = + ToJavaIntArray(env, native_cypher_array.Pass(), new_subsamples_size); + + return static_cast<MediaCodecStatus>( + Java_MediaCodecBridge_queueSecureInputBuffer( + env, j_media_codec_.obj(), index, 0, j_iv.obj(), j_key_id.obj(), + clear_array.obj(), cypher_array.obj(), new_subsamples_size, + presentation_time.InMicroseconds())); +} + +void SdkMediaCodecBridge::QueueEOS(int input_buffer_index) { + DVLOG(3) << __PRETTY_FUNCTION__ << ": " << input_buffer_index; + JNIEnv* env = AttachCurrentThread(); + Java_MediaCodecBridge_queueInputBuffer(env, j_media_codec_.obj(), + input_buffer_index, 0, 0, 0, + kBufferFlagEndOfStream); +} + +MediaCodecStatus SdkMediaCodecBridge::DequeueInputBuffer( + const base::TimeDelta& timeout, + int* index) { + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jobject> result = Java_MediaCodecBridge_dequeueInputBuffer( + env, j_media_codec_.obj(), timeout.InMicroseconds()); + *index = Java_DequeueInputResult_index(env, result.obj()); + MediaCodecStatus status = static_cast<MediaCodecStatus>( + Java_DequeueInputResult_status(env, result.obj())); + DVLOG(3) << __PRETTY_FUNCTION__ << ": status: " << status + << ", index: " << *index; + return status; +} + +MediaCodecStatus SdkMediaCodecBridge::DequeueOutputBuffer( + const base::TimeDelta& timeout, + int* index, + size_t* offset, + size_t* size, + base::TimeDelta* presentation_time, + bool* end_of_stream, + bool* key_frame) { + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jobject> result = + Java_MediaCodecBridge_dequeueOutputBuffer(env, j_media_codec_.obj(), + timeout.InMicroseconds()); + *index = Java_DequeueOutputResult_index(env, result.obj()); + *offset = base::checked_cast<size_t>( + Java_DequeueOutputResult_offset(env, result.obj())); + *size = base::checked_cast<size_t>( + Java_DequeueOutputResult_numBytes(env, result.obj())); + if (presentation_time) { + *presentation_time = base::TimeDelta::FromMicroseconds( + Java_DequeueOutputResult_presentationTimeMicroseconds(env, + result.obj())); + } + int flags = Java_DequeueOutputResult_flags(env, result.obj()); + if (end_of_stream) + *end_of_stream = flags & kBufferFlagEndOfStream; + if (key_frame) + *key_frame = flags & kBufferFlagSyncFrame; + MediaCodecStatus status = static_cast<MediaCodecStatus>( + Java_DequeueOutputResult_status(env, result.obj())); + DVLOG(3) << __PRETTY_FUNCTION__ << ": status: " << status + << ", index: " << *index << ", offset: " << *offset + << ", size: " << *size << ", flags: " << flags; + return status; +} + +void SdkMediaCodecBridge::ReleaseOutputBuffer(int index, bool render) { + DVLOG(3) << __PRETTY_FUNCTION__ << ": " << index; + JNIEnv* env = AttachCurrentThread(); + CHECK(env); + + Java_MediaCodecBridge_releaseOutputBuffer(env, j_media_codec_.obj(), index, + render); +} + +int SdkMediaCodecBridge::GetOutputBuffersCount() { + JNIEnv* env = AttachCurrentThread(); + return Java_MediaCodecBridge_getOutputBuffersCount(env, j_media_codec_.obj()); +} + +size_t SdkMediaCodecBridge::GetOutputBuffersCapacity() { + JNIEnv* env = AttachCurrentThread(); + return Java_MediaCodecBridge_getOutputBuffersCapacity(env, + j_media_codec_.obj()); +} + +void SdkMediaCodecBridge::GetInputBuffer(int input_buffer_index, + uint8** data, + size_t* capacity) { + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jobject> j_buffer(Java_MediaCodecBridge_getInputBuffer( + env, j_media_codec_.obj(), input_buffer_index)); + *data = static_cast<uint8*>(env->GetDirectBufferAddress(j_buffer.obj())); + *capacity = + base::checked_cast<size_t>(env->GetDirectBufferCapacity(j_buffer.obj())); +} + +bool SdkMediaCodecBridge::CopyFromOutputBuffer(int index, + size_t offset, + void* dst, + int dst_size) { + void* src_data = nullptr; + size_t src_capacity = GetOutputBufferAddress(index, offset, &src_data); + if (src_capacity < offset || + src_capacity - offset < static_cast<size_t>(dst_size)) { + return false; + } + memcpy(dst, static_cast<uint8*>(src_data) + offset, dst_size); + return true; +} + +int SdkMediaCodecBridge::GetOutputBufferAddress(int index, + size_t offset, + void** addr) { + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jobject> j_buffer( + Java_MediaCodecBridge_getOutputBuffer(env, j_media_codec_.obj(), index)); + *addr = + reinterpret_cast<uint8*>(env->GetDirectBufferAddress(j_buffer.obj())) + + offset; + return env->GetDirectBufferCapacity(j_buffer.obj()) - offset; +} + +// static +bool SdkMediaCodecBridge::RegisterSdkMediaCodecBridge(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +// static +AudioCodecBridge* AudioCodecBridge::Create(const AudioCodec& codec) { + if (!MediaCodecUtil::IsMediaCodecAvailable()) + return nullptr; + + const std::string mime = AudioCodecToAndroidMimeType(codec); + return mime.empty() ? nullptr : new AudioCodecBridge(mime); +} + +// static +bool AudioCodecBridge::IsKnownUnaccelerated(const AudioCodec& codec) { + return MediaCodecUtil::IsKnownUnaccelerated( + AudioCodecToAndroidMimeType(codec), MEDIA_CODEC_DECODER); +} + +AudioCodecBridge::AudioCodecBridge(const std::string& mime) + // Audio codec doesn't care about security level and there is no need for + // audio encoding yet. + : SdkMediaCodecBridge(mime, false, MEDIA_CODEC_DECODER) {} + +bool AudioCodecBridge::ConfigureAndStart(const AudioCodec& codec, + int sample_rate, + int channel_count, + const uint8* extra_data, + size_t extra_data_size, + int64 codec_delay_ns, + int64 seek_preroll_ns, + bool play_audio, + jobject media_crypto) { + JNIEnv* env = AttachCurrentThread(); + + if (!media_codec()) + return false; + + std::string codec_string = AudioCodecToAndroidMimeType(codec); + if (codec_string.empty()) + return false; + + ScopedJavaLocalRef<jstring> j_mime = + ConvertUTF8ToJavaString(env, codec_string); + ScopedJavaLocalRef<jobject> j_format(Java_MediaCodecBridge_createAudioFormat( + env, j_mime.obj(), sample_rate, channel_count)); + DCHECK(!j_format.is_null()); + + if (!ConfigureMediaFormat(j_format.obj(), codec, extra_data, extra_data_size, + codec_delay_ns, seek_preroll_ns)) { + return false; + } + + if (!Java_MediaCodecBridge_configureAudio(env, media_codec(), j_format.obj(), + media_crypto, 0, play_audio)) { + return false; + } + + return Start(); +} + +bool AudioCodecBridge::ConfigureMediaFormat(jobject j_format, + const AudioCodec& codec, + const uint8* extra_data, + size_t extra_data_size, + int64 codec_delay_ns, + int64 seek_preroll_ns) { + if (extra_data_size == 0 && codec != kCodecOpus) + return true; + + JNIEnv* env = AttachCurrentThread(); + switch (codec) { + case kCodecVorbis: { + if (extra_data[0] != 2) { + LOG(ERROR) << "Invalid number of vorbis headers before the codec " + << "header: " << extra_data[0]; + return false; + } + + size_t header_length[2]; + // |total_length| keeps track of the total number of bytes before the last + // header. + size_t total_length = 1; + const uint8* current_pos = extra_data; + // Calculate the length of the first 2 headers. + for (int i = 0; i < 2; ++i) { + header_length[i] = 0; + while (total_length < extra_data_size) { + size_t size = *(++current_pos); + total_length += 1 + size; + if (total_length > 0x80000000) { + LOG(ERROR) << "Vorbis header size too large"; + return false; + } + header_length[i] += size; + if (size < 0xFF) + break; + } + if (total_length >= extra_data_size) { + LOG(ERROR) << "Invalid vorbis header size in the extra data"; + return false; + } + } + current_pos++; + // The first header is identification header. + ScopedJavaLocalRef<jbyteArray> first_header = + base::android::ToJavaByteArray(env, current_pos, header_length[0]); + Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, + first_header.obj()); + // The last header is codec header. + ScopedJavaLocalRef<jbyteArray> last_header = + base::android::ToJavaByteArray(env, extra_data + total_length, + extra_data_size - total_length); + Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 1, + last_header.obj()); + break; + } + case kCodecAAC: { + media::BitReader reader(extra_data, extra_data_size); + + // The following code is copied from aac.cc + // TODO(qinmin): refactor the code in aac.cc to make it more reusable. + uint8 profile = 0; + uint8 frequency_index = 0; + uint8 channel_config = 0; + RETURN_ON_ERROR(reader.ReadBits(5, &profile)); + RETURN_ON_ERROR(reader.ReadBits(4, &frequency_index)); + + if (0xf == frequency_index) + RETURN_ON_ERROR(reader.SkipBits(24)); + RETURN_ON_ERROR(reader.ReadBits(4, &channel_config)); + + if (profile == 5 || profile == 29) { + // Read extension config. + RETURN_ON_ERROR(reader.ReadBits(4, &frequency_index)); + if (frequency_index == 0xf) + RETURN_ON_ERROR(reader.SkipBits(24)); + RETURN_ON_ERROR(reader.ReadBits(5, &profile)); + } + + if (profile < 1 || profile > 4 || frequency_index == 0xf || + channel_config > 7) { + LOG(ERROR) << "Invalid AAC header"; + return false; + } + const size_t kCsdLength = 2; + uint8 csd[kCsdLength]; + csd[0] = profile << 3 | frequency_index >> 1; + csd[1] = (frequency_index & 0x01) << 7 | channel_config << 3; + ScopedJavaLocalRef<jbyteArray> byte_array = + base::android::ToJavaByteArray(env, csd, kCsdLength); + Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, + byte_array.obj()); + + // TODO(qinmin): pass an extra variable to this function to determine + // whether we need to call this. + Java_MediaCodecBridge_setFrameHasADTSHeader(env, j_format); + break; + } + case kCodecOpus: { + if (!extra_data || extra_data_size == 0 || codec_delay_ns < 0 || + seek_preroll_ns < 0) { + LOG(ERROR) << "Invalid Opus Header"; + return false; + } + + // csd0 - Opus Header + ScopedJavaLocalRef<jbyteArray> csd0 = + base::android::ToJavaByteArray(env, extra_data, extra_data_size); + Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 0, csd0.obj()); + + // csd1 - Codec Delay + ScopedJavaLocalRef<jbyteArray> csd1 = base::android::ToJavaByteArray( + env, reinterpret_cast<const uint8*>(&codec_delay_ns), + sizeof(int64_t)); + Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 1, csd1.obj()); + + // csd2 - Seek Preroll + ScopedJavaLocalRef<jbyteArray> csd2 = base::android::ToJavaByteArray( + env, reinterpret_cast<const uint8*>(&seek_preroll_ns), + sizeof(int64_t)); + Java_MediaCodecBridge_setCodecSpecificData(env, j_format, 2, csd2.obj()); + break; + } + default: + LOG(ERROR) << "Invalid header encountered for codec: " + << AudioCodecToAndroidMimeType(codec); + return false; + } + return true; +} + +int64 AudioCodecBridge::PlayOutputBuffer(int index, + size_t size, + size_t offset, + bool postpone) { + DCHECK_LE(0, index); + int numBytes = base::checked_cast<int>(size); + + void* buffer = nullptr; + int capacity = GetOutputBufferAddress(index, offset, &buffer); + numBytes = std::min(capacity, numBytes); + CHECK_GE(numBytes, 0); + + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jbyteArray> byte_array = base::android::ToJavaByteArray( + env, static_cast<uint8*>(buffer), numBytes); + return Java_MediaCodecBridge_playOutputBuffer(env, media_codec(), + byte_array.obj(), postpone); +} + +void AudioCodecBridge::SetVolume(double volume) { + JNIEnv* env = AttachCurrentThread(); + Java_MediaCodecBridge_setVolume(env, media_codec(), volume); +} + +// static +bool VideoCodecBridge::IsKnownUnaccelerated(const VideoCodec& codec, + MediaCodecDirection direction) { + return MediaCodecUtil::IsKnownUnaccelerated( + VideoCodecToAndroidMimeType(codec), direction); +} + +// static +VideoCodecBridge* VideoCodecBridge::CreateDecoder(const VideoCodec& codec, + bool is_secure, + const gfx::Size& size, + jobject surface, + jobject media_crypto) { + if (!MediaCodecUtil::IsMediaCodecAvailable()) + return nullptr; + + const std::string mime = VideoCodecToAndroidMimeType(codec); + if (mime.empty()) + return nullptr; + + scoped_ptr<VideoCodecBridge> bridge( + new VideoCodecBridge(mime, is_secure, MEDIA_CODEC_DECODER)); + if (!bridge->media_codec()) + return nullptr; + + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime); + ScopedJavaLocalRef<jobject> j_format( + Java_MediaCodecBridge_createVideoDecoderFormat( + env, j_mime.obj(), size.width(), size.height())); + DCHECK(!j_format.is_null()); + if (!Java_MediaCodecBridge_configureVideo(env, bridge->media_codec(), + j_format.obj(), surface, + media_crypto, 0)) { + return nullptr; + } + + return bridge->Start() ? bridge.release() : nullptr; +} + +// static +VideoCodecBridge* VideoCodecBridge::CreateEncoder(const VideoCodec& codec, + const gfx::Size& size, + int bit_rate, + int frame_rate, + int i_frame_interval, + int color_format) { + if (!MediaCodecUtil::IsMediaCodecAvailable()) + return nullptr; + + const std::string mime = VideoCodecToAndroidMimeType(codec); + if (mime.empty()) + return nullptr; + + scoped_ptr<VideoCodecBridge> bridge( + new VideoCodecBridge(mime, false, MEDIA_CODEC_ENCODER)); + if (!bridge->media_codec()) + return nullptr; + + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jstring> j_mime = ConvertUTF8ToJavaString(env, mime); + ScopedJavaLocalRef<jobject> j_format( + Java_MediaCodecBridge_createVideoEncoderFormat( + env, j_mime.obj(), size.width(), size.height(), bit_rate, frame_rate, + i_frame_interval, color_format)); + DCHECK(!j_format.is_null()); + if (!Java_MediaCodecBridge_configureVideo(env, bridge->media_codec(), + j_format.obj(), nullptr, nullptr, + kConfigureFlagEncode)) { + return nullptr; + } + + return bridge->Start() ? bridge.release() : nullptr; +} + +VideoCodecBridge::VideoCodecBridge(const std::string& mime, + bool is_secure, + MediaCodecDirection direction) + : SdkMediaCodecBridge(mime, is_secure, direction), + adaptive_playback_supported_for_testing_(-1) {} + +void VideoCodecBridge::SetVideoBitrate(int bps) { + JNIEnv* env = AttachCurrentThread(); + Java_MediaCodecBridge_setVideoBitrate(env, media_codec(), bps); +} + +void VideoCodecBridge::RequestKeyFrameSoon() { + JNIEnv* env = AttachCurrentThread(); + Java_MediaCodecBridge_requestKeyFrameSoon(env, media_codec()); +} + +bool VideoCodecBridge::IsAdaptivePlaybackSupported(int width, int height) { + if (adaptive_playback_supported_for_testing_ == 0) + return false; + else if (adaptive_playback_supported_for_testing_ > 0) + return true; + JNIEnv* env = AttachCurrentThread(); + return Java_MediaCodecBridge_isAdaptivePlaybackSupported(env, media_codec(), + width, height); +} + +} // namespace media
diff --git a/media/base/android/sdk_media_codec_bridge.h b/media/base/android/sdk_media_codec_bridge.h new file mode 100644 index 0000000..3518ad71 --- /dev/null +++ b/media/base/android/sdk_media_codec_bridge.h
@@ -0,0 +1,196 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_BASE_ANDROID_SDK_MEDIA_CODEC_BRIDGE_H_ +#define MEDIA_BASE_ANDROID_SDK_MEDIA_CODEC_BRIDGE_H_ + +#include <jni.h> +#include <set> +#include <string> + +#include "base/android/scoped_java_ref.h" +#include "base/macros.h" +#include "base/time/time.h" +#include "media/base/android/media_codec_bridge.h" +#include "media/base/audio_decoder_config.h" +#include "media/base/media_export.h" +#include "media/base/video_decoder_config.h" +#include "ui/gfx/geometry/size.h" + +namespace media { + +// This class implements MediaCodecBridge using android MediaCodec SDK APIs. +class MEDIA_EXPORT SdkMediaCodecBridge : public MediaCodecBridge { + public: + ~SdkMediaCodecBridge() override; + + // MediaCodecBridge implementations. + MediaCodecStatus Reset() override; + bool Start() override; + void Stop() override; + void GetOutputFormat(int* width, int* height) override; + int GetOutputSamplingRate() override; + MediaCodecStatus QueueInputBuffer( + int index, + const uint8* data, + size_t data_size, + const base::TimeDelta& presentation_time) override; + using MediaCodecBridge::QueueSecureInputBuffer; + MediaCodecStatus QueueSecureInputBuffer( + int index, + const uint8* data, + size_t data_size, + const std::vector<char>& key_id, + const std::vector<char>& iv, + const SubsampleEntry* subsamples, + int subsamples_size, + const base::TimeDelta& presentation_time) override; + void QueueEOS(int input_buffer_index) override; + MediaCodecStatus DequeueInputBuffer(const base::TimeDelta& timeout, + int* index) override; + MediaCodecStatus DequeueOutputBuffer(const base::TimeDelta& timeout, + int* index, + size_t* offset, + size_t* size, + base::TimeDelta* presentation_time, + bool* end_of_stream, + bool* key_frame) override; + void ReleaseOutputBuffer(int index, bool render) override; + int GetOutputBuffersCount() override; + size_t GetOutputBuffersCapacity() override; + void GetInputBuffer(int input_buffer_index, + uint8** data, + size_t* capacity) override; + bool CopyFromOutputBuffer(int index, + size_t offset, + void* dst, + int dst_size) override; + + static bool RegisterSdkMediaCodecBridge(JNIEnv* env); + + protected: + SdkMediaCodecBridge(const std::string& mime, + bool is_secure, + MediaCodecDirection direction); + + // Called to get the buffer address given the output buffer index and offset. + // This function returns the size of the output and |addr| is the pointer to + // the address to read. + int GetOutputBufferAddress(int index, size_t offset, void** addr); + + jobject media_codec() { return j_media_codec_.obj(); } + MediaCodecDirection direction_; + + private: + // Java MediaCodec instance. + base::android::ScopedJavaGlobalRef<jobject> j_media_codec_; + + DISALLOW_COPY_AND_ASSIGN(SdkMediaCodecBridge); +}; + +// Class for handling audio decoding using android MediaCodec APIs. +// TODO(qinmin): implement the logic to switch between NDK and SDK +// MediaCodecBridge. +class MEDIA_EXPORT AudioCodecBridge : public SdkMediaCodecBridge { + public: + // Returns an AudioCodecBridge instance if |codec| is supported, or a NULL + // pointer otherwise. + static AudioCodecBridge* Create(const AudioCodec& codec); + + // See MediaCodecUtil::IsKnownUnaccelerated(). + static bool IsKnownUnaccelerated(const AudioCodec& codec); + + // Start the audio codec bridge. + bool ConfigureAndStart(const AudioCodec& codec, + int sample_rate, + int channel_count, + const uint8* extra_data, + size_t extra_data_size, + int64 codec_delay_ns, + int64 seek_preroll_ns, + bool play_audio, + jobject media_crypto) WARN_UNUSED_RESULT; + + // Plays the output buffer right away or save for later playback if |postpone| + // is set to true. This call must be called after DequeueOutputBuffer() and + // before ReleaseOutputBuffer. The data is extracted from the output buffers + // using |index|, |size| and |offset|. Returns the playback head position + // expressed in frames. + // When |postpone| is set to true, the next PlayOutputBuffer() should have + // postpone == false, and it will play two buffers: the postponed one and + // the one identified by |index|. + int64 PlayOutputBuffer(int index, + size_t size, + size_t offset, + bool postpone = false); + + // Set the volume of the audio output. + void SetVolume(double volume); + + private: + explicit AudioCodecBridge(const std::string& mime); + + // Configure the java MediaFormat object with the extra codec data passed in. + bool ConfigureMediaFormat(jobject j_format, + const AudioCodec& codec, + const uint8* extra_data, + size_t extra_data_size, + int64 codec_delay_ns, + int64 seek_preroll_ns); +}; + +// Class for handling video encoding/decoding using android MediaCodec APIs. +// TODO(qinmin): implement the logic to switch between NDK and SDK +// MediaCodecBridge. +class MEDIA_EXPORT VideoCodecBridge : public SdkMediaCodecBridge { + public: + // See MediaCodecUtil::IsKnownUnaccelerated(). + static bool IsKnownUnaccelerated(const VideoCodec& codec, + MediaCodecDirection direction); + + // Create, start, and return a VideoCodecBridge decoder or NULL on failure. + static VideoCodecBridge* CreateDecoder( + const VideoCodec& codec, // e.g. media::kCodecVP8 + bool is_secure, + const gfx::Size& size, // Output frame size. + jobject surface, // Output surface, optional. + jobject media_crypto); // MediaCrypto object, optional. + + // Create, start, and return a VideoCodecBridge encoder or NULL on failure. + static VideoCodecBridge* CreateEncoder( + const VideoCodec& codec, // e.g. media::kCodecVP8 + const gfx::Size& size, // input frame size + int bit_rate, // bits/second + int frame_rate, // frames/second + int i_frame_interval, // count + int color_format); // MediaCodecInfo.CodecCapabilities. + + void SetVideoBitrate(int bps); + void RequestKeyFrameSoon(); + + // Returns whether adaptive playback is supported for this object given + // the new size. + bool IsAdaptivePlaybackSupported(int width, int height); + + // Test-only method to set the return value of IsAdaptivePlaybackSupported(). + // Without this function, the return value of that function will be device + // dependent. If |adaptive_playback_supported| is equal to 0, the return value + // will be false. If |adaptive_playback_supported| is larger than 0, the + // return value will be true. + void set_adaptive_playback_supported_for_testing( + int adaptive_playback_supported) { + adaptive_playback_supported_for_testing_ = adaptive_playback_supported; + } + + private: + VideoCodecBridge(const std::string& mime, + bool is_secure, + MediaCodecDirection direction); + + int adaptive_playback_supported_for_testing_; +}; + +} // namespace media + +#endif // MEDIA_BASE_ANDROID_SDK_MEDIA_CODEC_BRIDGE_H_
diff --git a/media/base/android/sdk_media_codec_bridge_unittest.cc b/media/base/android/sdk_media_codec_bridge_unittest.cc new file mode 100644 index 0000000..2f6274f --- /dev/null +++ b/media/base/android/sdk_media_codec_bridge_unittest.cc
@@ -0,0 +1,300 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <string> + +#include "base/basictypes.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "media/base/android/media_codec_util.h" +#include "media/base/android/sdk_media_codec_bridge.h" +#include "media/base/decoder_buffer.h" +#include "media/base/test_data_util.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace { + +// The first frame of +// http://www.html5rocks.com/en/tutorials/audio/quick/test.mp3 +unsigned char test_mp3[] = { + 0xff, 0xfb, 0xd2, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x05, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0d, 0x20, 0x00, 0x00, 0x00, 0x2a, 0x7e, 0x40, + 0xc0, 0x19, 0x4a, 0x80, 0x0d, 0x60, 0x48, 0x1b, 0x40, 0xf7, 0xbd, 0xb9, + 0xd9, 0x40, 0x6f, 0x82, 0x01, 0x8b, 0x17, 0xa0, 0x80, 0xc5, 0x01, 0xad, + 0x9a, 0xd3, 0x00, 0x12, 0xc0, 0x72, 0x93, 0x67, 0xd0, 0x03, 0x6f, 0xa4, + 0xc0, 0xc3, 0x23, 0xee, 0x9b, 0xc0, 0xcc, 0x02, 0xa0, 0xa1, 0x30, 0x0c, + 0x52, 0x2d, 0xfd, 0x6e, 0x08, 0x83, 0x60, 0x40, 0x46, 0x06, 0x4b, 0x20, + 0x82, 0x82, 0x7f, 0xd4, 0x81, 0xe7, 0x00, 0x64, 0x20, 0x18, 0xec, 0xc2, + 0x06, 0x57, 0x0f, 0x81, 0x93, 0x0b, 0x00, 0x66, 0xe3, 0xb7, 0xe8, 0x32, + 0x6e, 0xf0, 0x32, 0xb0, 0x58, 0x0c, 0x7c, 0x3a, 0x03, 0x22, 0x14, 0x80, + 0xc9, 0x01, 0x80, 0x30, 0x20, 0x14, 0x0c, 0x96, 0x73, 0xfe, 0x9f, 0x6c, + 0x0c, 0xd2, 0x25, 0x0f, 0xdc, 0x0c, 0x32, 0x43, 0x03, 0x27, 0x87, 0xc0, + 0xc2, 0xc0, 0x20, 0xfc, 0x42, 0xc5, 0xff, 0xff, 0xd4, 0x80, 0x01, 0x01, + 0x80, 0xc3, 0x81, 0x01, 0x95, 0x03, 0x28, 0x82, 0xc0, 0xc3, 0x01, 0xa1, + 0x06, 0x81, 0x87, 0xc2, 0x40, 0x64, 0xc1, 0xf0, 0x12, 0x02, 0xff, 0xf6, + 0x5b, 0x9f, 0x44, 0xdc, 0xdd, 0x0b, 0x38, 0x59, 0xe0, 0x31, 0x71, 0x60, + 0x0c, 0xb4, 0x22, 0x03, 0x3b, 0x96, 0x40, 0xc8, 0x63, 0x90, 0x0a, 0x23, + 0x81, 0x9e, 0x4c, 0x20, 0x65, 0xb3, 0x18, 0x19, 0x6c, 0x42, 0x06, 0x36, + 0x1d, 0x01, 0x90, 0x87, 0xdf, 0xff, 0xd0, 0x65, 0xa6, 0xea, 0x66, 0xfd, + 0x40, 0x0c, 0x48, 0x03, 0x1a, 0x09, 0x01, 0x21, 0x98, 0x19, 0x2c, 0x36, + 0x06, 0x43, 0x21, 0x81, 0x92, 0xca, 0x60, 0x64, 0x70, 0xb8, 0x19, 0x20, + 0x6c, 0x02, 0x83, 0x80, 0xcb, 0x60, 0x65, 0x32, 0x28, 0x18, 0x64, 0x24, + 0x06, 0x3a, 0x0c, 0x00, 0xe1, 0x00, 0x18, 0xd0, 0x35, 0xff, 0xff, 0xff, + 0xe8, 0x32, 0xef, 0xb2, 0x90, 0x65, 0xbb, 0xdd, 0x94, 0x82, 0x0b, 0x4c, + 0xfa, 0x25, 0xf3, 0x74, 0x13, 0x0f, 0xf8, 0x19, 0x28, 0x84, 0x06, 0x36, + 0x11, 0x01, 0x20, 0x80, 0x18, 0xb4, 0x52, 0x0e, 0x15, 0x00, 0x30, 0x50, + 0x0c, 0x84, 0x32, 0x03, 0x11, 0x04, 0x03, 0x48, 0x04, 0x00, 0x00, 0x31, + 0x21, 0x00, 0x0c, 0x84, 0x18, 0x03, 0x07, 0x85, 0x40, 0xc6, 0xa5, 0x70, + 0x32, 0xb8, 0x7c, 0x0c, 0x54, 0x04, 0x00, 0xd0, 0x08, 0x59, 0x58, 0x18, + 0x20, 0x14, 0x06, 0x30, 0x30, 0x01, 0x9b, 0x86, 0x00, 0x6b, 0x54, 0xa8, + 0x19, 0x8c, 0x2a, 0x06, 0x16, 0x09, 0x01, 0xa0, 0xd0, 0xa0, 0x69, 0x74, + 0xb8, 0x19, 0xc4, 0x4a, 0xa3, 0xda, 0x9d, 0x1e, 0x4f, 0x05, 0xc0, 0x5b, + 0x0b, 0x03, 0xc2, 0x76, 0xa3, 0x4f, 0xb9, 0x16, 0xc2, 0x70, 0x41, 0x07, + 0xa0, 0x84, 0x16, 0x38, 0x4a, 0xc8, 0xaf, 0xee, 0x7f, 0x93, 0xb5, 0x5c, + 0x39, 0x1e, 0x29, 0xd9, 0x8c, 0x80, 0xb5, 0x80, 0xe6, 0x85, 0xb2, 0x99, + 0x68, 0x85, 0x46, 0x91, 0x60, 0xdb, 0x06, 0xfa, 0x38, 0x7a, 0xc7, 0xac, + 0x85, 0xa8, 0xd3, 0xe6, 0x99, 0x3b, 0x66, 0x43, 0x23, 0x1f, 0x84, 0xe1, + 0x65, 0x5e, 0xbc, 0x84, 0x18, 0x62, 0xe6, 0x42, 0x0b, 0x82, 0xe4, 0xd3, + 0x42, 0xd2, 0x05, 0x81, 0x4e, 0xe4, 0x9f, 0x8c, 0xc8, 0x7f, 0xa3, 0xe0, + 0x8d, 0xf1, 0x0f, 0x38, 0xe5, 0x3f, 0xc4, 0x2c, 0x24, 0x65, 0x8d, 0xb9, + 0x58, 0xac, 0x39, 0x0e, 0x37, 0x99, 0x2e, 0x85, 0xe0, 0xb7, 0x98, 0x41, + 0x20, 0x38, 0x1b, 0x95, 0x07, 0xfa, 0xa8, 0x9c, 0x21, 0x0f, 0x13, 0x8c, + 0xa5, 0xc1, 0x76, 0xae, 0x0b, 0xc1, 0x30, 0x27, 0x08, 0xc1, 0xf6, 0x4d, + 0xce, 0xb4, 0x41, 0x38, 0x1e, 0x82, 0x10, 0x74, 0x45, 0x91, 0x90, 0xff, + 0x41, 0x8b, 0x62, 0x1a, 0x71, 0xb6, 0x45, 0x63, 0x8c, 0xce, 0xb8, 0x54, + 0x1b, 0xe8, 0x5d, 0x9e, 0x35, 0x9d, 0x6c, 0xac, 0xe8, 0x83, 0xa1, 0xe9, + 0x3f, 0x13, 0x74, 0x11, 0x04, 0x10, 0xf1, 0x37, 0x38, 0xc6, 0x00, 0x60, + 0x27, 0x48, 0x38, 0x85, 0x92, 0x76, 0xb7, 0xf3, 0xa7, 0x1c, 0x4b, 0xf9, + 0x3b, 0x5a, 0x88, 0xac, 0x60, 0x1b, 0x85, 0x81, 0x16, 0xab, 0x44, 0x17, + 0x08, 0x2e, 0x0f, 0xd4, 0xe2, 0xde, 0x49, 0xc9, 0xe1, 0xc0, 0xc0, 0xa0, + 0x7e, 0x73, 0xa1, 0x67, 0xf8, 0xf5, 0x9f, 0xc4, 0x21, 0x50, 0x4f, 0x05, + 0x2c, 0xfc, 0x5c, 0xaa, 0x85, 0xb0, 0xfa, 0x67, 0x80, 0x7e, 0x0f, 0xfd, + 0x92, 0x30, 0xd5, 0xa0, 0xd4, 0x05, 0xdd, 0x06, 0x68, 0x1d, 0x6e, 0x4e, + 0x8b, 0x79, 0xd6, 0xfc, 0xff, 0x2e, 0x6e, 0x7c, 0xba, 0x03, 0x90, 0xd4, + 0x25, 0x65, 0x8e, 0xe7, 0x3a, 0xd1, 0xd6, 0xdc, 0xf0, 0xbe, 0x12, 0xc4, + 0x31, 0x08, 0x16, 0x70, 0x31, 0x85, 0x61, 0x38, 0x27, 0x0a, 0x91, 0x5f, + 0x03, 0x38, 0xeb, 0x37, 0x13, 0x48, 0x41, 0xbe, 0x7f, 0x04, 0x70, 0x62, + 0x2b, 0x15, 0x91, 0x67, 0x63, 0x4f, 0xad, 0xa7, 0x1d, 0x3f, 0x44, 0x17, + 0x02, 0x08, 0x0d, 0xf2, 0xfc, 0x03, 0xa0, 0x74, 0x21, 0x8b, 0x07, 0x3a, + 0x8d, 0x0f, 0x54, 0x58, 0x94, 0x12, 0xc5, 0x62, 0x18, 0xb9, 0x42, 0xf0, + 0x6c, 0x73, 0xa0, 0x92, 0xad, 0x27, 0x1c, 0x20, 0x0f, 0xc1, 0xca, 0x44, + 0x87, 0x47, 0xc5, 0x43, 0x23, 0x01, 0xda, 0x23, 0xe2, 0x89, 0x38, 0x9f, + 0x1f, 0x8d, 0x8c, 0xc6, 0x95, 0xa3, 0x34, 0x21, 0x21, 0x2d, 0x49, 0xea, + 0x4b, 0x05, 0x85, 0xf5, 0x58, 0x25, 0x13, 0xcd, 0x51, 0x19, 0x1a, 0x88, + 0xa6, 0x83, 0xd6, 0xd0, 0xbc, 0x25, 0x19, 0x1c, 0x92, 0x12, 0x44, 0x5d, + 0x1c, 0x04, 0xf1, 0x99, 0xdf, 0x92, 0x8e, 0x09, 0x85, 0xf3, 0x88, 0x82, + 0x4c, 0x22, 0x17, 0xc5, 0x25, 0x23, 0xed, 0x78, 0xf5, 0x41, 0xd1, 0xe9, + 0x8a, 0xb3, 0x52, 0xd1, 0x3d, 0x79, 0x81, 0x4d, 0x31, 0x24, 0xf9, 0x38, + 0x96, 0xbc, 0xf4, 0x8c, 0x25, 0xe9, 0xf2, 0x73, 0x94, 0x85, 0xc2, 0x61, + 0x6a, 0x34, 0x68, 0x65, 0x78, 0x87, 0xa6, 0x4f}; + +} // namespace + +namespace media { + +// Helper macro to skip the test if MediaCodecBridge isn't available. +#define SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE() \ + do { \ + if (!MediaCodecUtil::IsMediaCodecAvailable()) { \ + VLOG(0) << "Could not run test - not supported on device."; \ + return; \ + } \ + } while (0) + +static const int kPresentationTimeBase = 100; + +static inline const base::TimeDelta InfiniteTimeOut() { + return base::TimeDelta::FromMicroseconds(-1); +} + +void DecodeMediaFrame(VideoCodecBridge* media_codec, + const uint8* data, + size_t data_size, + const base::TimeDelta input_presentation_timestamp, + const base::TimeDelta initial_timestamp_lower_bound) { + base::TimeDelta input_pts = input_presentation_timestamp; + base::TimeDelta timestamp = initial_timestamp_lower_bound; + base::TimeDelta new_timestamp; + for (int i = 0; i < 10; ++i) { + int input_buf_index = -1; + MediaCodecStatus status = + media_codec->DequeueInputBuffer(InfiniteTimeOut(), &input_buf_index); + ASSERT_EQ(MEDIA_CODEC_OK, status); + + media_codec->QueueInputBuffer(input_buf_index, data, data_size, + input_presentation_timestamp); + + size_t unused_offset = 0; + size_t size = 0; + bool eos = false; + int output_buf_index = -1; + status = media_codec->DequeueOutputBuffer( + InfiniteTimeOut(), &output_buf_index, &unused_offset, &size, + &new_timestamp, &eos, nullptr); + + if (status == MEDIA_CODEC_OK && output_buf_index > 0) { + media_codec->ReleaseOutputBuffer(output_buf_index, false); + } + // Output time stamp should not be smaller than old timestamp. + ASSERT_TRUE(new_timestamp >= timestamp); + input_pts += base::TimeDelta::FromMicroseconds(33000); + timestamp = new_timestamp; + } +} + +TEST(SdkMediaCodecBridgeTest, Initialize) { + SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); + + scoped_ptr<media::MediaCodecBridge> media_codec; + media_codec.reset(VideoCodecBridge::CreateDecoder( + kCodecH264, false, gfx::Size(640, 480), nullptr, nullptr)); +} + +TEST(SdkMediaCodecBridgeTest, DoNormal) { + SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); + + scoped_ptr<media::AudioCodecBridge> media_codec; + media_codec.reset(AudioCodecBridge::Create(kCodecMP3)); + + ASSERT_TRUE(media_codec->ConfigureAndStart(kCodecMP3, 44100, 2, nullptr, 0, 0, + 0, false, nullptr)); + + int input_buf_index = -1; + MediaCodecStatus status = + media_codec->DequeueInputBuffer(InfiniteTimeOut(), &input_buf_index); + ASSERT_EQ(MEDIA_CODEC_OK, status); + ASSERT_GE(input_buf_index, 0); + + int64 input_pts = kPresentationTimeBase; + media_codec->QueueInputBuffer(input_buf_index, test_mp3, sizeof(test_mp3), + base::TimeDelta::FromMicroseconds(++input_pts)); + + status = media_codec->DequeueInputBuffer(InfiniteTimeOut(), &input_buf_index); + media_codec->QueueInputBuffer(input_buf_index, test_mp3, sizeof(test_mp3), + base::TimeDelta::FromMicroseconds(++input_pts)); + + status = media_codec->DequeueInputBuffer(InfiniteTimeOut(), &input_buf_index); + media_codec->QueueEOS(input_buf_index); + + input_pts = kPresentationTimeBase; + bool eos = false; + while (!eos) { + size_t unused_offset = 0; + size_t size = 0; + base::TimeDelta timestamp; + int output_buf_index = -1; + status = media_codec->DequeueOutputBuffer(InfiniteTimeOut(), + &output_buf_index, &unused_offset, + &size, ×tamp, &eos, nullptr); + switch (status) { + case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: + FAIL(); + return; + + case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: + continue; + + case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED: + continue; + + default: + break; + } + ASSERT_GE(output_buf_index, 0); + EXPECT_LE(1u, size); + if (!eos) + EXPECT_EQ(++input_pts, timestamp.InMicroseconds()); + ASSERT_LE(input_pts, kPresentationTimeBase + 2); + } + ASSERT_EQ(input_pts, kPresentationTimeBase + 2); +} + +TEST(SdkMediaCodecBridgeTest, InvalidVorbisHeader) { + SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); + + scoped_ptr<media::AudioCodecBridge> media_codec; + media_codec.reset(AudioCodecBridge::Create(kCodecVorbis)); + + // The first byte of the header is not 0x02. + uint8 invalid_first_byte[] = {0x00, 0xff, 0xff, 0xff, 0xff}; + EXPECT_FALSE(media_codec->ConfigureAndStart( + kCodecVorbis, 44100, 2, invalid_first_byte, sizeof(invalid_first_byte), 0, + 0, false, nullptr)); + + // Size of the header does not match with the data we passed in. + uint8 invalid_size[] = {0x02, 0x01, 0xff, 0x01, 0xff}; + EXPECT_FALSE(media_codec->ConfigureAndStart( + kCodecVorbis, 44100, 2, invalid_size, sizeof(invalid_size), 0, 0, false, + nullptr)); + + // Size of the header is too large. + size_t large_size = 8 * 1024 * 1024 + 2; + uint8* very_large_header = new uint8[large_size]; + very_large_header[0] = 0x02; + for (size_t i = 1; i < large_size - 1; ++i) + very_large_header[i] = 0xff; + very_large_header[large_size - 1] = 0xfe; + EXPECT_FALSE(media_codec->ConfigureAndStart(kCodecVorbis, 44100, 2, + very_large_header, 0x80000000, 0, + 0, false, nullptr)); + delete[] very_large_header; +} + +TEST(SdkMediaCodecBridgeTest, InvalidOpusHeader) { + SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); + + scoped_ptr<media::AudioCodecBridge> media_codec; + media_codec.reset(AudioCodecBridge::Create(kCodecOpus)); + uint8 dummy_extra_data[] = {0, 0}; + + // Extra Data is NULL. + EXPECT_FALSE(media_codec->ConfigureAndStart(kCodecOpus, 48000, 2, nullptr, 0, + -1, 0, false, nullptr)); + + // Codec Delay is < 0. + EXPECT_FALSE(media_codec->ConfigureAndStart( + kCodecOpus, 48000, 2, dummy_extra_data, sizeof(dummy_extra_data), -1, 0, + false, nullptr)); + + // Seek Preroll is < 0. + EXPECT_FALSE(media_codec->ConfigureAndStart( + kCodecOpus, 48000, 2, dummy_extra_data, sizeof(dummy_extra_data), 0, -1, + false, nullptr)); +} + +TEST(SdkMediaCodecBridgeTest, PresentationTimestampsDoNotDecrease) { + SKIP_TEST_IF_MEDIA_CODEC_BRIDGE_IS_NOT_AVAILABLE(); + + scoped_ptr<VideoCodecBridge> media_codec(VideoCodecBridge::CreateDecoder( + kCodecVP8, false, gfx::Size(320, 240), nullptr, nullptr)); + EXPECT_TRUE(media_codec.get()); + scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile("vp8-I-frame-320x240"); + DecodeMediaFrame(media_codec.get(), buffer->data(), buffer->data_size(), + base::TimeDelta(), base::TimeDelta()); + + // Simulate a seek to 10 seconds, and each chunk has 2 I-frames. + std::vector<uint8> chunk(buffer->data(), + buffer->data() + buffer->data_size()); + chunk.insert(chunk.end(), buffer->data(), + buffer->data() + buffer->data_size()); + media_codec->Reset(); + DecodeMediaFrame(media_codec.get(), &chunk[0], chunk.size(), + base::TimeDelta::FromMicroseconds(10000000), + base::TimeDelta::FromMicroseconds(9900000)); + + // Simulate a seek to 5 seconds. + media_codec->Reset(); + DecodeMediaFrame(media_codec.get(), &chunk[0], chunk.size(), + base::TimeDelta::FromMicroseconds(5000000), + base::TimeDelta::FromMicroseconds(4900000)); +} + +TEST(SdkMediaCodecBridgeTest, CreateUnsupportedCodec) { + EXPECT_EQ(nullptr, AudioCodecBridge::Create(kUnknownAudioCodec)); + EXPECT_EQ(nullptr, VideoCodecBridge::CreateDecoder(kUnknownVideoCodec, false, + gfx::Size(320, 240), + nullptr, nullptr)); +} + +} // namespace media
diff --git a/media/base/android/video_decoder_job.cc b/media/base/android/video_decoder_job.cc index d43f450..d74ba4ae 100644 --- a/media/base/android/video_decoder_job.cc +++ b/media/base/android/video_decoder_job.cc
@@ -7,8 +7,8 @@ #include "base/bind.h" #include "base/lazy_instance.h" #include "base/threading/thread.h" -#include "media/base/android/media_codec_bridge.h" #include "media/base/android/media_drm_bridge.h" +#include "media/base/android/sdk_media_codec_bridge.h" namespace media {
diff --git a/media/media.gyp b/media/media.gyp index e463802..4b25ca1 100644 --- a/media/media.gyp +++ b/media/media.gyp
@@ -1182,12 +1182,12 @@ ], 'sources': [ 'base/android/access_unit_queue_unittest.cc', - 'base/android/media_codec_bridge_unittest.cc', 'base/android/media_codec_decoder_unittest.cc', 'base/android/media_codec_player_unittest.cc', 'base/android/media_drm_bridge_unittest.cc', 'base/android/media_player_bridge_unittest.cc', 'base/android/media_source_player_unittest.cc', + 'base/android/sdk_media_codec_bridge_unittest.cc', 'base/android/test_data_factory.cc', 'base/android/test_data_factory.h', 'base/android/test_statistics.h', @@ -1807,6 +1807,7 @@ 'base/android/java/src/org/chromium/media/AudioManagerAndroid.java', 'base/android/java/src/org/chromium/media/AudioRecordInput.java', 'base/android/java/src/org/chromium/media/MediaCodecBridge.java', + 'base/android/java/src/org/chromium/media/MediaCodecUtil.java', 'base/android/java/src/org/chromium/media/MediaDrmBridge.java', 'base/android/java/src/org/chromium/media/MediaPlayerBridge.java', 'base/android/java/src/org/chromium/media/MediaPlayerListener.java', @@ -1856,6 +1857,8 @@ 'base/android/media_codec_player.h', 'base/android/media_codec_video_decoder.cc', 'base/android/media_codec_video_decoder.h', + 'base/android/media_codec_util.cc', + 'base/android/media_codec_util.h', 'base/android/media_common_android.h', 'base/android/media_decoder_job.cc', 'base/android/media_decoder_job.h', @@ -1882,12 +1885,28 @@ 'base/android/media_task_runner.h', 'base/android/media_url_interceptor.h', 'base/android/provision_fetcher.h', + 'base/android/sdk_media_codec_bridge.cc', + 'base/android/sdk_media_codec_bridge.h', 'base/android/video_decoder_job.cc', 'base/android/video_decoder_job.h', 'base/android/webaudio_media_codec_bridge.cc', 'base/android/webaudio_media_codec_bridge.h', 'base/android/webaudio_media_codec_info.h', ], + 'conditions': [ + # Only 64 bit builds are using android-21 NDK library, check common.gypi + ['target_arch=="arm64" or target_arch=="x64" or target_arch=="mips64el"', { + 'sources': [ + 'base/android/ndk_media_codec_bridge.cc', + 'base/android/ndk_media_codec_bridge.h', + ], + 'link_settings': { + 'libraries': [ + '-lmediandk', + ], + }, + }], + ], 'dependencies': [ '../base/base.gyp:base', '../third_party/widevine/cdm/widevine_cdm.gyp:widevine_cdm_version_h',
diff --git a/net/base/filename_util_internal.cc b/net/base/filename_util_internal.cc index 57183dc..4cfedcd8 100644 --- a/net/base/filename_util_internal.cc +++ b/net/base/filename_util_internal.cc
@@ -31,7 +31,12 @@ size_t length = filename->size(); size_t pos = filename->find_last_not_of(FILE_PATH_LITERAL(" .")); filename->resize((pos == std::string::npos) ? 0 : (pos + 1)); +#if defined(OS_WIN) base::TrimWhitespace(*filename, base::TRIM_TRAILING, filename); +#else + base::TrimWhitespaceASCII(*filename, base::TRIM_TRAILING, filename); +#endif + if (filename->empty()) return; size_t trimmed = length - filename->size();
diff --git a/net/test/python_utils_unittest.cc b/net/test/python_utils_unittest.cc index 57b7f476..a713e72f 100644 --- a/net/test/python_utils_unittest.cc +++ b/net/test/python_utils_unittest.cc
@@ -61,6 +61,6 @@ cmd_line.AppendArg(python_cmd); std::string output; EXPECT_TRUE(base::GetAppOutput(cmd_line, &output)); - base::TrimWhitespace(output, base::TRIM_TRAILING, &output); + base::TrimWhitespaceASCII(output, base::TRIM_TRAILING, &output); EXPECT_EQ(input, output); }
diff --git a/pdf/document_loader.cc b/pdf/document_loader.cc index 868a8c4..5bbed1a0 100644 --- a/pdf/document_loader.cc +++ b/pdf/document_loader.cc
@@ -36,8 +36,8 @@ std::string range_end; if (pos != std::string::npos) range_end = range.substr(pos + 1); - TrimWhitespaceASCII(range, base::TRIM_LEADING, &range); - TrimWhitespaceASCII(range_end, base::TRIM_LEADING, &range_end); + base::TrimWhitespaceASCII(range, base::TRIM_LEADING, &range); + base::TrimWhitespaceASCII(range_end, base::TRIM_LEADING, &range_end); *start = atoi(range.c_str()); *end = atoi(range_end.c_str()); return true; @@ -145,7 +145,7 @@ if (semi_colon_pos != std::string::npos) { type = type.substr(0, semi_colon_pos); } - TrimWhitespace(type, base::TRIM_ALL, &type); + TrimWhitespaceASCII(type, base::TRIM_ALL, &type); } else if (base::LowerCaseEqualsASCII(it.name(), "content-disposition")) { disposition = it.values(); }
diff --git a/sync/BUILD.gn b/sync/BUILD.gn index 2f0f730..71fc74a 100644 --- a/sync/BUILD.gn +++ b/sync/BUILD.gn
@@ -879,10 +879,10 @@ android_library("sync_java_test_support") { testonly = true deps = [ + "android:sync_java", "//base:base_java", "//base:base_java_test_support", "//third_party/jsr-305:jsr_305_javalib", - "android:sync_java", ] DEPRECATED_java_in_dir = "test/android/javatests/src" }
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 4238e835..5ebb58b 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -752,8 +752,6 @@ crbug.com/484370 [ Win Debug ] svg/custom/gradient-userSpaceOnUse-with-percentage.svg [ Failure ] -crbug.com/116710 [ Win Debug ] transforms/3d/point-mapping/3d-point-mapping-preserve-3d.html [ Failure ] - # Printing Layout broken in these tests. crbug.com/377696 printing/setPrinting.html [ Skip ] crbug.com/377696 printing/width-overflow.html [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/compositing/backface-visibility-transformed-expected.png b/third_party/WebKit/LayoutTests/compositing/backface-visibility-transformed-expected.png index 6e07a2e..bc9a785 100644 --- a/third_party/WebKit/LayoutTests/compositing/backface-visibility-transformed-expected.png +++ b/third_party/WebKit/LayoutTests/compositing/backface-visibility-transformed-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/compositing/overflow/nested-render-surfaces-with-rotation-expected.png b/third_party/WebKit/LayoutTests/compositing/overflow/nested-render-surfaces-with-rotation-expected.png index 598901a..e1f5c92 100644 --- a/third_party/WebKit/LayoutTests/compositing/overflow/nested-render-surfaces-with-rotation-expected.png +++ b/third_party/WebKit/LayoutTests/compositing/overflow/nested-render-surfaces-with-rotation-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/dom/node-filter-use-counters.html b/third_party/WebKit/LayoutTests/fast/dom/node-filter-use-counters.html new file mode 100644 index 0000000..14a3ae1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/dom/node-filter-use-counters.html
@@ -0,0 +1,39 @@ +<!DOCTYPE html> +<title>NodeFilter UseCounters</title> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script> +test(function() { + var NodeFilterIsFunction = 1059; // From UseCounter.h + + assert_false(internals.isUseCounted(document, NodeFilterIsFunction)); + + var filterCalled = false; + var filter = function() { + assert_true(internals.isUseCounted(document, NodeFilterIsFunction)); + filter.called = true; + }; + + var iterator = document.createNodeIterator(document, 0, filter); + iterator.filter.acceptNode(document); + assert_true(filter.called); +}, 'NodeFilter UseCounter for callback function'); + +test(function() { + var NodeFilterIsObject = 1060; // From UseCounter.h + + assert_false(internals.isUseCounted(document, NodeFilterIsObject)); + + var filter = { + acceptNodeCalled: false, + acceptNode: function() { + assert_true(internals.isUseCounted(document, NodeFilterIsObject)); + filter.called = true; + } + }; + + var iterator = document.createNodeIterator(document, 0, filter); + iterator.filter.acceptNode(document); + assert_true(filter.called); +}, 'NodeFilter UseCounter for callback function'); +</script>
diff --git a/third_party/WebKit/LayoutTests/fast/filesystem/null-arguments-expected.txt b/third_party/WebKit/LayoutTests/fast/filesystem/null-arguments-expected.txt index 86022b4..e5ff6cd 100644 --- a/third_party/WebKit/LayoutTests/fast/filesystem/null-arguments-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/filesystem/null-arguments-expected.txt
@@ -4,6 +4,8 @@ Successfully obtained FileSystem: file__0:Temporary +PASS fileSystem.root.moveTo(null) threw exception TypeError: Failed to execute 'moveTo' on 'Entry': parameter 1 is not of type 'DirectoryEntry'.. +PASS fileSystem.root.copyTo(null) threw exception TypeError: Failed to execute 'copyTo' on 'Entry': parameter 1 is not of type 'DirectoryEntry'.. PASS writer.error is null PASS writer.write(null) threw exception TypeError: Failed to execute 'write' on 'FileWriter': parameter 1 is not of type 'Blob'.. PASS writer.error is null
diff --git a/third_party/WebKit/LayoutTests/fast/filesystem/null-arguments.html b/third_party/WebKit/LayoutTests/fast/filesystem/null-arguments.html index 19495e4..ba87454 100644 --- a/third_party/WebKit/LayoutTests/fast/filesystem/null-arguments.html +++ b/third_party/WebKit/LayoutTests/fast/filesystem/null-arguments.html
@@ -18,6 +18,8 @@ window.fileSystem = fs; debug("Successfully obtained FileSystem: " + fileSystem.name); + shouldThrow("fileSystem.root.moveTo(null)"); + shouldThrow("fileSystem.root.copyTo(null)"); fileSystem.root.getFile("/test", { create: true }, function(entry) { entry.createWriter(function(writer) { window.writer = writer;
diff --git a/third_party/WebKit/LayoutTests/platform/android/compositing/backface-visibility-transformed-expected.png b/third_party/WebKit/LayoutTests/platform/android/compositing/backface-visibility-transformed-expected.png new file mode 100644 index 0000000..6e07a2e --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/compositing/backface-visibility-transformed-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/compositing/geometry/vertical-scroll-composited-expected.png b/third_party/WebKit/LayoutTests/platform/android/compositing/geometry/vertical-scroll-composited-expected.png new file mode 100644 index 0000000..96a745f1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/compositing/geometry/vertical-scroll-composited-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/compositing/overflow/nested-render-surfaces-with-rotation-expected.png b/third_party/WebKit/LayoutTests/platform/android/compositing/overflow/nested-render-surfaces-with-rotation-expected.png new file mode 100644 index 0000000..598901a --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/compositing/overflow/nested-render-surfaces-with-rotation-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/compositing/reflections/nested-reflection-animated-expected.png b/third_party/WebKit/LayoutTests/platform/android/compositing/reflections/nested-reflection-animated-expected.png new file mode 100644 index 0000000..38634564 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/compositing/reflections/nested-reflection-animated-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/compositing/reflections/transform-inside-reflection-expected.png b/third_party/WebKit/LayoutTests/platform/android/compositing/reflections/transform-inside-reflection-expected.png new file mode 100644 index 0000000..0cf6a2a --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/compositing/reflections/transform-inside-reflection-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png b/third_party/WebKit/LayoutTests/platform/android/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png new file mode 100644 index 0000000..b905bb7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png b/third_party/WebKit/LayoutTests/platform/android/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png new file mode 100644 index 0000000..f7a07e9e --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/media/video-layer-crash-expected.png b/third_party/WebKit/LayoutTests/platform/android/media/video-layer-crash-expected.png new file mode 100644 index 0000000..5b53bbe --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/media/video-layer-crash-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/media/video-transformed-expected.png b/third_party/WebKit/LayoutTests/platform/android/media/video-transformed-expected.png new file mode 100644 index 0000000..49346e41 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/media/video-transformed-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/transforms/3d/general/perspective-units-expected.png b/third_party/WebKit/LayoutTests/platform/android/transforms/3d/general/perspective-units-expected.png new file mode 100644 index 0000000..7cb846c --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/transforms/3d/general/perspective-units-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png b/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png new file mode 100644 index 0000000..81d32f2b --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png b/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png new file mode 100644 index 0000000..c455c60a --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-expected.png b/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-expected.png new file mode 100644 index 0000000..2f2d944f --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png b/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png new file mode 100644 index 0000000..d772043 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png b/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png new file mode 100644 index 0000000..3848ee814 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-with-rotation-expected.png b/third_party/WebKit/LayoutTests/platform/android/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-with-rotation-expected.png new file mode 100644 index 0000000..7fb3b24 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-with-rotation-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/layer-due-to-layer-children-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/layer-due-to-layer-children-expected.png index d0dbdc0..d79b934 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/layer-due-to-layer-children-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/layer-due-to-layer-children-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/vertical-scroll-composited-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/vertical-scroll-composited-expected.png index 96a745f1..2f459985 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/vertical-scroll-composited-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/geometry/vertical-scroll-composited-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/perpendicular-layer-sorting-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/perpendicular-layer-sorting-expected.png index bf790f1..b45d024 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/compositing/perpendicular-layer-sorting-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/perpendicular-layer-sorting-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-animated-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-animated-expected.png index 38634564..6c65c589 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-animated-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/nested-reflection-animated-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/transform-inside-reflection-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/transform-inside-reflection-expected.png index 0cf6a2a..f0154a6a 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/transform-inside-reflection-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/reflections/transform-inside-reflection-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png b/third_party/WebKit/LayoutTests/platform/linux/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png index b905bb7..b6e878a 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png index f7a07e9e..0102e495 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/video-layer-crash-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/video-layer-crash-expected.png index 5b53bbe..6a0526f 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/media/video-layer-crash-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/media/video-layer-crash-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/video-transformed-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/video-transformed-expected.png index 49346e41..7e0e513 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/media/video-transformed-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/media/video-transformed-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/general/perspective-units-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/general/perspective-units-expected.png index 7cb846c..710f11652 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/general/perspective-units-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/general/perspective-units-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png index 81d32f2b..07b957e 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png index c455c60a..b1a3574 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-expected.png index 2f2d944f..bc9146b 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png index d772043..4f99c115 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png index 3848ee814..69827c7 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png b/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png index a341ef37..86086f55 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-expected.png b/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-expected.png index f101ab3..8948eadf 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png b/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png index 90f2b8a..819ca38 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png b/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png index 03cfd4d5..509260e 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-lion/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png index 06a112ba..e019cae 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-expected.png index 04c7734aae..9326d29 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png index 5eda092..344a6306 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png index 0cc9602..4eeba60 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-mavericks/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png b/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png index 4ed0094..eb91ba1 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-expected.png b/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-expected.png index 5e6426a..6466c73 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png b/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png index 1ed76505..ad4bf90a 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png b/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png index 3c043c20..675e272 100644 --- a/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac-snowleopard/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/geometry/layer-due-to-layer-children-deep-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/geometry/layer-due-to-layer-children-deep-expected.png index 19a67dc..b215d68 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/compositing/geometry/layer-due-to-layer-children-deep-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/geometry/layer-due-to-layer-children-deep-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/geometry/layer-due-to-layer-children-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/geometry/layer-due-to-layer-children-expected.png index 77b7cb6..59358cd 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/compositing/geometry/layer-due-to-layer-children-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/geometry/layer-due-to-layer-children-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/geometry/vertical-scroll-composited-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/geometry/vertical-scroll-composited-expected.png index 96a745f1..2f459985 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/compositing/geometry/vertical-scroll-composited-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/geometry/vertical-scroll-composited-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/perpendicular-layer-sorting-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/perpendicular-layer-sorting-expected.png index bf790f1..b45d024 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/compositing/perpendicular-layer-sorting-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/perpendicular-layer-sorting-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-anchor-point-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-anchor-point-expected.png index d1ef18e..d27567f 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-anchor-point-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-anchor-point-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-animated-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-animated-expected.png index f1f5eda..cad9908 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-animated-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/nested-reflection-animated-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/transform-inside-reflection-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/transform-inside-reflection-expected.png index 1bc5fb79..bb10b7d 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/transform-inside-reflection-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/reflections/transform-inside-reflection-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png b/third_party/WebKit/LayoutTests/platform/mac/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png index 861a2c5..cb048616 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/video-layer-crash-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/video-layer-crash-expected.png index 7090363..878ae797 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/media/video-layer-crash-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/media/video-layer-crash-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/general/perspective-units-expected.png b/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/general/perspective-units-expected.png index 64a3bac..6a608a73 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/general/perspective-units-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/general/perspective-units-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png b/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png index 6ea69e6..4040a8a 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png b/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png index fb7ba570..bef14c1e 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-expected.png b/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-expected.png index 7841001..933a1929 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png b/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png index d4d4e9b..9442da9b 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png b/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png index aa223a8..c110b94 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/compositing/geometry/layer-due-to-layer-children-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/compositing/geometry/layer-due-to-layer-children-expected.png index 5ac8156..d484463e 100644 --- a/third_party/WebKit/LayoutTests/platform/win-xp/compositing/geometry/layer-due-to-layer-children-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win-xp/compositing/geometry/layer-due-to-layer-children-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/compositing/reflections/nested-reflection-animated-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/compositing/reflections/nested-reflection-animated-expected.png index f5027d61..19427c2 100644 --- a/third_party/WebKit/LayoutTests/platform/win-xp/compositing/reflections/nested-reflection-animated-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win-xp/compositing/reflections/nested-reflection-animated-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/compositing/reflections/transform-inside-reflection-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/compositing/reflections/transform-inside-reflection-expected.png index b5ba0d6..c805f41 100644 --- a/third_party/WebKit/LayoutTests/platform/win-xp/compositing/reflections/transform-inside-reflection-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win-xp/compositing/reflections/transform-inside-reflection-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png index 214782df..00f9db8 100644 --- a/third_party/WebKit/LayoutTests/platform/win-xp/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win-xp/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png index 5a3c8eb6..363c4b8 100644 --- a/third_party/WebKit/LayoutTests/platform/win-xp/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win-xp/fast/sub-pixel/transformed-iframe-copy-on-scroll-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/media/video-layer-crash-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/media/video-layer-crash-expected.png index faae7af..9be8946e 100644 --- a/third_party/WebKit/LayoutTests/platform/win-xp/media/video-layer-crash-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win-xp/media/video-layer-crash-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/media/video-transformed-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/media/video-transformed-expected.png index 8e2b2f6..d83de2f8 100644 --- a/third_party/WebKit/LayoutTests/platform/win-xp/media/video-transformed-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win-xp/media/video-transformed-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/transforms/3d/general/transform-origin-z-change-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/transforms/3d/general/transform-origin-z-change-expected.png new file mode 100644 index 0000000..31128b99 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win-xp/transforms/3d/general/transform-origin-z-change-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png index 010752cf..45d36d6 100644 --- a/third_party/WebKit/LayoutTests/platform/win-xp/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win-xp/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win-xp/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png b/third_party/WebKit/LayoutTests/platform/win-xp/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png index eface4b..707929c8 100644 --- a/third_party/WebKit/LayoutTests/platform/win-xp/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win-xp/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/geometry/layer-due-to-layer-children-deep-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/geometry/layer-due-to-layer-children-deep-expected.png index 7888087..a37a800 100644 --- a/third_party/WebKit/LayoutTests/platform/win/compositing/geometry/layer-due-to-layer-children-deep-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/compositing/geometry/layer-due-to-layer-children-deep-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/geometry/layer-due-to-layer-children-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/geometry/layer-due-to-layer-children-expected.png index 000f41e..72d1b311 100644 --- a/third_party/WebKit/LayoutTests/platform/win/compositing/geometry/layer-due-to-layer-children-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/compositing/geometry/layer-due-to-layer-children-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/geometry/vertical-scroll-composited-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/geometry/vertical-scroll-composited-expected.png index 3adcda9..f08c2b5 100644 --- a/third_party/WebKit/LayoutTests/platform/win/compositing/geometry/vertical-scroll-composited-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/compositing/geometry/vertical-scroll-composited-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/perpendicular-layer-sorting-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/perpendicular-layer-sorting-expected.png index 2f7a463..a505f0c8 100644 --- a/third_party/WebKit/LayoutTests/platform/win/compositing/perpendicular-layer-sorting-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/compositing/perpendicular-layer-sorting-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-anchor-point-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-anchor-point-expected.png index 9b8c8a0..87a94b2 100644 --- a/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-anchor-point-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-anchor-point-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-animated-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-animated-expected.png index 0c4e95c0..dc86fe2 100644 --- a/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-animated-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/nested-reflection-animated-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/transform-inside-reflection-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/transform-inside-reflection-expected.png index d57757b..a3403cc6 100644 --- a/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/transform-inside-reflection-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/compositing/reflections/transform-inside-reflection-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png b/third_party/WebKit/LayoutTests/platform/win/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png index d052d94..b16a1966 100644 --- a/third_party/WebKit/LayoutTests/platform/win/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/video-layer-crash-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/video-layer-crash-expected.png index 678bc1c..dfa30bab 100644 --- a/third_party/WebKit/LayoutTests/platform/win/media/video-layer-crash-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/media/video-layer-crash-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/transforms/3d/general/perspective-units-expected.png b/third_party/WebKit/LayoutTests/platform/win/transforms/3d/general/perspective-units-expected.png index e11aec8..14b2a3b 100644 --- a/third_party/WebKit/LayoutTests/platform/win/transforms/3d/general/perspective-units-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/transforms/3d/general/perspective-units-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png b/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png index 9f42f39..1e1f09b6 100644 --- a/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-coplanar-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png b/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png index 121fe2f..cd61512 100644 --- a/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-expected.png b/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-expected.png index 688d518a..2563581 100644 --- a/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png b/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png index 78a00780..e7aeea4 100644 --- a/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-origins-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png b/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png index 08647a2..66fbeb0 100644 --- a/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/transforms/3d/general/transform-origin-z-change-expected.png b/third_party/WebKit/LayoutTests/transforms/3d/general/transform-origin-z-change-expected.png index 31128b99..d761571 100644 --- a/third_party/WebKit/LayoutTests/transforms/3d/general/transform-origin-z-change-expected.png +++ b/third_party/WebKit/LayoutTests/transforms/3d/general/transform-origin-z-change-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-with-rotation-expected.png b/third_party/WebKit/LayoutTests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-with-rotation-expected.png index 7fb3b24..b474717 100644 --- a/third_party/WebKit/LayoutTests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-with-rotation-expected.png +++ b/third_party/WebKit/LayoutTests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-with-rotation-expected.png Binary files differ
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8NodeFilterCondition.cpp b/third_party/WebKit/Source/bindings/core/v8/V8NodeFilterCondition.cpp index 45e5517..2346c0bf 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8NodeFilterCondition.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8NodeFilterCondition.cpp
@@ -36,6 +36,7 @@ #include "bindings/core/v8/V8Node.h" #include "core/dom/Node.h" #include "core/dom/NodeFilter.h" +#include "core/frame/UseCounter.h" #include "wtf/OwnPtr.h" namespace blink { @@ -73,6 +74,7 @@ v8::Local<v8::Function> callback; v8::Local<v8::Value> receiver; if (filter->IsFunction()) { + UseCounter::countIfNotPrivateScript(isolate, callingExecutionContext(isolate), UseCounter::NodeFilterIsFunction); callback = v8::Local<v8::Function>::Cast(filter); receiver = v8::Undefined(isolate); } else { @@ -86,6 +88,7 @@ exceptionState.throwTypeError("NodeFilter object does not have an acceptNode function"); return NodeFilter::FILTER_REJECT; } + UseCounter::countIfNotPrivateScript(isolate, callingExecutionContext(isolate), UseCounter::NodeFilterIsObject); callback = v8::Local<v8::Function>::Cast(value); receiver = filter; }
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn index b80e959b..315a91b 100644 --- a/third_party/WebKit/Source/core/BUILD.gn +++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -49,6 +49,8 @@ deps = [ ":make_core_generated", ":prerequisites", + "inspector:instrumentation_sources", + "inspector:protocol_sources", "//gin", "//skia", "//third_party/WebKit/Source/bindings/core/v8:bindings_core_v8_generated", @@ -60,8 +62,6 @@ "//third_party/npapi", "//third_party/qcms", "//third_party/sqlite", - "inspector:instrumentation_sources", - "inspector:protocol_sources", # FIXME: don't depend on bindings/modules http://crbug.com/358074 "//third_party/WebKit/Source/bindings/modules:bindings_modules_generated", @@ -97,9 +97,9 @@ ] deps = [ ":make_core_generated", - "//third_party/WebKit/Source/bindings/core/v8:bindings_core_v8_generated", "inspector:instrumentation_sources", "inspector:protocol_sources", + "//third_party/WebKit/Source/bindings/core/v8:bindings_core_v8_generated", # FIXME: don't depend on bindings_modules http://crbug.com/358074 "//third_party/WebKit/Source/bindings/modules/v8:bindings_modules_generated", @@ -423,6 +423,8 @@ public_deps = [ ":make_core_generated", ":prerequisites", + "inspector:instrumentation_sources", + "inspector:protocol_sources", "//gin", "//skia", "//third_party/WebKit/Source/bindings/core/v8:bindings_core_v8_generated", @@ -434,8 +436,6 @@ "//third_party/npapi", "//third_party/qcms", "//third_party/sqlite", - "inspector:instrumentation_sources", - "inspector:protocol_sources", # FIXME: don't depend on bindings/modules http://crbug.com/358074 "//third_party/WebKit/Source/bindings/modules:bindings_modules_generated",
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.h b/third_party/WebKit/Source/core/frame/UseCounter.h index 445fa206..ecc81deb 100644 --- a/third_party/WebKit/Source/core/frame/UseCounter.h +++ b/third_party/WebKit/Source/core/frame/UseCounter.h
@@ -914,6 +914,8 @@ RTCPeerConnectionSetRemoteDescriptionLegacyNoFailureCallback = 1056, RTCPeerConnectionSetRemoteDescriptionLegacyCompliant = 1057, RTCPeerConnectionGetStatsLegacyNonCompliant = 1058, + NodeFilterIsFunction = 1059, + NodeFilterIsObject = 1060, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/WebKit/Source/modules/filesystem/Entry.idl b/third_party/WebKit/Source/modules/filesystem/Entry.idl index b00bc1d..d7162ef1 100644 --- a/third_party/WebKit/Source/modules/filesystem/Entry.idl +++ b/third_party/WebKit/Source/modules/filesystem/Entry.idl
@@ -39,8 +39,8 @@ readonly attribute DOMFileSystem filesystem; void getMetadata(MetadataCallback successCallback, optional ErrorCallback errorCallback); - [LegacyInterfaceTypeChecking] void moveTo(DirectoryEntry parent, [TreatUndefinedAs=NullString] optional DOMString? name, optional EntryCallback successCallback, optional ErrorCallback errorCallback); - [LegacyInterfaceTypeChecking] void copyTo(DirectoryEntry parent, [TreatUndefinedAs=NullString] optional DOMString? name, optional EntryCallback successCallback, optional ErrorCallback errorCallback); + void moveTo(DirectoryEntry parent, [TreatUndefinedAs=NullString] optional DOMString? name, optional EntryCallback successCallback, optional ErrorCallback errorCallback); + void copyTo(DirectoryEntry parent, [TreatUndefinedAs=NullString] optional DOMString? name, optional EntryCallback successCallback, optional ErrorCallback errorCallback); DOMString toURL(); void remove(VoidCallback successCallback, optional ErrorCallback errorCallback); void getParent(optional EntryCallback successCallback, optional ErrorCallback errorCallback);
diff --git a/third_party/boringssl/BUILD.gn b/third_party/boringssl/BUILD.gn index c0c5565..7de949b 100644 --- a/third_party/boringssl/BUILD.gn +++ b/third_party/boringssl/BUILD.gn
@@ -74,6 +74,7 @@ if (is_android) { rebased_android_toolchain_root = rebase_path(android_toolchain_root, root_build_dir) + # Else /usr/bin/as gets picked up. asmflags += [ "-B${rebased_android_toolchain_root}/bin" ] }
diff --git a/third_party/cacheinvalidation/BUILD.gn b/third_party/cacheinvalidation/BUILD.gn index 6035d5dc..083c6ff 100644 --- a/third_party/cacheinvalidation/BUILD.gn +++ b/third_party/cacheinvalidation/BUILD.gn
@@ -115,11 +115,11 @@ deps = [ ":cacheinvalidation", + "src/google/cacheinvalidation:cacheinvalidation_proto_cpp", "//base", "//base/test:run_all_unittests", "//testing/gmock", "//testing/gtest", - "src/google/cacheinvalidation:cacheinvalidation_proto_cpp", ] }
diff --git a/third_party/libvpx_new/BUILD.gn b/third_party/libvpx_new/BUILD.gn index 26aff0a..e2a0320 100644 --- a/third_party/libvpx_new/BUILD.gn +++ b/third_party/libvpx_new/BUILD.gn
@@ -55,6 +55,7 @@ if (is_android) { rebased_android_toolchain_root = rebase_path(android_toolchain_root, root_build_dir) + # Else /usr/bin/as gets picked up. asmflags += [ "-B${rebased_android_toolchain_root}/bin" ] }
diff --git a/tools/gn/example/BUILD.gn b/tools/gn/example/BUILD.gn index 58af9523..a18390e 100644 --- a/tools/gn/example/BUILD.gn +++ b/tools/gn/example/BUILD.gn
@@ -8,8 +8,8 @@ ] deps = [ - ":hello_static", ":hello_shared", + ":hello_static", ] }
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index abd8810..5ea6df9 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -63782,6 +63782,8 @@ <int value="1057" label="RTCPeerConnectionSetRemoteDescriptionLegacyCompliant"/> <int value="1058" label="RTCPeerConnectionGetStatsLegacyNonCompliant"/> + <int value="1059" label="NodeFilterIsFunction"/> + <int value="1060" label="NodeFilterIsObject"/> </enum> <enum name="FetchRequestMode" type="int">
diff --git a/ui/base/clipboard/clipboard_util_win.cc b/ui/base/clipboard/clipboard_util_win.cc index c0c05b0..ed5fe5f 100644 --- a/ui/base/clipboard/clipboard_util_win.cc +++ b/ui/base/clipboard/clipboard_util_win.cc
@@ -446,7 +446,7 @@ fragment_start != std::string::npos && fragment_end != std::string::npos) { *html = cf_html.substr(fragment_start, fragment_end - fragment_start); - base::TrimWhitespace(*html, base::TRIM_ALL, html); + base::TrimWhitespaceASCII(*html, base::TRIM_ALL, html); } } @@ -464,7 +464,7 @@ size_t src_start = line_start + src_url_str.length(); if (src_end != std::string::npos && src_start != std::string::npos) { *base_url = cf_html.substr(src_start, src_end - src_start); - base::TrimWhitespace(*base_url, base::TRIM_ALL, base_url); + base::TrimWhitespaceASCII(*base_url, base::TRIM_ALL, base_url); } } }
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc index b057366..fbc801d 100644 --- a/ui/compositor/compositor.cc +++ b/ui/compositor/compositor.cc
@@ -137,8 +137,8 @@ settings.initial_debug_state.SetRecordRenderingStats( command_line->HasSwitch(cc::switches::kEnableGpuBenchmarking)); - settings.use_property_trees = - command_line->HasSwitch(cc::switches::kEnableCompositorPropertyTrees); + if (command_line->HasSwitch(cc::switches::kDisableCompositorPropertyTrees)) + settings.use_property_trees = false; settings.use_zero_copy = IsUIZeroCopyEnabled(); settings.renderer_settings.use_rgba_4444_textures =
diff --git a/ui/gfx/font_fallback_win.cc b/ui/gfx/font_fallback_win.cc index 1612f3c7..c578ba8 100644 --- a/ui/gfx/font_fallback_win.cc +++ b/ui/gfx/font_fallback_win.cc
@@ -206,8 +206,8 @@ const size_t index = font_names->back().find('('); if (index != std::string::npos) { font_names->back().resize(index); - base::TrimWhitespace(font_names->back(), base::TRIM_TRAILING, - &font_names->back()); + base::TrimWhitespaceASCII(font_names->back(), base::TRIM_TRAILING, + &font_names->back()); } } }