summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authormcasas <mcasas@chromium.org>2015-03-30 08:46:26 -0700
committerCommit bot <commit-bot@chromium.org>2015-03-30 15:47:14 +0000
commitbfd1d51df98fa47330e7dfc0ca450d58b97f5254 (patch)
treea773275be24aaec59d2ad4f2673326f9f1a09c3b /media
parentd4e5c3a72c36baef955c01d23216682972c4bcc5 (diff)
downloadchromium_src-bfd1d51df98fa47330e7dfc0ca450d58b97f5254.zip
chromium_src-bfd1d51df98fa47330e7dfc0ca450d58b97f5254.tar.gz
chromium_src-bfd1d51df98fa47330e7dfc0ca450d58b97f5254.tar.bz2
FakeVideoCaptureDevice: cleanup, adding 'Direct' capture API, unit tests.
** FakeVideoCaptureDevice is only used for Debug and needs an explicit command line flag to turn it on ** FakeVCD uses its own buffer for capture. This CL extends it to be able to use Client provided Buffers ('Direct' API). It also adds skeleton, NOTIMPLEMENTED() code for GpuMemoryBuffers, to be added in an inminent CL. UnitTests are also extended accordingly. The command line flag --use-fake-device-for-media-stream is modified such that : - if there isn't any value associated to it, the behaviour is the legacy one: FakeVCD capturing in its own buffers. - else: (there is a parameter --use-fake-device-for-media-stream=bla) -- if |bla| is _not_ 'GPU' (case insensitive) then Cient-Buffers are used. -- else GpuMemoryBuffers are used (not implemented yet, but is the next CL see http://crrev.com/1040563002). Other things: - FakeVCD used to have an internal capture thread for no particular reason, possibly to replicate capture events coming from OS threads. That behaviour is in any case not explicitly tested (and exists in FileVCD), so is removed. - FakeVCD's functionality of producing different capture resolutions in sequence is not used and hasn't been for quite some time. Its associated UnitTest is Disabled (http://crbug.com/407061) so I changed the method to NOTIMPLEMENTED() until someone addresses this situation. BUG=440843, 339990 Review URL: https://codereview.chromium.org/1033143002 Cr-Commit-Position: refs/heads/master@{#322783}
Diffstat (limited to 'media')
-rw-r--r--media/video/capture/fake_video_capture_device.cc270
-rw-r--r--media/video/capture/fake_video_capture_device.h50
-rw-r--r--media/video/capture/fake_video_capture_device_factory.cc23
-rw-r--r--media/video/capture/fake_video_capture_device_unittest.cc133
4 files changed, 255 insertions, 221 deletions
diff --git a/media/video/capture/fake_video_capture_device.cc b/media/video/capture/fake_video_capture_device.cc
index d68d2a8..5e5c387 100644
--- a/media/video/capture/fake_video_capture_device.cc
+++ b/media/video/capture/fake_video_capture_device.cc
@@ -18,61 +18,72 @@
namespace media {
static const int kFakeCaptureBeepCycle = 10; // Visual beep every 0.5s.
-static const int kFakeCaptureCapabilityChangePeriod = 30;
-FakeVideoCaptureDevice::FakeVideoCaptureDevice()
- : capture_thread_("CaptureThread"),
- frame_count_(0),
- format_roster_index_(0) {}
-
-FakeVideoCaptureDevice::~FakeVideoCaptureDevice() {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!capture_thread_.IsRunning());
-}
+void DrawPacman(bool use_argb,
+ uint8_t* const data,
+ int frame_count,
+ int frame_interval,
+ const gfx::Size& frame_size) {
+ // |kN32_SkColorType| stands for the appropriiate RGBA/BGRA format.
+ const SkColorType colorspace =
+ use_argb ? kN32_SkColorType : kAlpha_8_SkColorType;
+ const SkImageInfo info = SkImageInfo::Make(frame_size.width(),
+ frame_size.height(),
+ colorspace,
+ kOpaque_SkAlphaType);
+ SkBitmap bitmap;
+ bitmap.setInfo(info);
+ bitmap.setPixels(data);
+ SkPaint paint;
+ paint.setStyle(SkPaint::kFill_Style);
+ SkCanvas canvas(bitmap);
-void FakeVideoCaptureDevice::AllocateAndStart(
- const VideoCaptureParams& params,
- scoped_ptr<VideoCaptureDevice::Client> client) {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (capture_thread_.IsRunning()) {
- NOTREACHED();
- return;
+ // Equalize Alpha_8 that has light green background while RGBA has white.
+ if (use_argb) {
+ const SkRect full_frame = SkRect::MakeWH(frame_size.width(),
+ frame_size.height());
+ paint.setARGB(255, 0, 127, 0);
+ canvas.drawRect(full_frame, paint);
}
+ paint.setColor(SK_ColorGREEN);
- capture_thread_.Start();
- capture_thread_.message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&FakeVideoCaptureDevice::OnAllocateAndStart,
- base::Unretained(this),
- params,
- base::Passed(&client)));
-}
+ // Draw a sweeping circle to show an animation.
+ const int end_angle = (3 * kFakeCaptureBeepCycle * frame_count % 361);
+ const int radius = std::min(frame_size.width(), frame_size.height()) / 4;
+ const SkRect rect = SkRect::MakeXYWH(frame_size.width() / 2 - radius,
+ frame_size.height() / 2 - radius,
+ 2 * radius,
+ 2 * radius);
+ canvas.drawArc(rect, 0, end_angle, true, paint);
-void FakeVideoCaptureDevice::StopAndDeAllocate() {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (!capture_thread_.IsRunning()) {
- NOTREACHED();
- return;
- }
- capture_thread_.message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&FakeVideoCaptureDevice::OnStopAndDeAllocate,
- base::Unretained(this)));
- capture_thread_.Stop();
+ // Draw current time.
+ const int elapsed_ms = frame_interval * frame_count;
+ const int milliseconds = elapsed_ms % 1000;
+ const int seconds = (elapsed_ms / 1000) % 60;
+ const int minutes = (elapsed_ms / 1000 / 60) % 60;
+ const int hours = (elapsed_ms / 1000 / 60 / 60) % 60;
+
+ const std::string time_string = base::StringPrintf("%d:%02d:%02d:%03d %d",
+ hours, minutes, seconds, milliseconds, frame_count);
+ canvas.scale(3, 3);
+ canvas.drawText(time_string.data(), time_string.length(), 30, 20, paint);
}
-void FakeVideoCaptureDevice::PopulateVariableFormatsRoster(
- const VideoCaptureFormats& formats) {
+FakeVideoCaptureDevice::FakeVideoCaptureDevice(
+ FakeVideoCaptureDeviceType device_type)
+ : device_type_(device_type),
+ frame_count_(0),
+ weak_factory_(this) {}
+
+FakeVideoCaptureDevice::~FakeVideoCaptureDevice() {
DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!capture_thread_.IsRunning());
- format_roster_ = formats;
- format_roster_index_ = 0;
}
-void FakeVideoCaptureDevice::OnAllocateAndStart(
+void FakeVideoCaptureDevice::AllocateAndStart(
const VideoCaptureParams& params,
scoped_ptr<VideoCaptureDevice::Client> client) {
- DCHECK_EQ(capture_thread_.message_loop(), base::MessageLoop::current());
+ DCHECK(thread_checker_.CalledOnValidThread());
+
client_ = client.Pass();
// Incoming |params| can be none of the supported formats, so we get the
@@ -80,7 +91,7 @@ void FakeVideoCaptureDevice::OnAllocateAndStart(
// the supported ones, when http://crbug.com/309554 is verified.
DCHECK_EQ(params.requested_format.pixel_format, PIXEL_FORMAT_I420);
capture_format_.pixel_format = params.requested_format.pixel_format;
- capture_format_.frame_rate = 30;
+ capture_format_.frame_rate = 30.0;
if (params.requested_format.frame_size.width() > 1280)
capture_format_.frame_size.SetSize(1920, 1080);
else if (params.requested_format.frame_size.width() > 640)
@@ -89,78 +100,46 @@ void FakeVideoCaptureDevice::OnAllocateAndStart(
capture_format_.frame_size.SetSize(640, 480);
else
capture_format_.frame_size.SetSize(320, 240);
- const size_t fake_frame_size =
- VideoFrame::AllocationSize(VideoFrame::I420, capture_format_.frame_size);
- fake_frame_.reset(new uint8[fake_frame_size]);
- capture_thread_.message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&FakeVideoCaptureDevice::OnCaptureTask,
- base::Unretained(this)));
+ switch (device_type_) {
+ case USING_OWN_BUFFERS:
+ fake_frame_.reset(new uint8[VideoFrame::AllocationSize(
+ VideoFrame::I420, capture_format_.frame_size)]);
+ BeepAndScheduleNextCapture(
+ base::Bind(&FakeVideoCaptureDevice::CaptureUsingOwnBuffers,
+ weak_factory_.GetWeakPtr()));
+ break;
+ case USING_CLIENT_BUFFERS:
+ BeepAndScheduleNextCapture(
+ base::Bind(&FakeVideoCaptureDevice::CaptureUsingClientBuffers,
+ weak_factory_.GetWeakPtr()));
+ break;
+ case USING_GPU_MEMORY_BUFFERS:
+ BeepAndScheduleNextCapture(
+ base::Bind(&FakeVideoCaptureDevice::CaptureUsingGpuMemoryBuffers,
+ weak_factory_.GetWeakPtr()));
+ break;
+ default:
+ client_->OnError("Unknown Fake Video Capture Device type.");
+ }
}
-void FakeVideoCaptureDevice::OnStopAndDeAllocate() {
- DCHECK_EQ(capture_thread_.message_loop(), base::MessageLoop::current());
+void FakeVideoCaptureDevice::StopAndDeAllocate() {
+ DCHECK(thread_checker_.CalledOnValidThread());
client_.reset();
}
-void FakeVideoCaptureDevice::OnCaptureTask() {
- if (!client_)
- return;
-
+void FakeVideoCaptureDevice::CaptureUsingOwnBuffers() {
+ DCHECK(thread_checker_.CalledOnValidThread());
const size_t frame_size =
VideoFrame::AllocationSize(VideoFrame::I420, capture_format_.frame_size);
memset(fake_frame_.get(), 0, frame_size);
- SkImageInfo info = SkImageInfo::MakeA8(capture_format_.frame_size.width(),
- capture_format_.frame_size.height());
- SkBitmap bitmap;
- bitmap.installPixels(info, fake_frame_.get(), info.width());
- SkCanvas canvas(bitmap);
-
- // Draw a sweeping circle to show an animation.
- int radius = std::min(capture_format_.frame_size.width(),
- capture_format_.frame_size.height()) / 4;
- SkRect rect =
- SkRect::MakeXYWH(capture_format_.frame_size.width() / 2 - radius,
- capture_format_.frame_size.height() / 2 - radius,
- 2 * radius,
- 2 * radius);
-
- SkPaint paint;
- paint.setStyle(SkPaint::kFill_Style);
-
- // Only Y plane is being drawn and this gives 50% grey on the Y
- // plane. The result is a light green color in RGB space.
- paint.setAlpha(128);
-
- int end_angle = (frame_count_ % kFakeCaptureBeepCycle * 360) /
- kFakeCaptureBeepCycle;
- if (!end_angle)
- end_angle = 360;
- canvas.drawArc(rect, 0, end_angle, true, paint);
-
- // Draw current time.
- int elapsed_ms = kFakeCaptureTimeoutMs * frame_count_;
- int milliseconds = elapsed_ms % 1000;
- int seconds = (elapsed_ms / 1000) % 60;
- int minutes = (elapsed_ms / 1000 / 60) % 60;
- int hours = (elapsed_ms / 1000 / 60 / 60) % 60;
-
- std::string time_string =
- base::StringPrintf("%d:%02d:%02d:%03d %d", hours, minutes,
- seconds, milliseconds, frame_count_);
- canvas.scale(3, 3);
- canvas.drawText(time_string.data(), time_string.length(), 30, 20,
- paint);
-
- if (frame_count_ % kFakeCaptureBeepCycle == 0) {
- // Generate a synchronized beep sound if there is one audio input
- // stream created.
- FakeAudioInputStream::BeepOnce();
- }
-
- frame_count_++;
+ DrawPacman(false /* use_argb */,
+ fake_frame_.get(),
+ frame_count_,
+ kFakeCapturePeriodMs,
+ capture_format_.frame_size);
// Give the captured frame to the client.
client_->OnIncomingCapturedData(fake_frame_.get(),
@@ -168,29 +147,68 @@ void FakeVideoCaptureDevice::OnCaptureTask() {
capture_format_,
0,
base::TimeTicks::Now());
- if (!(frame_count_ % kFakeCaptureCapabilityChangePeriod) &&
- format_roster_.size() > 0U) {
- Reallocate();
- }
- // Reschedule next CaptureTask.
- capture_thread_.message_loop()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&FakeVideoCaptureDevice::OnCaptureTask,
- base::Unretained(this)),
- base::TimeDelta::FromMilliseconds(kFakeCaptureTimeoutMs));
+ BeepAndScheduleNextCapture(
+ base::Bind(&FakeVideoCaptureDevice::CaptureUsingOwnBuffers,
+ weak_factory_.GetWeakPtr()));
}
-void FakeVideoCaptureDevice::Reallocate() {
- DCHECK_EQ(capture_thread_.message_loop(), base::MessageLoop::current());
- capture_format_ =
- format_roster_.at(++format_roster_index_ % format_roster_.size());
- DCHECK_EQ(capture_format_.pixel_format, PIXEL_FORMAT_I420);
- DVLOG(3) << "Reallocating FakeVideoCaptureDevice, new capture resolution "
- << capture_format_.frame_size.ToString();
+void FakeVideoCaptureDevice::CaptureUsingClientBuffers() {
+ DCHECK(thread_checker_.CalledOnValidThread());
- const size_t fake_frame_size =
- VideoFrame::AllocationSize(VideoFrame::I420, capture_format_.frame_size);
- fake_frame_.reset(new uint8[fake_frame_size]);
+ const scoped_refptr<VideoCaptureDevice::Client::Buffer> capture_buffer =
+ client_->ReserveOutputBuffer(VideoFrame::I420,
+ capture_format_.frame_size);
+ DLOG_IF(ERROR, !capture_buffer) << "Couldn't allocate Capture Buffer";
+ if (!capture_buffer)
+ return;
+
+ uint8_t* const data_ptr = static_cast<uint8_t*>(capture_buffer->data());
+ memset(data_ptr, 0, capture_buffer->size());
+ DCHECK(data_ptr) << "Buffer has NO backing memory";
+
+ DrawPacman(false /* use_argb */,
+ data_ptr,
+ frame_count_,
+ kFakeCapturePeriodMs,
+ capture_format_.frame_size);
+
+ scoped_refptr<VideoFrame> video_frame =
+ VideoFrame::WrapExternalPackedMemory(
+ VideoFrame::I420,
+ capture_format_.frame_size,
+ gfx::Rect(capture_format_.frame_size),
+ capture_format_.frame_size,
+ static_cast<uint8*>(capture_buffer->data()),
+ capture_buffer->size(),
+ base::SharedMemory::NULLHandle(),
+ 0,
+ base::TimeDelta(),
+ base::Closure());
+
+ // Give the captured frame to the client.
+ client_->OnIncomingCapturedVideoFrame(capture_buffer,
+ video_frame,
+ base::TimeTicks::Now());
+ BeepAndScheduleNextCapture(
+ base::Bind(&FakeVideoCaptureDevice::CaptureUsingClientBuffers,
+ weak_factory_.GetWeakPtr()));
+}
+
+void FakeVideoCaptureDevice::CaptureUsingGpuMemoryBuffers() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ NOTIMPLEMENTED();
+}
+
+void FakeVideoCaptureDevice::BeepAndScheduleNextCapture(
+ const base::Closure& next_capture) {
+ // Generate a synchronized beep sound every so many frames.
+ if (frame_count_++ % kFakeCaptureBeepCycle == 0)
+ FakeAudioInputStream::BeepOnce();
+
+ // Reschedule next CaptureTask.
+ base::MessageLoop::current()->PostDelayedTask(FROM_HERE, next_capture,
+ base::TimeDelta::FromMilliseconds(kFakeCapturePeriodMs));
}
} // namespace media
diff --git a/media/video/capture/fake_video_capture_device.h b/media/video/capture/fake_video_capture_device.h
index 30d1b33..e785ce6 100644
--- a/media/video/capture/fake_video_capture_device.h
+++ b/media/video/capture/fake_video_capture_device.h
@@ -12,6 +12,7 @@
#include "base/atomicops.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "base/threading/thread.h"
#include "base/threading/thread_checker.h"
#include "media/video/capture/video_capture_device.h"
@@ -20,46 +21,45 @@ namespace media {
class MEDIA_EXPORT FakeVideoCaptureDevice : public VideoCaptureDevice {
public:
- static const int kFakeCaptureTimeoutMs = 50;
+ enum FakeVideoCaptureDeviceType {
+ USING_OWN_BUFFERS,
+ USING_CLIENT_BUFFERS,
+ USING_GPU_MEMORY_BUFFERS,
+ };
- FakeVideoCaptureDevice();
+ static int FakeCapturePeriodMs() { return kFakeCapturePeriodMs; }
+
+ explicit FakeVideoCaptureDevice(FakeVideoCaptureDeviceType device_type);
~FakeVideoCaptureDevice() override;
// VideoCaptureDevice implementation.
void AllocateAndStart(const VideoCaptureParams& params,
- scoped_ptr<VideoCaptureDevice::Client> client) override;
+ scoped_ptr<Client> client) override;
void StopAndDeAllocate() override;
- // Sets the formats to use sequentially when the device is configured as
- // variable capture resolution. Works only before AllocateAndStart() or
- // after StopAndDeallocate().
- void PopulateVariableFormatsRoster(const VideoCaptureFormats& formats);
-
private:
- // Called on the |capture_thread_| only.
- void OnAllocateAndStart(const VideoCaptureParams& params,
- scoped_ptr<Client> client);
- void OnStopAndDeAllocate();
- void OnCaptureTask();
- void Reallocate();
-
- // |thread_checker_| is used to check that destructor, AllocateAndStart() and
- // StopAndDeAllocate() are called in the correct thread that owns the object.
+ static const int kFakeCapturePeriodMs = 50;
+
+ void CaptureUsingOwnBuffers();
+ void CaptureUsingClientBuffers();
+ void CaptureUsingGpuMemoryBuffers();
+ void BeepAndScheduleNextCapture(const base::Closure& next_capture);
+
+ // |thread_checker_| is used to check that all methods are called in the
+ // correct thread that owns the object.
base::ThreadChecker thread_checker_;
- base::Thread capture_thread_;
- // The following members are only used on the |capture_thread_|.
+ const FakeVideoCaptureDeviceType device_type_;
+
scoped_ptr<VideoCaptureDevice::Client> client_;
+ // |fake_frame_| is used for capturing on Own Buffers.
scoped_ptr<uint8[]> fake_frame_;
int frame_count_;
VideoCaptureFormat capture_format_;
- // When the device is allowed to change resolution, this vector holds the
- // available ones, used sequentially restarting at the end. These two members
- // are initialised in PopulateFormatRoster() before |capture_thread_| is
- // running and are subsequently read-only in that thread.
- std::vector<VideoCaptureFormat> format_roster_;
- int format_roster_index_;
+ // FakeVideoCaptureDevice post tasks to itself for frame construction and
+ // needs to deal with asynchronous StopAndDeallocate().
+ base::WeakPtrFactory<FakeVideoCaptureDevice> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(FakeVideoCaptureDevice);
};
diff --git a/media/video/capture/fake_video_capture_device_factory.cc b/media/video/capture/fake_video_capture_device_factory.cc
index a6cbd48..aea1909 100644
--- a/media/video/capture/fake_video_capture_device_factory.cc
+++ b/media/video/capture/fake_video_capture_device_factory.cc
@@ -4,7 +4,10 @@
#include "media/video/capture/fake_video_capture_device_factory.h"
+#include "base/command_line.h"
+#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
+#include "media/base/media_switches.h"
#include "media/video/capture/fake_video_capture_device.h"
namespace media {
@@ -16,10 +19,24 @@ FakeVideoCaptureDeviceFactory::FakeVideoCaptureDeviceFactory()
scoped_ptr<VideoCaptureDevice> FakeVideoCaptureDeviceFactory::Create(
const VideoCaptureDevice::Name& device_name) {
DCHECK(thread_checker_.CalledOnValidThread());
+
+ const std::string option = base::CommandLine::ForCurrentProcess()->
+ GetSwitchValueASCII(switches::kUseFakeDeviceForMediaStream);
+
+ FakeVideoCaptureDevice::FakeVideoCaptureDeviceType fake_vcd_type;
+ if (option.empty())
+ fake_vcd_type = FakeVideoCaptureDevice::USING_OWN_BUFFERS;
+ else if (base:: strcasecmp(option.c_str(), "gpu") == 0)
+ fake_vcd_type = FakeVideoCaptureDevice::USING_GPU_MEMORY_BUFFERS;
+ else
+ fake_vcd_type = FakeVideoCaptureDevice::USING_CLIENT_BUFFERS;
+
for (int n = 0; n < number_of_devices_; ++n) {
std::string possible_id = base::StringPrintf("/dev/video%d", n);
- if (device_name.id().compare(possible_id) == 0)
- return scoped_ptr<VideoCaptureDevice>(new FakeVideoCaptureDevice());
+ if (device_name.id().compare(possible_id) == 0) {
+ return scoped_ptr<VideoCaptureDevice>(
+ new FakeVideoCaptureDevice(fake_vcd_type));
+ }
}
return scoped_ptr<VideoCaptureDevice>();
}
@@ -49,7 +66,7 @@ void FakeVideoCaptureDeviceFactory::GetDeviceSupportedFormats(
const VideoCaptureDevice::Name& device,
VideoCaptureFormats* supported_formats) {
DCHECK(thread_checker_.CalledOnValidThread());
- const int frame_rate = 1000 / FakeVideoCaptureDevice::kFakeCaptureTimeoutMs;
+ const int frame_rate = 1000 / FakeVideoCaptureDevice::FakeCapturePeriodMs();
const gfx::Size supported_sizes[] = {gfx::Size(320, 240),
gfx::Size(640, 480),
gfx::Size(1280, 720),
diff --git a/media/video/capture/fake_video_capture_device_unittest.cc b/media/video/capture/fake_video_capture_device_unittest.cc
index 628708d..042fa7c 100644
--- a/media/video/capture/fake_video_capture_device_unittest.cc
+++ b/media/video/capture/fake_video_capture_device_unittest.cc
@@ -21,6 +21,33 @@ namespace media {
namespace {
+static const FakeVideoCaptureDevice::FakeVideoCaptureDeviceType
+kCaptureTypes[] = {
+ FakeVideoCaptureDevice::USING_OWN_BUFFERS,
+ FakeVideoCaptureDevice::USING_CLIENT_BUFFERS,
+ // TODO(mcasas): Add FakeVideoCaptureDevice::USING_GPU_MEMORY_BUFFERS when
+ // implemented.
+};
+
+// This class is a Client::Buffer that allocates and frees the requested |size|.
+class MockBuffer : public VideoCaptureDevice::Client::Buffer {
+ public:
+ MockBuffer(int buffer_id, size_t size)
+ : id_(buffer_id),
+ size_(size),
+ data_(new uint8[size_]) {}
+ int id() const override { return id_; }
+ void* data() const override { return static_cast<void*>(data_); }
+ size_t size() const override { return size_; }
+
+ private:
+ ~MockBuffer() override { delete[] data_; }
+
+ const int id_;
+ const size_t size_;
+ uint8* const data_;
+};
+
class MockClient : public VideoCaptureDevice::Client {
public:
MOCK_METHOD9(OnIncomingCapturedYuvData,
@@ -33,28 +60,37 @@ class MockClient : public VideoCaptureDevice::Client {
const VideoCaptureFormat& frame_format,
int clockwise_rotation,
const base::TimeTicks& timestamp));
- MOCK_METHOD2(ReserveOutputBuffer,
- scoped_refptr<Buffer>(VideoFrame::Format format,
- const gfx::Size& dimensions));
- MOCK_METHOD3(OnIncomingCapturedVideoFrame,
- void(const scoped_refptr<Buffer>& buffer,
- const scoped_refptr<media::VideoFrame>& frame,
- const base::TimeTicks& timestamp));
MOCK_METHOD1(OnError, void(const std::string& reason));
explicit MockClient(base::Callback<void(const VideoCaptureFormat&)> frame_cb)
- : main_thread_(base::MessageLoopProxy::current()), frame_cb_(frame_cb) {}
+ : frame_cb_(frame_cb) {}
+ // Client virtual method for capturing using Device Buffers.
void OnIncomingCapturedData(const uint8* data,
int length,
const VideoCaptureFormat& format,
int rotation,
- const base::TimeTicks& timestamp) override {
- main_thread_->PostTask(FROM_HERE, base::Bind(frame_cb_, format));
+ const base::TimeTicks& timestamp) {
+ frame_cb_.Run(format);
+ }
+
+ // Virtual methods for capturing using Client's Buffers.
+ scoped_refptr<Buffer> ReserveOutputBuffer(VideoFrame::Format format,
+ const gfx::Size& dimensions) {
+ EXPECT_EQ(format, VideoFrame::I420);
+ EXPECT_GT(dimensions.GetArea(), 0);
+ return make_scoped_refptr(
+ new MockBuffer(0, VideoFrame::AllocationSize(format, dimensions)));
+ }
+ void OnIncomingCapturedVideoFrame(
+ const scoped_refptr<Buffer>& buffer,
+ const scoped_refptr<media::VideoFrame>& frame,
+ const base::TimeTicks& timestamp) {
+ VideoCaptureFormat format(frame->natural_size(), 30.0, PIXEL_FORMAT_I420);
+ frame_cb_.Run(format);
}
private:
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
base::Callback<void(const VideoCaptureFormat&)> frame_cb_;
};
@@ -76,10 +112,10 @@ class DeviceEnumerationListener :
} // namespace
-class FakeVideoCaptureDeviceTest : public testing::Test {
+class FakeVideoCaptureDeviceTest
+ : public testing::TestWithParam<
+ FakeVideoCaptureDevice::FakeVideoCaptureDeviceType>{
protected:
- typedef VideoCaptureDevice::Client Client;
-
FakeVideoCaptureDeviceTest()
: loop_(new base::MessageLoop()),
client_(new MockClient(
@@ -92,8 +128,7 @@ class FakeVideoCaptureDeviceTest : public testing::Test {
void SetUp() override {
EXPECT_CALL(*client_, OnIncomingCapturedYuvData(_,_,_,_,_,_,_,_,_))
.Times(0);
- EXPECT_CALL(*client_, ReserveOutputBuffer(_,_)).Times(0);
- EXPECT_CALL(*client_, OnIncomingCapturedVideoFrame(_,_,_)).Times(0);
+ EXPECT_CALL(*client_, OnError(_)).Times(0);
}
void OnFrameCaptured(const VideoCaptureFormat& format) {
@@ -121,37 +156,38 @@ class FakeVideoCaptureDeviceTest : public testing::Test {
const VideoCaptureFormat& last_format() const { return last_format_; }
VideoCaptureDevice::Names names_;
- scoped_ptr<base::MessageLoop> loop_;
+ const scoped_ptr<base::MessageLoop> loop_;
scoped_ptr<base::RunLoop> run_loop_;
scoped_ptr<MockClient> client_;
scoped_refptr<DeviceEnumerationListener> device_enumeration_listener_;
VideoCaptureFormat last_format_;
- scoped_ptr<VideoCaptureDeviceFactory> video_capture_device_factory_;
+ const scoped_ptr<VideoCaptureDeviceFactory> video_capture_device_factory_;
};
-TEST_F(FakeVideoCaptureDeviceTest, Capture) {
- scoped_ptr<VideoCaptureDevice::Names> names(EnumerateDevices());
-
+TEST_P(FakeVideoCaptureDeviceTest, CaptureUsing) {
+ const scoped_ptr<VideoCaptureDevice::Names> names(EnumerateDevices());
ASSERT_FALSE(names->empty());
- scoped_ptr<VideoCaptureDevice> device(
- video_capture_device_factory_->Create(names->front()));
+ scoped_ptr<VideoCaptureDevice> device(new FakeVideoCaptureDevice(GetParam()));
ASSERT_TRUE(device);
- EXPECT_CALL(*client_, OnError(_)).Times(0);
-
VideoCaptureParams capture_params;
capture_params.requested_format.frame_size.SetSize(640, 480);
capture_params.requested_format.frame_rate = 30;
capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420;
device->AllocateAndStart(capture_params, client_.Pass());
+
WaitForCapturedFrame();
EXPECT_EQ(last_format().frame_size.width(), 640);
EXPECT_EQ(last_format().frame_size.height(), 480);
- EXPECT_EQ(last_format().frame_rate, 30);
+ EXPECT_EQ(last_format().frame_rate, 30.0);
device->StopAndDeAllocate();
}
+INSTANTIATE_TEST_CASE_P(,
+ FakeVideoCaptureDeviceTest,
+ testing::ValuesIn(kCaptureTypes));
+
TEST_F(FakeVideoCaptureDeviceTest, GetDeviceSupportedFormats) {
scoped_ptr<VideoCaptureDevice::Names> names(EnumerateDevices());
@@ -164,57 +200,20 @@ TEST_F(FakeVideoCaptureDeviceTest, GetDeviceSupportedFormats) {
EXPECT_EQ(supported_formats[0].frame_size.width(), 320);
EXPECT_EQ(supported_formats[0].frame_size.height(), 240);
EXPECT_EQ(supported_formats[0].pixel_format, PIXEL_FORMAT_I420);
- EXPECT_GE(supported_formats[0].frame_rate, 20);
+ EXPECT_GE(supported_formats[0].frame_rate, 20.0);
EXPECT_EQ(supported_formats[1].frame_size.width(), 640);
EXPECT_EQ(supported_formats[1].frame_size.height(), 480);
EXPECT_EQ(supported_formats[1].pixel_format, PIXEL_FORMAT_I420);
- EXPECT_GE(supported_formats[1].frame_rate, 20);
+ EXPECT_GE(supported_formats[1].frame_rate, 20.0);
EXPECT_EQ(supported_formats[2].frame_size.width(), 1280);
EXPECT_EQ(supported_formats[2].frame_size.height(), 720);
EXPECT_EQ(supported_formats[2].pixel_format, PIXEL_FORMAT_I420);
- EXPECT_GE(supported_formats[2].frame_rate, 20);
+ EXPECT_GE(supported_formats[2].frame_rate, 20.0);
EXPECT_EQ(supported_formats[3].frame_size.width(), 1920);
EXPECT_EQ(supported_formats[3].frame_size.height(), 1080);
EXPECT_EQ(supported_formats[3].pixel_format, PIXEL_FORMAT_I420);
- EXPECT_GE(supported_formats[3].frame_rate, 20);
- }
-}
-
-// Disabled, http://crbug.com/407061 .
-TEST_F(FakeVideoCaptureDeviceTest, DISABLED_CaptureVariableResolution) {
- scoped_ptr<VideoCaptureDevice::Names> names(EnumerateDevices());
-
- VideoCaptureParams capture_params;
- capture_params.requested_format.frame_size.SetSize(640, 480);
- capture_params.requested_format.frame_rate = 30;
- capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420;
- capture_params.resolution_change_policy =
- RESOLUTION_POLICY_DYNAMIC_WITHIN_LIMIT;
-
- ASSERT_FALSE(names->empty());
-
- scoped_ptr<VideoCaptureDevice> device(
- video_capture_device_factory_->Create(names->front()));
- ASSERT_TRUE(device);
-
- // Configure the FakeVideoCaptureDevice to use all its formats as roster.
- VideoCaptureFormats formats;
- video_capture_device_factory_->GetDeviceSupportedFormats(names->front(),
- &formats);
- static_cast<FakeVideoCaptureDevice*>(device.get())->
- PopulateVariableFormatsRoster(formats);
-
- EXPECT_CALL(*client_, OnError(_)).Times(0);
- int action_count = 200;
-
- device->AllocateAndStart(capture_params, client_.Pass());
-
- // We set TimeWait to 200 action timeouts and this should be enough for at
- // least action_count/kFakeCaptureCapabilityChangePeriod calls.
- for (int i = 0; i < action_count; ++i) {
- WaitForCapturedFrame();
+ EXPECT_GE(supported_formats[3].frame_rate, 20.0);
}
- device->StopAndDeAllocate();
}
}; // namespace media