summaryrefslogtreecommitdiffstats
path: root/content/renderer/media/video_capture_impl.h
blob: 278355a395eeff3c2487827a047d496e3b884703 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
// 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.
//
// All public methods of VideoCaptureImpl can be called on any thread.
// Internally it runs on the IO thread. Clients of this class implement
// interface media::VideoCapture::EventHandler which is called only on the IO
// thread.
//
// Implementation note: tasks are posted bound to Unretained(this) to the I/O
// thread and this is safe (even though the I/O thread is scoped to the renderer
// process) because VideoCaptureImplManager only triggers deletion of its
// VideoCaptureImpl's by calling DeInit which detours through the I/O thread, 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 released
// VideoCaptureHandle, which is a wrapper of this object.

#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:
  VideoCaptureImpl(media::VideoCaptureSessionId session_id,
                   VideoCaptureMessageFilter* filter);
  virtual ~VideoCaptureImpl();

  // Start listening to IPC messages.
  void Init();

  // Stop listening to IPC messages. Call |done_cb| when done.
  void DeInit(base::Closure done_cb);

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

  // 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;
  virtual void GetDeviceSupportedFormats(
      const DeviceFormatsCallback& callback) OVERRIDE;
  virtual void GetDeviceFormatsInUse(
      const DeviceFormatsInUseCallback& callback) OVERRIDE;

  media::VideoCaptureSessionId session_id() const { return session_id_; }

 private:
  friend class VideoCaptureImplTest;
  friend class MockVideoCaptureImpl;

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

  void InitOnIOThread();
  void DeInitOnIOThread(base::Closure done_cb);
  void SuspendCaptureOnIOThread(bool suspend);
  void StartCaptureOnIOThread(
      media::VideoCapture::EventHandler* handler,
      const media::VideoCaptureParams& params);
  void StopCaptureOnIOThread(media::VideoCapture::EventHandler* handler);
  void GetDeviceSupportedFormatsOnIOThread(
      const DeviceFormatsCallback& callback);
  void GetDeviceFormatsInUseOnIOThread(
      const DeviceFormatsInUseCallback& callback);

  // 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::TimeTicks timestamp,
      const media::VideoCaptureFormat& format) OVERRIDE;
  virtual void OnStateChanged(VideoCaptureState state) OVERRIDE;
  virtual void OnDeviceSupportedFormatsEnumerated(
      const media::VideoCaptureFormats& supported_formats) OVERRIDE;
  virtual void OnDeviceFormatsInUseReceived(
      const media::VideoCaptureFormats& formats_in_use) OVERRIDE;
  virtual void OnDelegateAdded(int32 device_id) OVERRIDE;

  // Sends an IPC message to browser process when all clients are done with the
  // buffer.
  void OnClientBufferFinished(
      int buffer_id,
      const scoped_refptr<ClientBuffer>& buffer);

  void StopDevice();
  void RestartCapture();
  void StartCaptureInternal();

  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> io_message_loop_proxy_;
  int device_id_;
  const int session_id_;

  // Vector of callbacks to be notified of device format enumerations, used only
  // on IO Thread.
  std::vector<DeviceFormatsCallback> device_formats_callback_queue_;
  // Vector of callbacks to be notified of a device's in use capture format(s),
  // used only on IO Thread.
  std::vector<DeviceFormatsInUseCallback> device_formats_in_use_callback_queue_;

  // 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 StartCapture().
  media::VideoCaptureParams params_;

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

  // The device's first captured frame timestamp sent from browser process side.
  base::TimeTicks first_frame_timestamp_;

  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_