Commit 9aa45129 authored by Sergey Ulanov's avatar Sergey Ulanov Committed by Commit Bot

[Fuchsia] Update FuchsiaVideoDecoder to use sysmem for output buffers.

Now FuchsiaVideoDecoder uses sysmem to allocate output buffers instead
of creating raw VMOs. The sysmem collection is shared with the GPU
where it's passed to Vulkan. This means that decoded frames are now
passed from mediacodec to Vulkan directly, without being touched by
the renderer or the GPU process.

Bug: 981026
Change-Id: I7dc8b48ceb0621966034e554897efd542af63a6e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1752918Reviewed-by: default avatarenne <enne@chromium.org>
Reviewed-by: default avatarWez <wez@chromium.org>
Reviewed-by: default avatarDan Sanders <sandersd@chromium.org>
Commit-Queue: Sergey Ulanov <sergeyu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#689065}
parent dc068eae
...@@ -40,6 +40,9 @@ specific_include_rules = { ...@@ -40,6 +40,9 @@ specific_include_rules = {
"cras_unified_unittest.cc": [ "cras_unified_unittest.cc": [
"+chromeos/dbus" "+chromeos/dbus"
], ],
"fuchsia_video_decoder_unittest.cc": [
"+components/viz/test/test_context_support.h",
],
"gpu_memory_buffer_video_frame_pool_unittest.cc": [ "gpu_memory_buffer_video_frame_pool_unittest.cc": [
"+components/viz/test/test_context_provider.h", "+components/viz/test/test_context_provider.h",
], ],
......
...@@ -209,8 +209,14 @@ jumbo_source_set("filters") { ...@@ -209,8 +209,14 @@ jumbo_source_set("filters") {
"fuchsia/fuchsia_video_decoder.h", "fuchsia/fuchsia_video_decoder.h",
] ]
deps += [ deps += [
"//gpu/command_buffer/client",
"//gpu/command_buffer/common",
"//gpu/ipc/common",
"//third_party/fuchsia-sdk/sdk:media", "//third_party/fuchsia-sdk/sdk:media",
"//third_party/fuchsia-sdk/sdk:mediacodec", "//third_party/fuchsia-sdk/sdk:mediacodec",
"//third_party/fuchsia-sdk/sdk:sys_cpp",
"//third_party/fuchsia-sdk/sdk:sysmem",
"//ui/ozone",
] ]
} }
} }
...@@ -311,6 +317,11 @@ source_set("unit_tests") { ...@@ -311,6 +317,11 @@ source_set("unit_tests") {
if (is_fuchsia) { if (is_fuchsia) {
sources += [ "fuchsia/fuchsia_video_decoder_unittest.cc" ] sources += [ "fuchsia/fuchsia_video_decoder_unittest.cc" ]
deps += [
"//components/viz/test:test_support",
"//third_party/fuchsia-sdk/sdk:sys_cpp",
"//third_party/fuchsia-sdk/sdk:sysmem",
]
} }
# libvpx for running vpx test on chromecast doesn't support high bit depth. # libvpx for running vpx test on chromecast doesn't support high bit depth.
......
...@@ -9,18 +9,28 @@ ...@@ -9,18 +9,28 @@
#include "media/base/media_export.h" #include "media/base/media_export.h"
namespace gpu {
class ContextSupport;
class SharedImageInterface;
} // namespace gpu
namespace media { namespace media {
class VideoDecoder; class VideoDecoder;
// Creates VideoDecoder that uses fuchsia.mediacodec API. The returned // Creates VideoDecoder that uses fuchsia.mediacodec API. The returned
// VideoDecoder instance will only try to use hardware video codecs. // VideoDecoder instance will only try to use hardware video codecs.
MEDIA_EXPORT std::unique_ptr<VideoDecoder> CreateFuchsiaVideoDecoder(); // |shared_image_interface| and |gpu_context_support| must outlive the decoder.
MEDIA_EXPORT std::unique_ptr<VideoDecoder> CreateFuchsiaVideoDecoder(
gpu::SharedImageInterface* shared_image_interface,
gpu::ContextSupport* gpu_context_support);
// Same as above, but also allows to enable software codecs. This is useful for // Same as above, but also allows to enable software codecs. This is useful for
// FuchsiaVideoDecoder tests that run on systems that don't have hardware // FuchsiaVideoDecoder tests that run on systems that don't have hardware
// decoder support. // decoder support.
MEDIA_EXPORT std::unique_ptr<VideoDecoder> CreateFuchsiaVideoDecoderForTests( MEDIA_EXPORT std::unique_ptr<VideoDecoder> CreateFuchsiaVideoDecoderForTests(
gpu::SharedImageInterface* shared_image_interface,
gpu::ContextSupport* gpu_context_support,
bool enable_sw_decoding); bool enable_sw_decoding);
} // namespace media } // namespace media
......
...@@ -4,21 +4,188 @@ ...@@ -4,21 +4,188 @@
#include "media/filters/fuchsia/fuchsia_video_decoder.h" #include "media/filters/fuchsia/fuchsia_video_decoder.h"
#include <fuchsia/sysmem/cpp/fidl.h>
#include <lib/sys/cpp/component_context.h>
#include "base/bind.h" #include "base/bind.h"
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/fuchsia/default_context.h"
#include "base/fuchsia/fuchsia_logging.h"
#include "base/test/scoped_task_environment.h" #include "base/test/scoped_task_environment.h"
#include "components/viz/test/test_context_support.h"
#include "gpu/command_buffer/client/shared_image_interface.h"
#include "media/base/test_data_util.h" #include "media/base/test_data_util.h"
#include "media/base/test_helpers.h" #include "media/base/test_helpers.h"
#include "media/base/video_decoder.h" #include "media/base/video_decoder.h"
#include "media/base/video_frame.h" #include "media/base/video_frame.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/gpu_memory_buffer.h"
namespace media { namespace media {
namespace {
class TestBufferCollection {
public:
explicit TestBufferCollection(zx::channel collection_token) {
sysmem_allocator_ = base::fuchsia::ComponentContextForCurrentProcess()
->svc()
->Connect<fuchsia::sysmem::Allocator>();
sysmem_allocator_.set_error_handler([](zx_status_t status) {
ZX_LOG(FATAL, status)
<< "The fuchsia.sysmem.Allocator channel was terminated.";
});
sysmem_allocator_->BindSharedCollection(
fidl::InterfaceHandle<fuchsia::sysmem::BufferCollectionToken>(
std::move(collection_token)),
buffers_collection_.NewRequest());
fuchsia::sysmem::BufferCollectionConstraints buffer_constraints;
buffer_constraints.usage.cpu = fuchsia::sysmem::cpuUsageRead;
zx_status_t status = buffers_collection_->SetConstraints(
/*has_constraints=*/true, std::move(buffer_constraints));
ZX_CHECK(status == ZX_OK, status) << "BufferCollection::SetConstraints()";
}
~TestBufferCollection() { buffers_collection_->Close(); }
size_t GetNumBuffers() {
if (!buffer_collection_info_) {
zx_status_t wait_status;
fuchsia::sysmem::BufferCollectionInfo_2 info;
zx_status_t status =
buffers_collection_->WaitForBuffersAllocated(&wait_status, &info);
ZX_CHECK(status == ZX_OK, status)
<< "BufferCollection::WaitForBuffersAllocated()";
ZX_CHECK(wait_status == ZX_OK, wait_status)
<< "BufferCollection::WaitForBuffersAllocated()";
buffer_collection_info_ = std::move(info);
}
return buffer_collection_info_->buffer_count;
}
private:
fuchsia::sysmem::AllocatorPtr sysmem_allocator_;
fuchsia::sysmem::BufferCollectionSyncPtr buffers_collection_;
base::Optional<fuchsia::sysmem::BufferCollectionInfo_2>
buffer_collection_info_;
DISALLOW_COPY_AND_ASSIGN(TestBufferCollection);
};
class TestSharedImageInterface : public gpu::SharedImageInterface {
public:
TestSharedImageInterface() = default;
~TestSharedImageInterface() override = default;
gpu::Mailbox CreateSharedImage(viz::ResourceFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage) override {
NOTREACHED();
return gpu::Mailbox();
}
gpu::Mailbox CreateSharedImage(
viz::ResourceFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage,
base::span<const uint8_t> pixel_data) override {
NOTREACHED();
return gpu::Mailbox();
}
gpu::Mailbox CreateSharedImage(
gfx::GpuMemoryBuffer* gpu_memory_buffer,
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
const gfx::ColorSpace& color_space,
uint32_t usage) override {
gfx::GpuMemoryBufferHandle handle = gpu_memory_buffer->CloneHandle();
CHECK_EQ(handle.type, gfx::GpuMemoryBufferType::NATIVE_PIXMAP);
auto collection_it = sysmem_buffer_collections_.find(
handle.native_pixmap_handle.buffer_collection_id);
CHECK(collection_it != sysmem_buffer_collections_.end());
CHECK_LT(handle.native_pixmap_handle.buffer_index,
collection_it->second->GetNumBuffers());
auto result = gpu::Mailbox::Generate();
mailoxes_.insert(result);
return result;
}
void UpdateSharedImage(const gpu::SyncToken& sync_token,
const gpu::Mailbox& mailbox) override {
NOTREACHED();
}
void UpdateSharedImage(const gpu::SyncToken& sync_token,
std::unique_ptr<gfx::GpuFence> acquire_fence,
const gpu::Mailbox& mailbox) override {
NOTREACHED();
}
void DestroySharedImage(const gpu::SyncToken& sync_token,
const gpu::Mailbox& mailbox) override {
CHECK_EQ(mailoxes_.erase(mailbox), 1U);
}
SwapChainMailboxes CreateSwapChain(viz::ResourceFormat format,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage) override {
NOTREACHED();
return SwapChainMailboxes();
}
void PresentSwapChain(const gpu::SyncToken& sync_token,
const gpu::Mailbox& mailbox) override {
NOTREACHED();
}
void RegisterSysmemBufferCollection(gfx::SysmemBufferCollectionId id,
zx::channel token) override {
std::unique_ptr<TestBufferCollection>& collection =
sysmem_buffer_collections_[id];
EXPECT_FALSE(collection);
collection = std::make_unique<TestBufferCollection>(std::move(token));
}
void ReleaseSysmemBufferCollection(
gfx::SysmemBufferCollectionId id) override {
EXPECT_EQ(sysmem_buffer_collections_.erase(id), 1U);
}
gpu::SyncToken GenVerifiedSyncToken() override {
NOTREACHED();
return gpu::SyncToken();
}
gpu::SyncToken GenUnverifiedSyncToken() override {
return gpu::SyncToken(gpu::CommandBufferNamespace::GPU_IO,
gpu::CommandBufferId(33), 1);
}
void Flush() override { NOTREACHED(); }
private:
base::flat_map<gfx::SysmemBufferCollectionId,
std::unique_ptr<TestBufferCollection>>
sysmem_buffer_collections_;
base::flat_set<gpu::Mailbox> mailoxes_;
};
} // namespace
class FuchsiaVideoDecoderTest : public testing::Test { class FuchsiaVideoDecoderTest : public testing::Test {
public: public:
FuchsiaVideoDecoderTest() { FuchsiaVideoDecoderTest() {
decoder_ = CreateFuchsiaVideoDecoderForTests(/*enable_sw_decoding=*/true); decoder_ = CreateFuchsiaVideoDecoderForTests(&shared_image_interface_,
&gpu_context_support_,
/*enable_sw_decoding=*/true);
} }
~FuchsiaVideoDecoderTest() override = default; ~FuchsiaVideoDecoderTest() override = default;
...@@ -43,6 +210,7 @@ class FuchsiaVideoDecoderTest : public testing::Test { ...@@ -43,6 +210,7 @@ class FuchsiaVideoDecoderTest : public testing::Test {
void OnVideoFrame(scoped_refptr<VideoFrame> frame) { void OnVideoFrame(scoped_refptr<VideoFrame> frame) {
num_output_frames_++; num_output_frames_++;
CHECK(frame->HasTextures());
output_frames_.push_back(std::move(frame)); output_frames_.push_back(std::move(frame));
while (output_frames_.size() > frames_to_keep_) { while (output_frames_.size() > frames_to_keep_) {
output_frames_.pop_front(); output_frames_.pop_front();
...@@ -76,6 +244,10 @@ class FuchsiaVideoDecoderTest : public testing::Test { ...@@ -76,6 +244,10 @@ class FuchsiaVideoDecoderTest : public testing::Test {
base::test::TaskEnvironment task_environment_{ base::test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::ThreadingMode::MAIN_THREAD_ONLY, base::test::TaskEnvironment::ThreadingMode::MAIN_THREAD_ONLY,
base::test::TaskEnvironment::MainThreadType::IO}; base::test::TaskEnvironment::MainThreadType::IO};
TestSharedImageInterface shared_image_interface_;
viz::TestContextSupport gpu_context_support_;
std::unique_ptr<VideoDecoder> decoder_; std::unique_ptr<VideoDecoder> decoder_;
std::list<scoped_refptr<VideoFrame>> output_frames_; std::list<scoped_refptr<VideoFrame>> output_frames_;
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "build/buildflag.h" #include "build/buildflag.h"
#include "components/viz/common/gpu/context_provider.h"
#include "media/base/decoder_factory.h" #include "media/base/decoder_factory.h"
#include "media/base/media_switches.h" #include "media/base/media_switches.h"
#include "media/media_buildflags.h" #include "media/media_buildflags.h"
...@@ -104,7 +105,11 @@ void DefaultDecoderFactory::CreateVideoDecoders( ...@@ -104,7 +105,11 @@ void DefaultDecoderFactory::CreateVideoDecoders(
} }
#if defined(OS_FUCHSIA) #if defined(OS_FUCHSIA)
video_decoders->push_back(CreateFuchsiaVideoDecoder()); if (gpu_factories) {
video_decoders->push_back(CreateFuchsiaVideoDecoder(
gpu_factories->SharedImageInterface(),
gpu_factories->GetMediaContextProvider()->ContextSupport()));
}
#endif #endif
#if BUILDFLAG(ENABLE_LIBVPX) #if BUILDFLAG(ENABLE_LIBVPX)
......
...@@ -87,26 +87,28 @@ VideoFrameResourceType ExternalResourceTypeForHardwarePlanes( ...@@ -87,26 +87,28 @@ VideoFrameResourceType ExternalResourceTypeForHardwarePlanes(
} }
break; break;
case PIXEL_FORMAT_I420: case PIXEL_FORMAT_I420:
DCHECK(num_textures == 3); DCHECK_EQ(num_textures, 3);
buffer_formats[0] = gfx::BufferFormat::R_8; buffer_formats[0] = gfx::BufferFormat::R_8;
buffer_formats[1] = gfx::BufferFormat::R_8; buffer_formats[1] = gfx::BufferFormat::R_8;
buffer_formats[2] = gfx::BufferFormat::R_8; buffer_formats[2] = gfx::BufferFormat::R_8;
return VideoFrameResourceType::YUV; return VideoFrameResourceType::YUV;
case PIXEL_FORMAT_NV12: case PIXEL_FORMAT_NV12:
DCHECK(target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_2D || // |target| is set to 0 for Vulkan textures.
target == GL_TEXTURE_RECTANGLE_ARB) DCHECK(target == 0 || target == GL_TEXTURE_EXTERNAL_OES ||
target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ARB)
<< "Unsupported target " << gl::GLEnums::GetStringEnum(target); << "Unsupported target " << gl::GLEnums::GetStringEnum(target);
DCHECK(num_textures <= 2);
// Single plane textures can be sampled as RGB. if (num_textures == 1) {
if (num_textures == 2) { // Single-texture multi-planar frames can be sampled as RGB.
buffer_formats[0] = gfx::BufferFormat::R_8; buffer_formats[0] = gfx::BufferFormat::YUV_420_BIPLANAR;
buffer_formats[1] = gfx::BufferFormat::RG_88; return VideoFrameResourceType::RGB;
return VideoFrameResourceType::YUV;
} }
buffer_formats[0] = gfx::BufferFormat::YUV_420_BIPLANAR; buffer_formats[0] = gfx::BufferFormat::R_8;
return VideoFrameResourceType::RGB; buffer_formats[1] = gfx::BufferFormat::RG_88;
return VideoFrameResourceType::YUV;
case PIXEL_FORMAT_YV12: case PIXEL_FORMAT_YV12:
case PIXEL_FORMAT_I422: case PIXEL_FORMAT_I422:
case PIXEL_FORMAT_I444: case PIXEL_FORMAT_I444:
......
...@@ -20,7 +20,6 @@ class ClientNativePixmapFuchsia : public gfx::ClientNativePixmap { ...@@ -20,7 +20,6 @@ class ClientNativePixmapFuchsia : public gfx::ClientNativePixmap {
public: public:
explicit ClientNativePixmapFuchsia(gfx::NativePixmapHandle handle) explicit ClientNativePixmapFuchsia(gfx::NativePixmapHandle handle)
: handle_(std::move(handle)) { : handle_(std::move(handle)) {
DCHECK(!handle_.planes.empty());
} }
~ClientNativePixmapFuchsia() override { ~ClientNativePixmapFuchsia() override {
...@@ -32,10 +31,8 @@ class ClientNativePixmapFuchsia : public gfx::ClientNativePixmap { ...@@ -32,10 +31,8 @@ class ClientNativePixmapFuchsia : public gfx::ClientNativePixmap {
if (mapping_) if (mapping_)
return true; return true;
if (!handle_.planes[0].vmo) { if (handle_.planes.empty() || !handle_.planes[0].vmo)
NOTREACHED();
return false; return false;
}
uintptr_t addr; uintptr_t addr;
...@@ -110,8 +107,6 @@ class ScenicClientNativePixmapFactory : public gfx::ClientNativePixmapFactory { ...@@ -110,8 +107,6 @@ class ScenicClientNativePixmapFactory : public gfx::ClientNativePixmapFactory {
const gfx::Size& size, const gfx::Size& size,
gfx::BufferFormat format, gfx::BufferFormat format,
gfx::BufferUsage usage) override { gfx::BufferUsage usage) override {
if (handle.planes.empty())
return nullptr;
return std::make_unique<ClientNativePixmapFuchsia>(std::move(handle)); return std::make_unique<ClientNativePixmapFuchsia>(std::move(handle));
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment