blob: a688c12b57b087cfff965bf97fbae8f08a10976f [file] [log] [blame]
// Copyright 2014 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 "base/bind.h"
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "content/child/child_process.h"
#include "content/renderer/media/video_capture_impl.h"
#include "content/renderer/media/video_capture_impl_manager.h"
#include "content/renderer/media/video_capture_message_filter.h"
#include "media/base/bind_to_current_loop.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::_;
using ::testing::DoAll;
using ::testing::SaveArg;
using media::BindToCurrentLoop;
namespace content {
ACTION_P(RunClosure, closure) {
closure.Run();
}
class MockVideoCaptureImpl : public VideoCaptureImpl {
public:
MockVideoCaptureImpl(media::VideoCaptureSessionId session_id,
VideoCaptureMessageFilter* filter,
base::Closure destruct_callback)
: VideoCaptureImpl(session_id, filter),
destruct_callback_(destruct_callback) {
}
~MockVideoCaptureImpl() override { destruct_callback_.Run(); }
private:
base::Closure destruct_callback_;
DISALLOW_COPY_AND_ASSIGN(MockVideoCaptureImpl);
};
class MockVideoCaptureImplManager : public VideoCaptureImplManager {
public:
explicit MockVideoCaptureImplManager(
base::Closure destruct_video_capture_callback)
: destruct_video_capture_callback_(
destruct_video_capture_callback) {}
~MockVideoCaptureImplManager() override {}
protected:
VideoCaptureImpl* CreateVideoCaptureImplForTesting(
media::VideoCaptureSessionId id,
VideoCaptureMessageFilter* filter) const override {
return new MockVideoCaptureImpl(id,
filter,
destruct_video_capture_callback_);
}
private:
base::Closure destruct_video_capture_callback_;
DISALLOW_COPY_AND_ASSIGN(MockVideoCaptureImplManager);
};
class VideoCaptureImplManagerTest : public ::testing::Test {
public:
VideoCaptureImplManagerTest()
: manager_(new MockVideoCaptureImplManager(
BindToCurrentLoop(cleanup_run_loop_.QuitClosure()))) {
params_.requested_format = media::VideoCaptureFormat(
gfx::Size(176, 144), 30, media::PIXEL_FORMAT_I420);
child_process_.reset(new ChildProcess());
}
void FakeChannelSetup() {
scoped_refptr<base::MessageLoopProxy> loop =
child_process_->io_message_loop_proxy();
if (!loop->BelongsToCurrentThread()) {
loop->PostTask(
FROM_HERE,
base::Bind(
&VideoCaptureImplManagerTest::FakeChannelSetup,
base::Unretained(this)));
return;
}
manager_->video_capture_message_filter()->OnFilterAdded(NULL);
}
protected:
MOCK_METHOD3(OnFrameReady,
void(const scoped_refptr<media::VideoFrame>&,
const media::VideoCaptureFormat&,
const base::TimeTicks& estimated_capture_time));
MOCK_METHOD0(OnStarted, void());
MOCK_METHOD0(OnStopped, void());
void OnStateUpdate(VideoCaptureState state) {
switch (state) {
case VIDEO_CAPTURE_STATE_STARTED:
OnStarted();
break;
case VIDEO_CAPTURE_STATE_STOPPED:
OnStopped();
break;
default:
NOTREACHED();
}
}
base::Closure StartCapture(const media::VideoCaptureParams& params) {
return manager_->StartCapture(
0, params,
base::Bind(&VideoCaptureImplManagerTest::OnStateUpdate,
base::Unretained(this)),
base::Bind(&VideoCaptureImplManagerTest::OnFrameReady,
base::Unretained(this)));
}
base::MessageLoop message_loop_;
scoped_ptr<ChildProcess> child_process_;
media::VideoCaptureParams params_;
base::RunLoop cleanup_run_loop_;
scoped_ptr<MockVideoCaptureImplManager> manager_;
private:
DISALLOW_COPY_AND_ASSIGN(VideoCaptureImplManagerTest);
};
// Multiple clients with the same session id. There is only one
// media::VideoCapture object.
TEST_F(VideoCaptureImplManagerTest, MultipleClients) {
base::Closure release_cb1 = manager_->UseDevice(0);
base::Closure release_cb2 = manager_->UseDevice(0);
base::Closure stop_cb1, stop_cb2;
{
base::RunLoop run_loop;
base::Closure quit_closure = BindToCurrentLoop(
run_loop.QuitClosure());
EXPECT_CALL(*this, OnStarted()).WillOnce(
RunClosure(quit_closure));
EXPECT_CALL(*this, OnStarted()).RetiresOnSaturation();
stop_cb1 = StartCapture(params_);
stop_cb2 = StartCapture(params_);
FakeChannelSetup();
run_loop.Run();
}
{
base::RunLoop run_loop;
base::Closure quit_closure = BindToCurrentLoop(
run_loop.QuitClosure());
EXPECT_CALL(*this, OnStopped()).WillOnce(
RunClosure(quit_closure));
EXPECT_CALL(*this, OnStopped()).RetiresOnSaturation();
stop_cb1.Run();
stop_cb2.Run();
run_loop.Run();
}
release_cb1.Run();
release_cb2.Run();
cleanup_run_loop_.Run();
}
TEST_F(VideoCaptureImplManagerTest, NoLeak) {
manager_->UseDevice(0).Reset();
manager_.reset();
cleanup_run_loop_.Run();
}
} // namespace content