summaryrefslogtreecommitdiff
path: root/chromium/media/video/capture/video_capture_device.h
blob: e7340841ceecf5a22212489d86d449f672a76a39 (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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
// 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.
//
// VideoCaptureDevice is the abstract base class for realizing video capture
// device support in Chromium. It provides the interface for OS dependent
// implementations.
// The class is created and functions are invoked on a thread owned by
// VideoCaptureManager. Capturing is done on other threads, depending on the OS
// specific implementation.

#ifndef MEDIA_VIDEO_CAPTURE_VIDEO_CAPTURE_DEVICE_H_
#define MEDIA_VIDEO_CAPTURE_VIDEO_CAPTURE_DEVICE_H_

#include <list>
#include <string>

#include "base/logging.h"
#include "base/time/time.h"
#include "media/base/media_export.h"
#include "media/video/capture/video_capture_types.h"

namespace media {

class MEDIA_EXPORT VideoCaptureDevice {
 public:
  // Represents a capture device name and ID.
  // You should not create an instance of this class directly by e.g. setting
  // various properties directly.  Instead use
  // VideoCaptureDevice::GetDeviceNames to do this for you and if you need to
  // cache your own copy of a name, you can do so via the copy constructor.
  // The reason for this is that a device name might contain platform specific
  // settings that are relevant only to the platform specific implementation of
  // VideoCaptureDevice::Create.
  class MEDIA_EXPORT Name {
   public:
    Name() {}
    Name(const std::string& name, const std::string& id)
        : device_name_(name), unique_id_(id) {}

#if defined(OS_WIN)
    // Windows targets Capture Api type: it can only be set on construction.
    enum CaptureApiType {
      MEDIA_FOUNDATION,
      DIRECT_SHOW,
      API_TYPE_UNKNOWN
    };

    Name(const std::string& name,
         const std::string& id,
         const CaptureApiType api_type)
        : device_name_(name), unique_id_(id), capture_api_class_(api_type) {}
#endif  // if defined(OS_WIN)
    ~Name() {}

    // Friendly name of a device
    const std::string& name() const { return device_name_; }

    // Unique name of a device. Even if there are multiple devices with the same
    // friendly name connected to the computer this will be unique.
    const std::string& id() const { return unique_id_; }

    // The unique hardware model identifier of the capture device.  Returns
    // "[vid]:[pid]" when a USB device is detected, otherwise "".
    // The implementation of this method is platform-dependent.
    const std::string GetModel() const;

    // Friendly name of a device, plus the model identifier in parentheses.
    const std::string GetNameAndModel() const;

    // These operators are needed due to storing the name in an STL container.
    // In the shared build, all methods from the STL container will be exported
    // so even though they're not used, they're still depended upon.
    bool operator==(const Name& other) const {
      return other.id() == unique_id_;
    }
    bool operator<(const Name& other) const {
      return unique_id_ < other.id();
    }

#if defined(OS_WIN)
    CaptureApiType capture_api_type() const {
      return capture_api_class_.capture_api_type();
    }
#endif  // if defined(OS_WIN)

   private:
    std::string device_name_;
    std::string unique_id_;
#if defined(OS_WIN)
    // This class wraps the CaptureApiType, so it has a by default value if not
    // inititalized, and I (mcasas) do a DCHECK on reading its value.
    class CaptureApiClass {
     public:
      CaptureApiClass():  capture_api_type_(API_TYPE_UNKNOWN) {}
      CaptureApiClass(const CaptureApiType api_type)
          :  capture_api_type_(api_type) {}
      CaptureApiType capture_api_type() const {
        DCHECK_NE(capture_api_type_,  API_TYPE_UNKNOWN);
        return capture_api_type_;
      }
     private:
      CaptureApiType capture_api_type_;
    };

    CaptureApiClass capture_api_class_;
#endif  // if defined(OS_WIN)
    // Allow generated copy constructor and assignment.
  };

  // Manages a list of Name entries.
  class MEDIA_EXPORT Names
      : public NON_EXPORTED_BASE(std::list<Name>) {
   public:
    // Returns NULL if no entry was found by that ID.
    Name* FindById(const std::string& id);

    // Allow generated copy constructor and assignment.
  };

  class MEDIA_EXPORT EventHandler {
   public:
    virtual ~EventHandler() {}

    // Reserve an output buffer into which a video frame can be captured
    // directly. If all buffers are currently busy, returns NULL.
    //
    // The returned VideoFrames will always be allocated with a YV12 format. The
    // size will match that specified by an earlier call to OnFrameInfo. It is
    // the VideoCaptureDevice's responsibility to obey whatever stride and
    // memory layout are indicated on the returned VideoFrame object.
    //
    // The output buffer stays reserved for use by the calling
    // VideoCaptureDevice until either the last reference to the VideoFrame is
    // released, or until the buffer is passed back to the EventHandler's
    // OnIncomingCapturedFrame() method.
    virtual scoped_refptr<media::VideoFrame> ReserveOutputBuffer() = 0;

    // Captured a new video frame as a raw buffer. The size, color format, and
    // layout are taken from the parameters specified by an earlier call to
    // OnFrameInfo(). |data| must be packed, with no padding between rows and/or
    // color planes.
    //
    // This method will try to reserve an output buffer and copy from |data|
    // into the output buffer. If no output buffer is available, the frame will
    // be silently dropped.
    virtual void OnIncomingCapturedFrame(const uint8* data,
                                         int length,
                                         base::Time timestamp,
                                         int rotation,  // Clockwise.
                                         bool flip_vert,
                                         bool flip_horiz) = 0;

    // Captured a new video frame, held in a VideoFrame container.
    //
    // If |frame| was created via the ReserveOutputBuffer() mechanism, then the
    // frame delivery is guaranteed (it will not be silently dropped), and
    // delivery will require no additional copies in the browser process. For
    // such frames, the VideoCaptureDevice's reservation on the output buffer
    // ends immediately. The VideoCaptureDevice may not read or write the
    // underlying memory afterwards, and it should release its references to
    // |frame| as soon as possible, to allow buffer reuse.
    //
    // If |frame| was NOT created via ReserveOutputBuffer(), then this method
    // will try to reserve an output buffer and copy from |frame| into the
    // output buffer. If no output buffer is available, the frame will be
    // silently dropped. |frame| must be allocated as RGB32, YV12 or I420, and
    // the size must match that specified by an earlier call to OnFrameInfo().
    virtual void OnIncomingCapturedVideoFrame(
        const scoped_refptr<media::VideoFrame>& frame,
        base::Time timestamp) = 0;

    // An error has occurred that cannot be handled and VideoCaptureDevice must
    // be StopAndDeAllocate()-ed.
    virtual void OnError() = 0;

    // Called when VideoCaptureDevice::AllocateAndStart() has been called to
    // inform of the resulting frame size.
    virtual void OnFrameInfo(const VideoCaptureCapability& info) = 0;

    // Called when the native resolution of VideoCaptureDevice has been changed
    // and it needs to inform its client of the new frame size.
    virtual void OnFrameInfoChanged(const VideoCaptureCapability& info) {};
  };
  // Creates a VideoCaptureDevice object.
  // Return NULL if the hardware is not available.
  static VideoCaptureDevice* Create(const Name& device_name);
  virtual ~VideoCaptureDevice();

  // Gets the names of all video capture devices connected to this computer.
  static void GetDeviceNames(Names* device_names);

  // Prepare the camera for use. After this function has been called no other
  // applications can use the camera. On completion EventHandler::OnFrameInfo()
  // is called informing of the resulting resolution and frame rate.
  // StopAndDeAllocate() must be called before the object is deleted.
  virtual void AllocateAndStart(
      const VideoCaptureCapability& capture_format,
      scoped_ptr<EventHandler> client) = 0;

  // Deallocates the camera, possibly asynchronously.
  //
  // This call requires the device to do the following things, eventually: put
  // camera hardware into a state where other applications could use it, free
  // the memory associated with capture, and delete the |client| pointer passed
  // into AllocateAndStart.
  //
  // If deallocation is done asynchronously, then the device implementation must
  // ensure that a subsequent AllocateAndStart() operation targeting the same ID
  // would be sequenced through the same task runner, so that deallocation
  // happens first.
  virtual void StopAndDeAllocate() = 0;
};

// VideoCaptureDevice1 is a bridge to an older API against which
// VideoCaptureDevices were implemented. Differences between VideoCaptureDevice
// (new style) and VideoCaptureDevice1 (old style) are as follows:
//
// [1] The Stop+DeAllocate calls are merged in the new style.
// [2] The Allocate+Start calls are merged in the new style.
// [3] New style devices own their EventHandler* pointers, allowing handlers to
//     remain valid even after the device is stopped. Whereas old style devices
//     may not dereference their handlers after DeAllocate().
// [4] device_name() is eliminated from the new-style interface.
//
// TODO(nick): Remove this bridge class. It exists to enable incremental
// migration to an alternative VideoCaptureDevice API.
class MEDIA_EXPORT VideoCaptureDevice1 : public VideoCaptureDevice {
 public:
  VideoCaptureDevice1();
  virtual ~VideoCaptureDevice1();

  // VideoCaptureDevice implementation.
  virtual void AllocateAndStart(
      const VideoCaptureCapability& capture_format,
      scoped_ptr<EventHandler> client) OVERRIDE;
  virtual void StopAndDeAllocate() OVERRIDE;

  // Prepare the camera for use. After this function has been called no other
  // applications can use the camera. On completion EventHandler::OnFrameInfo()
  // is called informing of the resulting resolution and frame rate.
  // DeAllocate() must be called before this function can be called again and
  // before the object is deleted.
  virtual void Allocate(const VideoCaptureCapability& capture_format,
                        EventHandler* client) = 0;

  // Start capturing video frames. Allocate must be called before this function.
  virtual void Start() = 0;

  // Stop capturing video frames.
  virtual void Stop() = 0;

  // Deallocates the camera. This means other applications can use it. After
  // this function has been called the capture device is reset to the state it
  // was when created. After DeAllocate() is called, the VideoCaptureDevice is
  // not permitted to make any additional calls to its EventHandler.
  virtual void DeAllocate() = 0;

  // Get the name of the capture device.
  virtual const Name& device_name() = 0;

 private:
  // The device client which proxies device events to the controller.
  scoped_ptr<EventHandler> client_;
};

}  // namespace media

#endif  // MEDIA_VIDEO_CAPTURE_VIDEO_CAPTURE_DEVICE_H_