summaryrefslogtreecommitdiffstats
path: root/media/capture/video/video_capture_device.h
blob: 71a4f3e6697a41f0d36c2bebc66af88390e991f1 (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
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
// 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 <stddef.h>
#include <stdint.h>

#include <list>
#include <string>

#include "base/files/file.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "media/base/media_export.h"
#include "media/base/video_capture_types.h"
#include "media/base/video_frame.h"
#include "ui/gfx/gpu_memory_buffer.h"

namespace tracked_objects {
class Location;
}  // namespace tracked_objects

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);

#if defined(OS_LINUX)
    // Linux/CrOS targets Capture Api type: it can only be set on construction.
    enum CaptureApiType {
      V4L2_SINGLE_PLANE,
      API_TYPE_UNKNOWN
    };
#elif defined(OS_WIN)
    // Windows targets Capture Api type: it can only be set on construction.
    enum CaptureApiType { MEDIA_FOUNDATION, DIRECT_SHOW, API_TYPE_UNKNOWN };
#elif defined(OS_MACOSX)
    // Mac targets Capture Api type: it can only be set on construction.
    enum CaptureApiType { AVFOUNDATION, QTKIT, DECKLINK, API_TYPE_UNKNOWN };
    // For AVFoundation Api, identify devices that are built-in or USB.
    enum TransportType { USB_OR_BUILT_IN, OTHER_TRANSPORT };
#elif defined(OS_ANDROID)
    // Android targets Capture Api type: it can only be set on construction.
    // Automatically generated enum to interface with Java world.
    //
    // A Java counterpart will be generated for this enum.
    // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.media
    enum CaptureApiType {
      API1,
      API2_LEGACY,
      API2_FULL,
      API2_LIMITED,
      TANGO,
      API_TYPE_UNKNOWN
    };
#endif

#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \
    defined(OS_ANDROID)
    Name(const std::string& name,
         const std::string& id,
         const CaptureApiType api_type);
#endif
#if defined(OS_MACOSX)
    Name(const std::string& name,
         const std::string& id,
         const CaptureApiType api_type,
         const TransportType transport_type);
#endif
    ~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) || defined(OS_MACOSX) || defined(OS_LINUX) || \
    defined(OS_ANDROID)
    CaptureApiType capture_api_type() const {
      return capture_api_class_.capture_api_type();
    }
    const char* GetCaptureApiTypeString() const;
#endif
#if defined(OS_WIN)
    // Certain devices need an ID different from the |unique_id_| for
    // capabilities retrieval.
    const std::string& capabilities_id() const { return capabilities_id_; }
    void set_capabilities_id(const std::string& id) { capabilities_id_ = id; }
#endif  // if defined(OS_WIN)
#if defined(OS_MACOSX)
    TransportType transport_type() const { return transport_type_; }
    bool is_blacklisted() const { return is_blacklisted_; }
    void set_is_blacklisted(bool is_blacklisted) {
      is_blacklisted_ = is_blacklisted;
    }
#endif  // if defined(OS_MACOSX)

   private:
    std::string device_name_;
    std::string unique_id_;
#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \
    defined(OS_ANDROID)
    // This class wraps the CaptureApiType to give it a by default value if not
    // initialized.
    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)
    // ID used for capabilities retrieval. By default is equal to |unique_id|.
    std::string capabilities_id_;
#endif
#if defined(OS_MACOSX)
    TransportType transport_type_;
    // Flag used to mark blacklisted devices for QTKit Api.
    bool is_blacklisted_;
#endif
    // Allow generated copy constructor and assignment.
  };

  // Manages a list of Name entries.
  typedef std::list<Name> Names;

  // Interface defining the methods that clients of VideoCapture must have. It
  // is actually two-in-one: clients may implement OnIncomingCapturedData() or
  // ReserveOutputBuffer() + OnIncomingCapturedVideoFrame(), or all of them.
  // All clients must implement OnError().
  class MEDIA_EXPORT Client {
   public:
    // Memory buffer returned by Client::ReserveOutputBuffer().
    class MEDIA_EXPORT Buffer {
     public:
      virtual ~Buffer() = 0;
      virtual int id() const = 0;
      virtual gfx::Size dimensions() const = 0;
      virtual size_t mapped_size() const = 0;
      virtual void* data(int plane) = 0;
      void* data() { return data(0); }
      virtual ClientBuffer AsClientBuffer(int plane) = 0;
#if defined(OS_POSIX) && !(defined(OS_MACOSX) && !defined(OS_IOS))
      virtual base::FileDescriptor AsPlatformFile() = 0;
#endif
    };

    virtual ~Client() {}

    // Captured a new video frame, data for which is pointed to by |data|.
    //
    // The format of the frame is described by |frame_format|, and is assumed to
    // be tightly packed. 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 OnIncomingCapturedData(const uint8_t* data,
                                        int length,
                                        const VideoCaptureFormat& frame_format,
                                        int clockwise_rotation,
                                        const base::TimeTicks& timestamp) = 0;

    // Reserve an output buffer into which contents can be captured directly.
    // The returned Buffer will always be allocated with a memory size suitable
    // for holding a packed video frame with pixels of |format| format, of
    // |dimensions| frame dimensions. It is permissible for |dimensions| to be
    // zero; in which case the returned Buffer does not guarantee memory
    // backing, but functions as a reservation for external input for the
    // purposes of buffer throttling.
    //
    // The output buffer stays reserved and mapped for use until the Buffer
    // object is destroyed or returned.
    virtual scoped_ptr<Buffer> ReserveOutputBuffer(
        const gfx::Size& dimensions,
        VideoPixelFormat format,
        VideoPixelStorage storage) = 0;

    // Captured new video data, held in |frame| or |buffer|, respectively for
    // OnIncomingCapturedVideoFrame() and  OnIncomingCapturedBuffer().
    //
    // In both cases, as the frame is backed by a reservation returned by
    // ReserveOutputBuffer(), delivery is guaranteed and will require no
    // additional copies in the browser process.
    virtual void OnIncomingCapturedBuffer(
        scoped_ptr<Buffer> buffer,
        const VideoCaptureFormat& frame_format,
        const base::TimeTicks& timestamp) = 0;
    virtual void OnIncomingCapturedVideoFrame(
        scoped_ptr<Buffer> buffer,
        const scoped_refptr<VideoFrame>& frame,
        const base::TimeTicks& timestamp) = 0;

    // Attempts to reserve the same Buffer provided in the last call to one of
    // the OnIncomingCapturedXXX() methods. This will fail if the content of the
    // Buffer has not been preserved, or if the |dimensions|, |format|, or
    // |storage| disagree with how it was reserved via ReserveOutputBuffer().
    // When this operation fails, nullptr will be returned.
    virtual scoped_ptr<Buffer> ResurrectLastOutputBuffer(
        const gfx::Size& dimensions,
        VideoPixelFormat format,
        VideoPixelStorage storage) = 0;

    // An error has occurred that cannot be handled and VideoCaptureDevice must
    // be StopAndDeAllocate()-ed. |reason| is a text description of the error.
    virtual void OnError(const tracked_objects::Location& from_here,
                         const std::string& reason) = 0;

    // VideoCaptureDevice requests the |message| to be logged.
    virtual void OnLog(const std::string& message) {}

    // Returns the current buffer pool utilization, in the range 0.0 (no buffers
    // are in use by producers or consumers) to 1.0 (all buffers are in use).
    virtual double GetBufferPoolUtilization() const = 0;
  };

  virtual ~VideoCaptureDevice();

  // Prepares the video capturer for use. StopAndDeAllocate() must be called
  // before the object is deleted.
  virtual void AllocateAndStart(const VideoCaptureParams& params,
                                scoped_ptr<Client> client) = 0;

  // In cases where the video capturer self-pauses (e.g., a screen capturer
  // where the screen's content has not changed in a while), consumers may call
  // this to request a "refresh frame" be delivered to the Client.  This is used
  // in a number of circumstances, such as:
  //
  //   1. An additional consumer of video frames is starting up and requires a
  //      first frame (as opposed to not receiving a frame for an indeterminate
  //      amount of time).
  //   2. A few repeats of the same frame would allow a lossy video encoder to
  //      improve the video quality of unchanging content.
  //
  // The default implementation is a no-op. VideoCaptureDevice implementations
  // are not required to honor this request, especially if they do not
  // self-pause and/or if honoring the request would cause them to exceed their
  // configured maximum frame rate. Any VideoCaptureDevice that does self-pause,
  // however, should provide an implementation of this method that makes
  // reasonable attempts to honor these requests.
  virtual void RequestRefreshFrame() {}

  // Deallocates the video capturer, possibly asynchronously.
  //
  // This call requires the device to do the following things, eventually: put
  // 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;

  // Gets the power line frequency, either from the params if specified by the
  // user or from the current system time zone.
  PowerLineFrequency GetPowerLineFrequency(
      const VideoCaptureParams& params) const;

 private:
  // Gets the power line frequency from the current system time zone if this is
  // defined, otherwise returns 0.
  PowerLineFrequency GetPowerLineFrequencyForLocation() const;
};

}  // namespace media

#endif  // MEDIA_VIDEO_CAPTURE_VIDEO_CAPTURE_DEVICE_H_