15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/command_line.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/files/scoped_file.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
139ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/run_loop.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/browser_thread_impl.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/media/media_stream_manager.h"
194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/browser/renderer_host/media/media_stream_requester.h"
204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/media/video_capture_host.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/media/video_capture_manager.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/media/video_capture_messages.h"
245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "content/public/common/content_switches.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/mock_resource_context.h"
26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/test/test_browser_context.h"
27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "content/public/test/test_browser_thread_bundle.h"
28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/test/test_content_browser_client.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_manager.h"
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "media/base/media_switches.h"
31424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "media/base/video_frame.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/video/capture/video_capture_types.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_context.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::_;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::AtLeast;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::AnyNumber;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::DoAll;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::InSequence;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Mock;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Return;
444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)using ::testing::SaveArg;
454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)using ::testing::StrictMock;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Id used to identify the capture session between renderer and
50d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// video_capture_host. This is an arbitrary value.
51d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)static const int kDeviceId = 555;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Define to enable test where video is dumped to file.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// #define DUMP_VIDEO
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Define to use a real video capture device.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// #define TEST_REAL_CAPTURE_DEVICE
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Simple class used for dumping video to a file. This can be used for
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// verifying the output.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DumpVideo {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DumpVideo() : expected_size_(0) {}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartDump(int width, int height) {
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath file_name = base::FilePath(base::StringPrintf(
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FILE_PATH_LITERAL("dump_w%d_h%d.yuv"), width, height));
67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    file_.reset(base::OpenFile(file_name, "wb"));
68424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    expected_size_ = media::VideoFrame::AllocationSize(
69424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        media::VideoFrame::I420, gfx::Size(width, height));
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void NewVideoFrame(const void* buffer) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (file_.get() != NULL) {
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      ASSERT_EQ(1U, fwrite(buffer, expected_size_, 1, file_.get()));
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::ScopedFILE file_;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int expected_size_;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)class MockMediaStreamRequester : public MediaStreamRequester {
834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public:
844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  MockMediaStreamRequester() {}
854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual ~MockMediaStreamRequester() {}
864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // MediaStreamRequester implementation.
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MOCK_METHOD5(StreamGenerated,
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               void(int render_view_id,
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    int page_request_id,
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    const std::string& label,
924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                    const StreamDeviceInfoArray& audio_devices,
934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                    const StreamDeviceInfoArray& video_devices));
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MOCK_METHOD3(StreamGenerationFailed,
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      void(int render_view_id,
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)           int page_request_id,
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)           content::MediaStreamRequestResult result));
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  MOCK_METHOD3(DeviceStopped, void(int render_view_id,
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                   const std::string& label,
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                   const StreamDeviceInfo& device));
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MOCK_METHOD4(DevicesEnumerated, void(int render_view_id,
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                       int page_request_id,
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                       const std::string& label,
1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                       const StreamDeviceInfoArray& devices));
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MOCK_METHOD4(DeviceOpened, void(int render_view_id,
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  int page_request_id,
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  const std::string& label,
1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                  const StreamDeviceInfo& device_info));
1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private:
1114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MockMediaStreamRequester);
1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockVideoCaptureHost : public VideoCaptureHost {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockVideoCaptureHost(MediaStreamManager* manager)
117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      : VideoCaptureHost(manager),
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return_buffers_(false),
119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        dump_video_(false) {}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A list of mock methods.
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MOCK_METHOD4(OnNewBufferCreated,
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)               void(int device_id,
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    base::SharedMemoryHandle handle,
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    int length,
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    int buffer_id));
1271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  MOCK_METHOD2(OnBufferFreed,
1281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)               void(int device_id, int buffer_id));
1291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  MOCK_METHOD4(OnBufferFilled,
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               void(int device_id,
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    int buffer_id,
132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    const media::VideoCaptureFormat& format,
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    base::TimeTicks timestamp));
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MOCK_METHOD5(OnMailboxBufferFilled,
135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)               void(int device_id,
136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    int buffer_id,
137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    const gpu::MailboxHolder& mailbox_holder,
138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    const media::VideoCaptureFormat& format,
139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    base::TimeTicks timestamp));
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MOCK_METHOD2(OnStateChanged, void(int device_id, VideoCaptureState state));
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use class DumpVideo to write I420 video to file.
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetDumpVideo(bool enable) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dump_video_ = enable;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void SetReturnReceivedDibs(bool enable) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return_buffers_ = enable;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return Dibs we currently have received.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ReturnReceivedDibs(int device_id)  {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int handle = GetReceivedDib();
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (handle) {
1555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      this->OnReceiveEmptyBuffer(device_id, handle, std::vector<uint32>());
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      handle = GetReceivedDib();
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int GetReceivedDib() {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (filled_dib_.empty())
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 0;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::map<int, base::SharedMemory*>::iterator it = filled_dib_.begin();
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int h = it->first;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete it->second;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    filled_dib_.erase(it);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return h;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MockVideoCaptureHost() {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STLDeleteContainerPairSecondPointers(filled_dib_.begin(),
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         filled_dib_.end());
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This method is used to dispatch IPC messages to the renderer. We intercept
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // these messages here and dispatch to our mock methods to verify the
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // conversation between this object and the renderer.
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool Send(IPC::Message* message) OVERRIDE {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(message);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In this method we dispatch the messages to the according handlers as if
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we are the renderer.
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool handled = true;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_BEGIN_MESSAGE_MAP(MockVideoCaptureHost, *message)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IPC_MESSAGE_HANDLER(VideoCaptureMsg_NewBuffer, OnNewBufferCreatedDispatch)
1881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      IPC_MESSAGE_HANDLER(VideoCaptureMsg_FreeBuffer, OnBufferFreedDispatch)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IPC_MESSAGE_HANDLER(VideoCaptureMsg_BufferReady, OnBufferFilledDispatch)
190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      IPC_MESSAGE_HANDLER(VideoCaptureMsg_MailboxBufferReady,
191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                          OnMailboxBufferFilledDispatch)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IPC_MESSAGE_HANDLER(VideoCaptureMsg_StateChanged, OnStateChangedDispatch)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IPC_MESSAGE_UNHANDLED(handled = false)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_END_MESSAGE_MAP()
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(handled);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete message;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These handler methods do minimal things and delegate to the mock methods.
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnNewBufferCreatedDispatch(int device_id,
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  base::SharedMemoryHandle handle,
204424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                  uint32 length,
205424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                  int buffer_id) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnNewBufferCreated(device_id, handle, length, buffer_id);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SharedMemory* dib = new base::SharedMemory(handle, false);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dib->Map(length);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    filled_dib_[buffer_id] = dib;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void OnBufferFreedDispatch(int device_id, int buffer_id) {
2131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    OnBufferFreed(device_id, buffer_id);
2141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    std::map<int, base::SharedMemory*>::iterator it =
2161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        filled_dib_.find(buffer_id);
2171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    ASSERT_TRUE(it != filled_dib_.end());
2181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    delete it->second;
2191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    filled_dib_.erase(it);
2201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
2211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void OnBufferFilledDispatch(int device_id,
2231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                              int buffer_id,
224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                              const media::VideoCaptureFormat& frame_format,
225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                              base::TimeTicks timestamp) {
2261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    base::SharedMemory* dib = filled_dib_[buffer_id];
2271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    ASSERT_TRUE(dib != NULL);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dump_video_) {
2291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      if (!format_.IsValid()) {
230f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        dumper_.StartDump(frame_format.frame_size.width(),
231f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                          frame_format.frame_size.height());
2321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        format_ = frame_format;
2331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      }
234f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      ASSERT_EQ(format_.frame_size.width(), frame_format.frame_size.width())
235f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          << "Dump format does not handle variable resolution.";
236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      ASSERT_EQ(format_.frame_size.height(), frame_format.frame_size.height())
2371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          << "Dump format does not handle variable resolution.";
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dumper_.NewVideoFrame(dib->memory());
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    OnBufferFilled(device_id, buffer_id, frame_format, timestamp);
242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (return_buffers_) {
2435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      VideoCaptureHost::OnReceiveEmptyBuffer(
2445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          device_id, buffer_id, std::vector<uint32>());
245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
247a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void OnMailboxBufferFilledDispatch(int device_id,
249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     int buffer_id,
250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     const gpu::MailboxHolder& mailbox_holder,
251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     const media::VideoCaptureFormat& format,
252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     base::TimeTicks timestamp) {
253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    OnMailboxBufferFilled(
254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        device_id, buffer_id, mailbox_holder, format, timestamp);
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (return_buffers_) {
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      VideoCaptureHost::OnReceiveEmptyBuffer(
2575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          device_id, buffer_id, std::vector<uint32>());
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnStateChangedDispatch(int device_id, VideoCaptureState state) {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnStateChanged(device_id, state);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<int, base::SharedMemory*> filled_dib_;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool return_buffers_;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool dump_video_;
2681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  media::VideoCaptureFormat format_;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DumpVideo dumper_;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochACTION_P2(ExitMessageLoop, message_loop, quit_closure) {
273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  message_loop->PostTask(FROM_HERE, quit_closure);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// This is an integration test of VideoCaptureHost in conjunction with
2774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// MediaStreamManager, VideoCaptureManager, VideoCaptureController, and
2784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// VideoCaptureDevice.
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VideoCaptureHostTest : public testing::Test {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  VideoCaptureHostTest()
282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
2834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        message_loop_(base::MessageLoopProxy::current()),
2844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        opened_session_id_(kInvalidMediaCaptureSessionId) {}
2854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual void SetUp() OVERRIDE {
287a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    SetBrowserClientForTesting(&browser_client_);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create our own MediaStreamManager.
289a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    audio_manager_.reset(media::AudioManager::CreateForTesting());
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef TEST_REAL_CAPTURE_DEVICE
2915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    base::CommandLine::ForCurrentProcess()->AppendSwitch(
2925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        switches::kUseFakeDeviceForMediaStream);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
2954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    media_stream_manager_->UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy>());
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Create a Host and connect it to a simulated IPC channel.
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host_ = new MockVideoCaptureHost(media_stream_manager_.get());
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host_->OnChannelConnected(base::GetCurrentProcId());
3004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    OpenSession();
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual void TearDown() OVERRIDE {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verifies and removes the expectations on host_ and
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // returns true iff successful.
307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    Mock::VerifyAndClearExpectations(host_.get());
3084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(0u, host_->entries_.size());
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CloseSession();
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Simulate closing the IPC sender.
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host_->OnChannelClosing();
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Release the reference to the mock object. The object will be destructed
316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // on the current message loop.
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host_ = NULL;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void OpenSession() {
3214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const int render_process_id = 1;
3224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const int render_view_id = 1;
3234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const int page_request_id = 1;
324a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const GURL security_origin("http://test.com");
3254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ASSERT_TRUE(opened_device_label_.empty());
3274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Enumerate video devices.
3294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    StreamDeviceInfoArray devices;
3304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    {
3314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::RunLoop run_loop;
3324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      std::string label = media_stream_manager_->EnumerateDevices(
3334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          &stream_requester_,
3344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          render_process_id,
3354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          render_view_id,
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
3374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          page_request_id,
3384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          MEDIA_DEVICE_VIDEO_CAPTURE,
33946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          security_origin,
34046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          true);
3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_CALL(stream_requester_, DevicesEnumerated(render_view_id,
3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                       page_request_id,
3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                       label,
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                       _))
3454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          .Times(1).WillOnce(
3464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)              DoAll(ExitMessageLoop(message_loop_, run_loop.QuitClosure()),
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    SaveArg<3>(&devices)));
3484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      run_loop.Run();
3494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      Mock::VerifyAndClearExpectations(&stream_requester_);
3504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      media_stream_manager_->CancelRequest(label);
3514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
3524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ASSERT_FALSE(devices.empty());
3534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ASSERT_EQ(StreamDeviceInfo::kNoId, devices[0].session_id);
3544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Open the first device.
3564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    {
3574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::RunLoop run_loop;
3584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      StreamDeviceInfo opened_device;
3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      media_stream_manager_->OpenDevice(
3604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          &stream_requester_,
3614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          render_process_id,
3624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          render_view_id,
3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
3644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          page_request_id,
3654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          devices[0].device.id,
3664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          MEDIA_DEVICE_VIDEO_CAPTURE,
3674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          security_origin);
3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_CALL(stream_requester_, DeviceOpened(render_view_id,
3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                  page_request_id,
3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                  _,
3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                  _))
3724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          .Times(1).WillOnce(
3734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)              DoAll(ExitMessageLoop(message_loop_, run_loop.QuitClosure()),
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    SaveArg<2>(&opened_device_label_),
3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    SaveArg<3>(&opened_device)));
3764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      run_loop.Run();
3774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      Mock::VerifyAndClearExpectations(&stream_requester_);
3784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      ASSERT_NE(StreamDeviceInfo::kNoId, opened_device.session_id);
3794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      opened_session_id_ = opened_device.session_id;
3804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
3814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void CloseSession() {
3844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (opened_device_label_.empty())
3854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return;
3868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    media_stream_manager_->CancelRequest(opened_device_label_);
3874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    opened_device_label_.clear();
3884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    opened_session_id_ = kInvalidMediaCaptureSessionId;
3894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch protected:
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartCapture() {
3934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_CALL(*host_, OnNewBufferCreated(kDeviceId, _, _, _))
394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        .Times(AnyNumber()).WillRepeatedly(Return());
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::RunLoop run_loop;
3971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    EXPECT_CALL(*host_, OnBufferFilled(kDeviceId, _, _, _))
398eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        .Times(AnyNumber()).WillOnce(ExitMessageLoop(
399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            message_loop_, run_loop.QuitClosure()));
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    media::VideoCaptureParams params;
4021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    params.requested_format = media::VideoCaptureFormat(
403f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        gfx::Size(352, 288), 30, media::PIXEL_FORMAT_I420);
404f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    host_->OnStartCapture(kDeviceId, opened_session_id_, params);
405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    run_loop.Run();
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
408d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  void StartStopCapture() {
409d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // Quickly start and then stop capture, without giving much chance for
410d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // asynchronous start operations to complete.
411d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    InSequence s;
412d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    base::RunLoop run_loop;
4134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_CALL(*host_, OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_STOPPED));
414d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    media::VideoCaptureParams params;
4151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    params.requested_format = media::VideoCaptureFormat(
416f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        gfx::Size(352, 288), 30, media::PIXEL_FORMAT_I420);
417f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    host_->OnStartCapture(kDeviceId, opened_session_id_, params);
418d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    host_->OnStopCapture(kDeviceId);
419d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    run_loop.RunUntilIdle();
420d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
421d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DUMP_VIDEO
423d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  void CaptureAndDumpVideo(int width, int height, int frame_rate) {
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InSequence s;
4251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    EXPECT_CALL(*host_.get(), OnNewBufferCreated(kDeviceId, _, _, _))
4261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        .Times(AnyNumber()).WillRepeatedly(Return());
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::RunLoop run_loop;
4291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    EXPECT_CALL(*host_, OnBufferFilled(kDeviceId, _, _, _))
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Times(AnyNumber())
431eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        .WillOnce(ExitMessageLoop(message_loop_, run_loop.QuitClosure()));
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    media::VideoCaptureParams params;
434f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    params.requested_format =
435f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        media::VideoCaptureFormat(gfx::Size(width, height), frame_rate);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host_->SetDumpVideo(true);
437f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    host_->OnStartCapture(kDeviceId, opened_session_id_, params);
438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    run_loop.Run();
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StopCapture() {
443eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::RunLoop run_loop;
4444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_CALL(*host_, OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_STOPPED))
445eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        .WillOnce(ExitMessageLoop(message_loop_, run_loop.QuitClosure()));
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host_->OnStopCapture(kDeviceId);
4481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    host_->SetReturnReceivedDibs(true);
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host_->ReturnReceivedDibs(kDeviceId);
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
451eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    run_loop.Run();
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    host_->SetReturnReceivedDibs(false);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Expect the VideoCaptureDevice has been stopped
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0u, host_->entries_.size());
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void NotifyPacketReady() {
459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::RunLoop run_loop;
4601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    EXPECT_CALL(*host_, OnBufferFilled(kDeviceId, _, _, _))
461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        .Times(AnyNumber()).WillOnce(ExitMessageLoop(
462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            message_loop_, run_loop.QuitClosure()))
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .RetiresOnSaturation();
464eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    run_loop.Run();
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ReturnReceivedPackets() {
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host_->ReturnReceivedDibs(kDeviceId);
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SimulateError() {
4724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Expect a change state to error state sent through IPC.
4734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_CALL(*host_, OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_ERROR))
4744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        .Times(1);
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VideoCaptureControllerID id(kDeviceId);
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host_->OnError(id);
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Wait for the error callback.
478eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::RunLoop().RunUntilIdle();
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<MockVideoCaptureHost> host_;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
4844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  StrictMock<MockMediaStreamRequester> stream_requester_;
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<media::AudioManager> audio_manager_;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<MediaStreamManager> media_stream_manager_;
487eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  content::TestBrowserThreadBundle thread_bundle_;
488a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  content::TestBrowserContext browser_context_;
489a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  content::TestContentBrowserClient browser_client_;
490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_refptr<base::MessageLoopProxy> message_loop_;
4914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int opened_session_id_;
4924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  std::string opened_device_label_;
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(VideoCaptureHostTest);
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST_F(VideoCaptureHostTest, CloseSessionWithoutStopping) {
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StartCapture();
4994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // When the session is closed via the stream without stopping capture, the
5014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // ENDED event is sent.
5024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_CALL(*host_, OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_ENDED))
5034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      .Times(1);
5044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  CloseSession();
5054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::RunLoop().RunUntilIdle();
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST_F(VideoCaptureHostTest, StopWhileStartPending) {
509d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  StartStopCapture();
510d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
511d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VideoCaptureHostTest, StartCapturePlayStop) {
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StartCapture();
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotifyPacketReady();
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotifyPacketReady();
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReturnReceivedPackets();
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StopCapture();
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VideoCaptureHostTest, StartCaptureErrorStop) {
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StartCapture();
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateError();
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StopCapture();
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VideoCaptureHostTest, StartCaptureError) {
5274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_CALL(*host_, OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_STOPPED))
5284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      .Times(0);
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StartCapture();
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotifyPacketReady();
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateError();
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200));
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DUMP_VIDEO
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VideoCaptureHostTest, CaptureAndDumpVideoVga) {
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CaptureAndDumpVideo(640, 480, 30);
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VideoCaptureHostTest, CaptureAndDump720P) {
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CaptureAndDumpVideo(1280, 720, 30);
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
545