| Index: content/browser/renderer_host/media/video_capture_controller_unittest.cc
|
| diff --git a/content/browser/renderer_host/media/video_capture_controller_unittest.cc b/content/browser/renderer_host/media/video_capture_controller_unittest.cc
|
| index 1852a71fe8a3d61f828453a9cebe97fbff30c621..6bc262abc5b76604c9f195ae520ea8814f3a7856 100644
|
| --- a/content/browser/renderer_host/media/video_capture_controller_unittest.cc
|
| +++ b/content/browser/renderer_host/media/video_capture_controller_unittest.cc
|
| @@ -18,7 +18,7 @@
|
| #include "content/browser/renderer_host/media/video_capture_manager.h"
|
| #include "content/common/media/media_stream_options.h"
|
| #include "content/public/test/test_browser_thread_bundle.h"
|
| -#include "media/base/video_frame.h"
|
| +#include "gpu/command_buffer/common/mailbox_holder.h"
|
| #include "media/base/video_util.h"
|
| #include "media/video/capture/video_capture_types.h"
|
| #include "testing/gmock/include/gmock/gmock.h"
|
| @@ -42,6 +42,7 @@ class MockVideoCaptureControllerEventHandler
|
| MOCK_METHOD1(DoBufferCreated, void(const VideoCaptureControllerID&));
|
| MOCK_METHOD1(DoBufferDestroyed, void(const VideoCaptureControllerID&));
|
| MOCK_METHOD1(DoBufferReady, void(const VideoCaptureControllerID&));
|
| + MOCK_METHOD1(DoMailboxBufferReady, void(const VideoCaptureControllerID&));
|
| MOCK_METHOD1(DoEnded, void(const VideoCaptureControllerID&));
|
| MOCK_METHOD1(DoError, void(const VideoCaptureControllerID&));
|
|
|
| @@ -59,12 +60,34 @@ class MockVideoCaptureControllerEventHandler
|
| }
|
| virtual void OnBufferReady(const VideoCaptureControllerID& id,
|
| int buffer_id,
|
| - base::TimeTicks timestamp,
|
| - const media::VideoCaptureFormat& format) OVERRIDE {
|
| + const media::VideoCaptureFormat& format,
|
| + base::TimeTicks timestamp) OVERRIDE {
|
| DoBufferReady(id);
|
| - base::MessageLoop::current()->PostTask(FROM_HERE,
|
| + base::MessageLoop::current()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&VideoCaptureController::ReturnBuffer,
|
| + base::Unretained(controller_),
|
| + id,
|
| + this,
|
| + buffer_id,
|
| + 0));
|
| + }
|
| + virtual void OnMailboxBufferReady(const VideoCaptureControllerID& id,
|
| + int buffer_id,
|
| + const gpu::MailboxHolder& mailbox_holder,
|
| + const media::VideoCaptureFormat& format,
|
| + base::TimeTicks timestamp) OVERRIDE {
|
| + DoMailboxBufferReady(id);
|
| + // Use a very different syncpoint value when returning a new syncpoint.
|
| + const uint32 new_sync_point = ~mailbox_holder.sync_point;
|
| + base::MessageLoop::current()->PostTask(
|
| + FROM_HERE,
|
| base::Bind(&VideoCaptureController::ReturnBuffer,
|
| - base::Unretained(controller_), id, this, buffer_id));
|
| + base::Unretained(controller_),
|
| + id,
|
| + this,
|
| + buffer_id,
|
| + new_sync_point));
|
| }
|
| virtual void OnEnded(const VideoCaptureControllerID& id) OVERRIDE {
|
| DoEnded(id);
|
| @@ -99,7 +122,37 @@ class VideoCaptureControllerTest : public testing::Test {
|
| base::RunLoop().RunUntilIdle();
|
| }
|
|
|
| - TestBrowserThreadBundle bindle_;
|
| + scoped_refptr<media::VideoFrame> WrapI420Buffer(
|
| + const scoped_refptr<media::VideoCaptureDevice::Client::Buffer>& buffer,
|
| + gfx::Size dimensions) {
|
| + return media::VideoFrame::WrapExternalPackedMemory(
|
| + media::VideoFrame::I420,
|
| + dimensions,
|
| + gfx::Rect(dimensions),
|
| + dimensions,
|
| + reinterpret_cast<uint8*>(buffer->data()),
|
| + media::VideoFrame::AllocationSize(media::VideoFrame::I420, dimensions),
|
| + base::SharedMemory::NULLHandle(),
|
| + base::TimeDelta(),
|
| + base::Closure());
|
| + }
|
| +
|
| + scoped_refptr<media::VideoFrame> WrapMailboxBuffer(
|
| + const scoped_refptr<media::VideoCaptureDevice::Client::Buffer>& buffer,
|
| + scoped_ptr<gpu::MailboxHolder> holder,
|
| + const media::VideoFrame::ReleaseMailboxCB& release_cb,
|
| + gfx::Size dimensions) {
|
| + return media::VideoFrame::WrapNativeTexture(
|
| + holder.Pass(),
|
| + release_cb,
|
| + dimensions,
|
| + gfx::Rect(dimensions),
|
| + dimensions,
|
| + base::TimeDelta(),
|
| + media::VideoFrame::ReadPixelsCB());
|
| + }
|
| +
|
| + TestBrowserThreadBundle bundle_;
|
| scoped_ptr<MockVideoCaptureControllerEventHandler> client_a_;
|
| scoped_ptr<MockVideoCaptureControllerEventHandler> client_b_;
|
| scoped_ptr<VideoCaptureController> controller_;
|
| @@ -209,6 +262,11 @@ TEST_F(VideoCaptureControllerTest, AddAndRemoveClients) {
|
| << "Client count should return to zero after all clients are gone.";
|
| }
|
|
|
| +static void CacheSyncPoint(uint32* sync_value,
|
| + const gpu::MailboxHolder* mailbox_holder) {
|
| + *sync_value = mailbox_holder->sync_point;
|
| +}
|
| +
|
| // This test will connect and disconnect several clients while simulating an
|
| // active capture device being started and generating frames. It runs on one
|
| // thread and is intended to behave deterministically.
|
| @@ -276,11 +334,13 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
|
| EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2)).Times(1);
|
| EXPECT_CALL(*client_a_, DoBufferReady(client_a_route_2)).Times(1);
|
| }
|
| - device_->OnIncomingCapturedBuffer(buffer,
|
| - media::VideoFrame::I420,
|
| - capture_resolution,
|
| - base::TimeTicks(),
|
| - device_format.frame_rate);
|
| + device_->OnIncomingCapturedVideoFrame(
|
| + buffer,
|
| + media::VideoCaptureFormat(capture_resolution,
|
| + device_format.frame_rate,
|
| + media::PIXEL_FORMAT_I420),
|
| + WrapI420Buffer(buffer, capture_resolution),
|
| + base::TimeTicks());
|
| buffer = NULL;
|
|
|
| base::RunLoop().RunUntilIdle();
|
| @@ -294,11 +354,13 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
|
| device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
|
| ASSERT_TRUE(buffer);
|
| memset(buffer->data(), buffer_no++, buffer->size());
|
| - device_->OnIncomingCapturedBuffer(buffer,
|
| - media::VideoFrame::I420,
|
| - capture_resolution,
|
| - base::TimeTicks(),
|
| - device_format.frame_rate);
|
| + device_->OnIncomingCapturedVideoFrame(
|
| + buffer,
|
| + media::VideoCaptureFormat(capture_resolution,
|
| + device_format.frame_rate,
|
| + media::PIXEL_FORMAT_I420),
|
| + WrapI420Buffer(buffer, capture_resolution),
|
| + base::TimeTicks());
|
| buffer = NULL;
|
|
|
| // The buffer should be delivered to the clients in any order.
|
| @@ -323,11 +385,13 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
|
| capture_resolution);
|
| ASSERT_TRUE(buffer);
|
| memset(buffer->data(), buffer_no++, buffer->size());
|
| - device_->OnIncomingCapturedBuffer(buffer,
|
| - media::VideoFrame::I420,
|
| - capture_resolution,
|
| - base::TimeTicks(),
|
| - device_format.frame_rate);
|
| + device_->OnIncomingCapturedVideoFrame(
|
| + buffer,
|
| + media::VideoCaptureFormat(capture_resolution,
|
| + device_format.frame_rate,
|
| + media::PIXEL_FORMAT_I420),
|
| + WrapI420Buffer(buffer, capture_resolution),
|
| + base::TimeTicks());
|
| buffer = NULL;
|
| }
|
| // ReserveOutputBuffer ought to fail now, because the pool is depleted.
|
| @@ -361,11 +425,13 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
|
| device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
|
| ASSERT_TRUE(buffer);
|
| memset(buffer->data(), buffer_no++, buffer->size());
|
| - device_->OnIncomingCapturedBuffer(buffer,
|
| - media::VideoFrame::I420,
|
| - capture_resolution,
|
| - base::TimeTicks(),
|
| - device_format.frame_rate);
|
| + device_->OnIncomingCapturedVideoFrame(
|
| + buffer,
|
| + media::VideoCaptureFormat(capture_resolution,
|
| + device_format.frame_rate,
|
| + media::PIXEL_FORMAT_I420),
|
| + WrapI420Buffer(buffer, capture_resolution),
|
| + base::TimeTicks());
|
| buffer = NULL;
|
| buffer =
|
| device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
|
| @@ -377,11 +443,13 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
|
| }
|
| ASSERT_TRUE(buffer);
|
| memset(buffer->data(), buffer_no++, buffer->size());
|
| - device_->OnIncomingCapturedBuffer(buffer,
|
| - media::VideoFrame::I420,
|
| - capture_resolution,
|
| - base::TimeTicks(),
|
| - device_format.frame_rate);
|
| + device_->OnIncomingCapturedVideoFrame(
|
| + buffer,
|
| + media::VideoCaptureFormat(capture_resolution,
|
| + device_format.frame_rate,
|
| + media::PIXEL_FORMAT_I420),
|
| + WrapI420Buffer(buffer, capture_resolution),
|
| + base::TimeTicks());
|
| buffer = NULL;
|
| // B2 is the only client left, and is the only one that should
|
| // get the buffer.
|
| @@ -389,6 +457,65 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
|
| base::RunLoop().RunUntilIdle();
|
| Mock::VerifyAndClearExpectations(client_a_.get());
|
| Mock::VerifyAndClearExpectations(client_b_.get());
|
| +
|
| + // Allocate all buffers from the buffer pool, half as SHM buffer and half as
|
| + // mailbox buffers. Make sure of different counts though.
|
| + int shm_buffers = kPoolSize / 2;
|
| + int mailbox_buffers = kPoolSize - shm_buffers;
|
| + if (shm_buffers == mailbox_buffers) {
|
| + shm_buffers--;
|
| + mailbox_buffers++;
|
| + }
|
| +
|
| + for (int i = 0; i < shm_buffers; ++i) {
|
| + buffer = device_->ReserveOutputBuffer(media::VideoFrame::I420,
|
| + capture_resolution);
|
| + ASSERT_TRUE(buffer);
|
| + device_->OnIncomingCapturedVideoFrame(
|
| + buffer,
|
| + media::VideoCaptureFormat(capture_resolution,
|
| + device_format.frame_rate,
|
| + media::PIXEL_FORMAT_I420),
|
| + WrapI420Buffer(buffer, capture_resolution),
|
| + base::TimeTicks());
|
| + buffer = NULL;
|
| + }
|
| + std::vector<uint32> mailbox_syncpoints(mailbox_buffers);
|
| + std::vector<uint32> mailbox_syncpoints_new(mailbox_buffers);
|
| + for (int i = 0; i < mailbox_buffers; ++i) {
|
| + buffer = device_->ReserveOutputBuffer(media::VideoFrame::NATIVE_TEXTURE,
|
| + gfx::Size(0, 0));
|
| + ASSERT_TRUE(buffer);
|
| + mailbox_syncpoints[i] = i;
|
| + device_->OnIncomingCapturedVideoFrame(
|
| + buffer,
|
| + media::VideoCaptureFormat(capture_resolution,
|
| + device_format.frame_rate,
|
| + media::PIXEL_FORMAT_TEXTURE),
|
| + WrapMailboxBuffer(
|
| + buffer,
|
| + make_scoped_ptr(new gpu::MailboxHolder(
|
| + gpu::Mailbox(), 0, mailbox_syncpoints[i])),
|
| + base::Bind(&CacheSyncPoint, &mailbox_syncpoints_new[i]),
|
| + capture_resolution),
|
| + base::TimeTicks());
|
| + buffer = NULL;
|
| + }
|
| + // ReserveOutputBuffers ought to fail now regardless of buffer format, because
|
| + // the pool is depleted.
|
| + ASSERT_FALSE(device_->ReserveOutputBuffer(media::VideoFrame::I420,
|
| + capture_resolution));
|
| + ASSERT_FALSE(device_->ReserveOutputBuffer(media::VideoFrame::NATIVE_TEXTURE,
|
| + gfx::Size(0, 0)));
|
| + EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2)).Times(shm_buffers);
|
| + EXPECT_CALL(*client_b_, DoMailboxBufferReady(client_b_route_2))
|
| + .Times(mailbox_buffers);
|
| + base::RunLoop().RunUntilIdle();
|
| + for (size_t i = 0; i < mailbox_syncpoints.size(); ++i) {
|
| + // See: MockVideoCaptureControllerEventHandler::OnMailboxBufferReady()
|
| + ASSERT_EQ(mailbox_syncpoints[i], ~mailbox_syncpoints_new[i]);
|
| + }
|
| + Mock::VerifyAndClearExpectations(client_b_.get());
|
| }
|
|
|
| // Exercises the OnError() codepath of VideoCaptureController, and tests the
|
| @@ -424,11 +551,12 @@ TEST_F(VideoCaptureControllerTest, ErrorBeforeDeviceCreation) {
|
| device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
|
| ASSERT_TRUE(buffer);
|
|
|
| - device_->OnIncomingCapturedBuffer(buffer,
|
| - media::VideoFrame::I420,
|
| - capture_resolution,
|
| - base::TimeTicks(),
|
| - 30);
|
| + device_->OnIncomingCapturedVideoFrame(
|
| + buffer,
|
| + media::VideoCaptureFormat(
|
| + capture_resolution, 30, media::PIXEL_FORMAT_I420),
|
| + WrapI420Buffer(buffer, capture_resolution),
|
| + base::TimeTicks());
|
| buffer = NULL;
|
|
|
| base::RunLoop().RunUntilIdle();
|
| @@ -463,11 +591,12 @@ TEST_F(VideoCaptureControllerTest, ErrorAfterDeviceCreation) {
|
| ASSERT_TRUE(buffer);
|
|
|
| device_->OnError();
|
| - device_->OnIncomingCapturedBuffer(buffer,
|
| - media::VideoFrame::I420,
|
| - dims,
|
| - base::TimeTicks(),
|
| - device_format.frame_rate);
|
| + device_->OnIncomingCapturedVideoFrame(
|
| + buffer,
|
| + media::VideoCaptureFormat(
|
| + dims, device_format.frame_rate, media::PIXEL_FORMAT_I420),
|
| + WrapI420Buffer(buffer, dims),
|
| + base::TimeTicks());
|
| buffer = NULL;
|
|
|
| EXPECT_CALL(*client_a_, DoError(route_id)).Times(1);
|
|
|