| // Copyright 2016 The Cobalt Authors. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include <memory> |
| |
| #include "base/files/file_enumerator.h" |
| #include "base/files/file_path.h" |
| #include "base/files/file_util.h" |
| #include "base/logging.h" |
| #include "base/path_service.h" |
| #include "base/time/time.h" |
| #include "base/trace_event/trace_event.h" |
| #include "cobalt/base/wrap_main.h" |
| #include "cobalt/loader/image/image_decoder.h" |
| #include "cobalt/math/size.h" |
| #include "cobalt/renderer/renderer_module.h" |
| #include "cobalt/system_window/system_window.h" |
| #include "cobalt/trace_event/scoped_trace_to_file.h" |
| |
| namespace cobalt { |
| namespace loader { |
| namespace image { |
| namespace sandbox { |
| namespace { |
| const int kViewportWidth = 1920; |
| const int kViewportHeight = 1080; |
| |
| using base::FileEnumerator; |
| using render_tree::ResourceProvider; |
| using renderer::RendererModule; |
| using system_window::SystemWindow; |
| |
| struct ImageDecoderCallback { |
| void SuccessCallback(const scoped_refptr<loader::image::Image>& value) { |
| image = value; |
| } |
| |
| void LoadCompleteCallback(const base::Optional<std::string>& error) { |
| if (error) LOG(ERROR) << *error; |
| } |
| |
| scoped_refptr<loader::image::Image> image; |
| }; |
| |
| std::vector<base::FilePath> GetImagePaths(const char* extension) { |
| base::FilePath image_path; |
| CHECK(base::PathService::Get(base::DIR_TEST_DATA, &image_path)); |
| image_path = image_path.Append(FILE_PATH_LITERAL("cobalt")) |
| .Append(FILE_PATH_LITERAL("loader")) |
| .Append(FILE_PATH_LITERAL("testdata")); |
| |
| std::vector<base::FilePath> result; |
| FileEnumerator file_enumerator(image_path, false /* Not recursive */, |
| FileEnumerator::FILES); |
| for (base::FilePath next = file_enumerator.Next(); !next.empty(); |
| next = file_enumerator.Next()) { |
| if (next.Extension() == extension) { |
| result.push_back(next); |
| } |
| } |
| return result; |
| } |
| |
| std::vector<uint8> GetFileContent(const base::FilePath& file_path) { |
| int64 size; |
| std::vector<uint8> data; |
| |
| bool success = base::GetFileSize(file_path, &size); |
| |
| CHECK(success) << "Could not get file size."; |
| CHECK_GT(size, 0); |
| |
| data.resize(static_cast<size_t>(size)); |
| |
| int num_of_bytes = base::ReadFile( |
| file_path, reinterpret_cast<char*>(&data[0]), static_cast<int>(size)); |
| |
| CHECK_EQ(num_of_bytes, data.size()) |
| << "Could not read '" << file_path.value() << "'."; |
| return data; |
| } |
| |
| void DecodeImages(ResourceProvider* resource_provider, const char* extension) { |
| std::vector<base::FilePath> paths = GetImagePaths(extension); |
| base::TimeDelta total_time; |
| size_t total_size = 0; |
| |
| for (size_t i = 0; i < paths.size(); ++i) { |
| base::NullDebuggerHooks debugger_hooks; |
| ImageDecoderCallback image_decoder_result; |
| std::vector<uint8> image_data = GetFileContent(paths[i]); |
| |
| base::Time start = base::Time::Now(); |
| std::unique_ptr<Decoder> image_decoder( |
| new ImageDecoder(resource_provider, debugger_hooks, |
| base::Bind(&ImageDecoderCallback::SuccessCallback, |
| base::Unretained(&image_decoder_result)), |
| base::Bind(&ImageDecoderCallback::LoadCompleteCallback, |
| base::Unretained(&image_decoder_result)))); |
| |
| image_decoder->DecodeChunk(reinterpret_cast<char*>(&image_data[0]), |
| image_data.size()); |
| image_decoder->Finish(); |
| if (image_decoder_result.image) { |
| base::TimeDelta decoding_time = base::Time::Now() - start; |
| total_time += decoding_time; |
| total_size += image_decoder_result.image->GetEstimatedSizeInBytes(); |
| LOG(INFO) << "Decoding " << paths[i].BaseName().value() << " takes " |
| << decoding_time.InMicroseconds() << " microseconds"; |
| } |
| } |
| if (total_time.InMicroseconds() != 0) { |
| LOG(INFO) << "Average decoding speed for type \"" << extension << "\" is " |
| << total_size * base::Time::kMicrosecondsPerSecond / |
| total_time.InMicroseconds() |
| << " byte per seconds"; |
| } |
| } |
| |
| int SandboxMain(int argc, char** argv) { |
| cobalt::trace_event::ScopedTraceToFile trace_to_file( |
| base::FilePath(FILE_PATH_LITERAL("image_decoder_sandbox_trace.json"))); |
| |
| math::Size view_size(kViewportWidth, kViewportHeight); |
| |
| base::EventDispatcher event_dispatcher; |
| // Create a system window to use as a render target. |
| std::unique_ptr<SystemWindow> system_window( |
| new cobalt::system_window::SystemWindow(&event_dispatcher, view_size)); |
| |
| // Construct a renderer module using default options. |
| RendererModule::Options renderer_module_options; |
| RendererModule renderer_module(system_window.get(), renderer_module_options); |
| |
| // Try to decode all images in the given folder. |
| ResourceProvider* resource_provider = |
| renderer_module.pipeline()->GetResourceProvider(); |
| DecodeImages(resource_provider, ".jpg"); |
| DecodeImages(resource_provider, ".png"); |
| DecodeImages(resource_provider, ".webp"); |
| |
| return 0; |
| } |
| |
| } // namespace |
| } // namespace sandbox |
| } // namespace image |
| } // namespace loader |
| } // namespace cobalt |
| |
| COBALT_WRAP_SIMPLE_MAIN(cobalt::loader::image::sandbox::SandboxMain); |