blob: 8006fc545a13482cdbb909e2cd531df37bce63e2 [file] [log] [blame]
// Copyright 2018 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 "components/mirroring/service/video_capture_client.h"
#include "base/bind.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/run_loop.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_task_environment.h"
#include "components/mirroring/service/fake_video_capture_host.h"
#include "media/base/video_frame.h"
#include "media/base/video_frame_metadata.h"
#include "media/capture/mojom/video_capture_types.mojom.h"
#include "mojo/public/cpp/base/shared_memory_utils.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::InvokeWithoutArgs;
using ::testing::_;
namespace mirroring {
namespace {
constexpr double kUtilization = 0.6;
media::mojom::VideoFrameInfoPtr GetVideoFrameInfo(const gfx::Size& size) {
media::VideoFrameMetadata metadata;
metadata.SetDouble(media::VideoFrameMetadata::FRAME_RATE, 30);
metadata.SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME,
base::TimeTicks());
return media::mojom::VideoFrameInfo::New(
base::TimeDelta(), metadata.GetInternalValues().Clone(),
media::PIXEL_FORMAT_I420, size, gfx::Rect(size),
gfx::ColorSpace::CreateREC709(), nullptr);
}
} // namespace
class VideoCaptureClientTest : public ::testing::Test,
public ::testing::WithParamInterface<bool> {
public:
VideoCaptureClientTest() {
media::mojom::VideoCaptureHostPtr host;
host_impl_ =
std::make_unique<FakeVideoCaptureHost>(mojo::MakeRequest(&host));
client_ = std::make_unique<VideoCaptureClient>(media::VideoCaptureParams(),
std::move(host));
}
~VideoCaptureClientTest() override {
if (client_) {
base::RunLoop run_loop;
EXPECT_CALL(*host_impl_, OnStopped())
.WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
client_->Stop();
run_loop.Run();
}
scoped_task_environment_.RunUntilIdle();
}
MOCK_METHOD1(OnFrameReceived, void(const gfx::Size&));
void OnFrameReady(scoped_refptr<media::VideoFrame> video_frame) {
video_frame->metadata()->SetDouble(
media::VideoFrameMetadata::RESOURCE_UTILIZATION, kUtilization);
OnFrameReceived(video_frame->coded_size());
}
protected:
void StartCapturing() {
EXPECT_CALL(error_cb_, Run()).Times(0);
base::RunLoop run_loop;
// Expect to call RequestRefreshFrame() after capturing started.
EXPECT_CALL(*host_impl_, RequestRefreshFrame(_))
.WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
client_->Start(base::BindRepeating(&VideoCaptureClientTest::OnFrameReady,
base::Unretained(this)),
error_cb_.Get());
run_loop.Run();
scoped_task_environment_.RunUntilIdle();
}
void OnNewBuffer(int buffer_id, int buffer_size) {
EXPECT_CALL(error_cb_, Run()).Times(0);
const bool use_shared_buffer = GetParam();
if (use_shared_buffer) {
client_->OnNewBuffer(
buffer_id, media::mojom::VideoBufferHandle::NewSharedBufferHandle(
mojo::SharedBufferHandle::Create(buffer_size)));
} else {
client_->OnNewBuffer(
buffer_id,
media::mojom::VideoBufferHandle::NewReadOnlyShmemRegion(
mojo::CreateReadOnlySharedMemoryRegion(buffer_size).region));
}
scoped_task_environment_.RunUntilIdle();
}
void OnBufferReady(int buffer_id, const gfx::Size& frame_size) {
EXPECT_CALL(error_cb_, Run()).Times(0);
base::RunLoop run_loop;
// Expects to receive one frame.
EXPECT_CALL(*this, OnFrameReceived(frame_size)).Times(1);
// Expects to return the buffer after the frame is consumed.
EXPECT_CALL(*host_impl_, ReleaseBuffer(_, 0, kUtilization))
.WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
client_->OnBufferReady(buffer_id, GetVideoFrameInfo(frame_size));
run_loop.Run();
scoped_task_environment_.RunUntilIdle();
}
private:
base::test::ScopedTaskEnvironment scoped_task_environment_;
base::MockCallback<base::OnceClosure> error_cb_;
std::unique_ptr<FakeVideoCaptureHost> host_impl_;
std::unique_ptr<VideoCaptureClient> client_;
DISALLOW_COPY_AND_ASSIGN(VideoCaptureClientTest);
};
TEST_P(VideoCaptureClientTest, Basic) {
StartCapturing();
// A new buffer is created.
OnNewBuffer(0, 100000);
// One captured frame is ready. Expects to receive the frame.
OnBufferReady(0, gfx::Size(126, 64));
// A smaller size video frame is received in the same buffer.
OnBufferReady(0, gfx::Size(64, 32));
// A larger size video frame is received in the same buffer.
OnBufferReady(0, gfx::Size(320, 180));
}
INSTANTIATE_TEST_CASE_P(,
VideoCaptureClientTest,
::testing::Values(true, false));
} // namespace mirroring