1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_AVFOUNDATION_MAC_H_
6#define MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_AVFOUNDATION_MAC_H_
7
8#import <Foundation/Foundation.h>
9
10#import "base/mac/scoped_nsobject.h"
11#include "base/synchronization/lock.h"
12#include "base/threading/thread_checker.h"
13#import "media/base/mac/avfoundation_glue.h"
14#import "media/video/capture/mac/platform_video_capturing_mac.h"
15#include "media/video/capture/video_capture_device.h"
16#include "media/video/capture/video_capture_types.h"
17
18namespace media {
19class VideoCaptureDeviceMac;
20}
21
22@class CrAVCaptureDevice;
23@class CrAVCaptureSession;
24@class CrAVCaptureVideoDataOutput;
25
26// Class used by VideoCaptureDeviceMac (VCDM) for video capture using
27// AVFoundation API. This class lives inside the thread created by its owner
28// VCDM.
29//
30//  * Clients (VCDM) should call +deviceNames to fetch the list of devices
31//    available in the system; this method returns the list of device names that
32//    have to be used with -setCaptureDevice:.
33//  * Previous to any use, clients (VCDM) must call -initWithFrameReceiver: to
34//    initialise an object of this class and register a |frameReceiver_|.
35//  * Frame receiver registration or removal can also happen via explicit call
36//    to -setFrameReceiver:. Re-registrations are safe and allowed, even during
37//    capture using this method.
38//  * Method -setCaptureDevice: must be called at least once with a device
39//    identifier from +deviceNames. Creates all the necessary AVFoundation
40//    objects on first call; it connects them ready for capture every time.
41//    This method should not be called during capture (i.e. between
42//    -startCapture and -stopCapture).
43//  * -setCaptureWidth:height:frameRate: is called if a resolution or frame rate
44//    different than the by default one set by -setCaptureDevice: is needed.
45//    This method should not be called during capture. This method must be
46//    called after -setCaptureDevice:.
47//  * -startCapture registers the notification listeners and starts the
48//    capture. The capture can be stop using -stopCapture. The capture can be
49//    restarted and restoped multiple times, reconfiguring or not the device in
50//    between.
51//  * -setCaptureDevice can be called with a |nil| value, case in which it stops
52//    the capture and disconnects the library objects. This step is not
53//    necessary.
54//  * Deallocation of the library objects happens gracefully on destruction of
55//    the VideoCaptureDeviceAVFoundation object.
56//
57//
58@interface VideoCaptureDeviceAVFoundation
59    : NSObject<CrAVCaptureVideoDataOutputSampleBufferDelegate,
60               PlatformVideoCapturingMac> {
61 @private
62  // The following attributes are set via -setCaptureHeight:width:frameRate:.
63  int frameWidth_;
64  int frameHeight_;
65  float frameRate_;
66
67  base::Lock lock_;  // Protects concurrent setting and using of frameReceiver_.
68  media::VideoCaptureDeviceMac* frameReceiver_;  // weak.
69
70  base::scoped_nsobject<CrAVCaptureSession> captureSession_;
71
72  // |captureDevice_| is an object coming from AVFoundation, used only to be
73  // plugged in |captureDeviceInput_| and to query for session preset support.
74  CrAVCaptureDevice* captureDevice_;
75  // |captureDeviceInput_| is owned by |captureSession_|.
76  CrAVCaptureDeviceInput* captureDeviceInput_;
77  base::scoped_nsobject<CrAVCaptureVideoDataOutput> captureVideoDataOutput_;
78
79  base::ThreadChecker main_thread_checker_;
80  base::ThreadChecker callback_thread_checker_;
81}
82
83// Returns a dictionary of capture devices with friendly name and unique id.
84+ (NSDictionary*)deviceNames;
85
86// Retrieve the capture supported formats for a given device |name|.
87+ (void)getDevice:(const media::VideoCaptureDevice::Name&)name
88    supportedFormats:(media::VideoCaptureFormats*)formats;
89
90// Initializes the instance and the underlying capture session and registers the
91// frame receiver.
92- (id)initWithFrameReceiver:(media::VideoCaptureDeviceMac*)frameReceiver;
93
94// Sets the frame receiver.
95- (void)setFrameReceiver:(media::VideoCaptureDeviceMac*)frameReceiver;
96
97// Sets which capture device to use by name, retrieved via |deviceNames|. Once
98// the deviceId is known, the library objects are created if needed and
99// connected for the capture, and a by default resolution is set. If deviceId is
100// nil, then the eventual capture is stopped and library objects are
101// disconnected. Returns YES on sucess, NO otherwise. This method should not be
102// called during capture.
103- (BOOL)setCaptureDevice:(NSString*)deviceId;
104
105// Configures the capture properties for the capture session and the video data
106// output; this means it MUST be called after setCaptureDevice:. Return YES on
107// success, else NO.
108- (BOOL)setCaptureHeight:(int)height
109                   width:(int)width
110               frameRate:(float)frameRate;
111
112// Starts video capturing and register the notification listeners. Must be
113// called after setCaptureDevice:, and, eventually, also after
114// setCaptureHeight:width:frameRate:. Returns YES on sucess, NO otherwise.
115- (BOOL)startCapture;
116
117// Stops video capturing and stops listening to notifications.
118- (void)stopCapture;
119
120@end
121
122#endif  // MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_AVFOUNDATION_MAC_H_
123