C++程序  |  158行  |  6.14 KB

// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// VideoCaptureImpl represents a capture device in renderer process. It provides
// interfaces for clients to Start/Stop capture. It also communicates to clients
// when buffer is ready, state of capture device is changed.

// VideoCaptureImpl is also a delegate of VideoCaptureMessageFilter which relays
// operation of a capture device to the browser process and receives responses
// from browser process.

// The media::VideoCapture and VideoCaptureMessageFilter::Delegate are
// asynchronous interfaces, which means callers can call those interfaces
// from any threads without worrying about thread safety.
// The |capture_message_loop_proxy_| is the working thread of VideoCaptureImpl.
// All non-const members are accessed only on that working thread.
//
// Implementation note: tasks are posted bound to Unretained(this) to both the
// I/O and Capture threads and this is safe (even though the I/O thread is
// scoped to the renderer process and the capture_message_loop_proxy_ thread is
// scoped to the VideoCaptureImplManager) because VideoCaptureImplManager only
// triggers deletion of its VideoCaptureImpl's by calling DeInit which detours
// through the capture & I/O threads, so as long as nobody posts tasks after the
// DeInit() call is made, it is guaranteed none of these Unretained posted tasks
// will dangle after the delete goes through.  The "as long as" is guaranteed by
// clients of VideoCaptureImplManager not using devices after they've
// RemoveDevice'd them.

#ifndef CONTENT_RENDERER_MEDIA_VIDEO_CAPTURE_IMPL_H_
#define CONTENT_RENDERER_MEDIA_VIDEO_CAPTURE_IMPL_H_

#include <list>
#include <map>

#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
#include "content/common/media/video_capture.h"
#include "content/renderer/media/video_capture_message_filter.h"
#include "media/video/capture/video_capture.h"
#include "media/video/capture/video_capture_types.h"

namespace base {
class MessageLoopProxy;
}

namespace content {

class CONTENT_EXPORT VideoCaptureImpl
    : public media::VideoCapture, public VideoCaptureMessageFilter::Delegate {
 public:
  // media::VideoCapture interface.
  virtual void StartCapture(
      media::VideoCapture::EventHandler* handler,
      const media::VideoCaptureParams& params) OVERRIDE;
  virtual void StopCapture(media::VideoCapture::EventHandler* handler) OVERRIDE;
  virtual bool CaptureStarted() OVERRIDE;
  virtual int CaptureFrameRate() OVERRIDE;

  // VideoCaptureMessageFilter::Delegate interface.
  virtual void OnBufferCreated(base::SharedMemoryHandle handle,
                               int length,
                               int buffer_id) OVERRIDE;
  virtual void OnBufferDestroyed(int buffer_id) OVERRIDE;
  virtual void OnBufferReceived(
      int buffer_id,
      base::Time timestamp,
      const media::VideoCaptureFormat& format) OVERRIDE;
  virtual void OnStateChanged(VideoCaptureState state) OVERRIDE;
  virtual void OnDelegateAdded(int32 device_id) OVERRIDE;

  // Stop/resume delivering video frames to clients, based on flag |suspend|.
  virtual void SuspendCapture(bool suspend);

 private:
  friend class VideoCaptureImplManager;
  friend class VideoCaptureImplTest;
  friend class MockVideoCaptureImpl;

  class ClientBuffer;
  typedef std::map<media::VideoCapture::EventHandler*,
                   media::VideoCaptureParams> ClientInfo;

  VideoCaptureImpl(media::VideoCaptureSessionId session_id,
                   base::MessageLoopProxy* capture_message_loop_proxy,
                   VideoCaptureMessageFilter* filter);
  virtual ~VideoCaptureImpl();

  void DoStartCaptureOnCaptureThread(
      media::VideoCapture::EventHandler* handler,
      const media::VideoCaptureParams& params);
  void DoStopCaptureOnCaptureThread(media::VideoCapture::EventHandler* handler);
  void DoBufferCreatedOnCaptureThread(base::SharedMemoryHandle handle,
                                      int length,
                                      int buffer_id);
  void DoBufferDestroyedOnCaptureThread(int buffer_id);
  void DoBufferReceivedOnCaptureThread(
      int buffer_id,
      base::Time timestamp,
      const media::VideoCaptureFormat& format);
  void DoClientBufferFinishedOnCaptureThread(
      int buffer_id,
      const scoped_refptr<ClientBuffer>& buffer);
  void DoStateChangedOnCaptureThread(VideoCaptureState state);
  void DoDelegateAddedOnCaptureThread(int32 device_id);

  void DoSuspendCaptureOnCaptureThread(bool suspend);

  void Init();
  void DeInit(base::Closure task);
  void DoDeInitOnCaptureThread(base::Closure task);
  void StopDevice();
  void RestartCapture();
  void StartCaptureInternal();
  void AddDelegateOnIOThread();
  void RemoveDelegateOnIOThread(base::Closure task);
  virtual void Send(IPC::Message* message);

  // Helpers.
  bool RemoveClient(media::VideoCapture::EventHandler* handler,
                    ClientInfo* clients);

  const scoped_refptr<VideoCaptureMessageFilter> message_filter_;
  const scoped_refptr<base::MessageLoopProxy> capture_message_loop_proxy_;
  const scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
  int device_id_;
  const int session_id_;

  // Buffers available for sending to the client.
  typedef std::map<int32, scoped_refptr<ClientBuffer> > ClientBufferMap;
  ClientBufferMap client_buffers_;

  ClientInfo clients_;
  ClientInfo clients_pending_on_filter_;
  ClientInfo clients_pending_on_restart_;

  // Member params_ represents the video format requested by the
  // client to this class via DoStartCaptureOnCaptureThread.
  media::VideoCaptureParams params_;

  // The device's video capture format sent from browser process side.
  media::VideoCaptureFormat last_frame_format_;

  bool suspended_;
  VideoCaptureState state_;

  // WeakPtrFactory pointing back to |this| object, for use with
  // media::VideoFrames constructed in OnBufferReceived() from buffers cached
  // in |client_buffers_|.
  base::WeakPtrFactory<VideoCaptureImpl> weak_this_factory_;

  DISALLOW_COPY_AND_ASSIGN(VideoCaptureImpl);
};

}  // namespace content

#endif  // CONTENT_RENDERER_MEDIA_VIDEO_CAPTURE_IMPL_H_