blob: c3a0e5e78a6ad58e93c587e6fe676a44354b6dfd [file] [log] [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/video_effects/video_effects_processor_impl.h"
#include <optional>
#include "base/functional/callback_helpers.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/unsafe_shared_memory_region.h"
#include "base/notreached.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "base/test/test_future.h"
#include "gpu/command_buffer/common/capabilities.h"
#include "gpu/command_buffer/common/context_result.h"
#include "gpu/command_buffer/common/mailbox_holder.h"
#include "gpu/ipc/common/gpu_channel.mojom-forward.h"
#include "gpu/ipc/common/mock_gpu_channel.h"
#include "media/capture/mojom/video_capture_buffer.mojom.h"
#include "media/capture/mojom/video_effects_manager.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "services/video_effects/public/mojom/video_effects_processor.mojom.h"
#include "services/video_effects/test_gpu_channel_host_provider.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace video_effects {
using testing::_;
namespace {
// Helper, returns dummy (but valid) VideoBufferHandlePtr.
media::mojom::VideoBufferHandlePtr GetDummyVideoBufferHandle() {
auto shared_image = gpu::ClientSharedImage::CreateForTesting();
return media::mojom::VideoBufferHandle::NewSharedImageHandle(
media::mojom::SharedImageBufferHandleSet::New(shared_image->Export(),
gpu::SyncToken()));
}
class VideoEffectsProcessorTest : public testing::Test {
void SetUp() override {
scoped_refptr<GpuChannelHostProvider> gpu_channel_host_provider =
new TestGpuChannelHostProvider(gpu_channel_);
on_processor_error_.emplace();
processor_impl_.emplace(
wgpu::Device{}, manager_receiver_.InitWithNewPipeAndPassRemote(),
processor_remote_.BindNewPipeAndPassReceiver(),
gpu_channel_host_provider, on_processor_error_->GetCallback());
}
protected:
base::test::TaskEnvironment task_environment_;
gpu::MockGpuChannel gpu_channel_;
// Processor under test:
std::optional<VideoEffectsProcessorImpl> processor_impl_;
std::optional<base::test::TestFuture<void>> on_processor_error_;
// Processor under test's remote. The unit-tests will usually interact with
// the processor via the remote.
mojo::Remote<mojom::VideoEffectsProcessor> processor_remote_;
mojo::PendingReceiver<media::mojom::ReadonlyVideoEffectsManager>
manager_receiver_;
};
TEST_F(VideoEffectsProcessorTest, InitializeSucceeds) {
ON_CALL(gpu_channel_, CreateCommandBuffer(_, _, _, _, _, _, _, _))
.WillByDefault(
[](gpu::mojom::CreateCommandBufferParamsPtr params,
int32_t routing_id, base::UnsafeSharedMemoryRegion shared_state,
mojo::PendingAssociatedReceiver<gpu::mojom::CommandBuffer>
receiver,
mojo::PendingAssociatedRemote<gpu::mojom::CommandBufferClient>
client,
gpu::ContextResult* result, gpu::Capabilities* capabilities,
gpu::GLCapabilities* gl_capabilities) -> bool {
capabilities->sync_query = true;
receiver.EnableUnassociatedUsage();
*result = gpu::ContextResult::kSuccess;
return true;
});
// DO_NOT_SUBMIT: Fails to initialize because of a lack of valid context
// providers and wgpu::Device
// EXPECT_TRUE(processor_impl_->Initialize());
EXPECT_FALSE(processor_impl_->Initialize());
}
TEST_F(VideoEffectsProcessorTest, ErrorCallbackCalledWhenManagerDisconnects) {
manager_receiver_.reset();
EXPECT_TRUE(on_processor_error_->Wait());
}
TEST_F(VideoEffectsProcessorTest, ErrorCallbackCalledWhenProcessorDisconnects) {
processor_remote_.reset();
EXPECT_TRUE(on_processor_error_->Wait());
}
// TODO(b/333097635): Figure out how to mock/fake the GpuChannel so that it
// does not raise context loss events immediately after creating context
// providers.
TEST_F(VideoEffectsProcessorTest,
DISABLED_ErrorCallbackCalledContextRecreationFailed) {
// Initialize the processor first, GPU service connections won't be
// established until the processor has been initialized and thus it won't
// auto-recover from GPU context loss.
ASSERT_TRUE(processor_impl_->Initialize());
}
// TODO(b/333097635): Figure out how to mock/fake the GpuChannel so that it
// does not raise context loss events immediately after creating context
// providers.
TEST_F(VideoEffectsProcessorTest,
DISABLED_ProcessorGivesUpAfterTooManyContextLosses) {}
TEST_F(VideoEffectsProcessorTest, PostProcessRunsAndFails) {
// For now, since `VideoEffectsProcessorImpl` is still a stub, we expect a
// call to `VideoEffectsProcessor::PostProcess()` to fail.
base::test::TestFuture<mojom::PostProcessResultPtr> post_process_result;
processor_remote_->PostProcess(
GetDummyVideoBufferHandle(), media::mojom::VideoFrameInfo::New(),
GetDummyVideoBufferHandle(), media::VideoPixelFormat::PIXEL_FORMAT_I420,
post_process_result.GetCallback());
mojom::PostProcessResultPtr result = post_process_result.Take();
EXPECT_TRUE(result->is_error());
}
} // namespace
} // namespace video_effects