OLD | NEW |
| (Empty) |
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 #import "media/base/mac/avfoundation_glue.h" | |
6 | |
7 #import <AVFoundation/AVFoundation.h> | |
8 #include <dlfcn.h> | |
9 #include <stddef.h> | |
10 | |
11 #include "base/command_line.h" | |
12 #include "base/lazy_instance.h" | |
13 #include "base/mac/mac_util.h" | |
14 #include "base/macros.h" | |
15 #include "base/metrics/histogram.h" | |
16 #include "base/trace_event/trace_event.h" | |
17 #include "media/base/media_switches.h" | |
18 | |
19 namespace { | |
20 // This class is used to retrieve AVFoundation NSBundle and library handle. It | |
21 // must be used as a LazyInstance so that it is initialised once and in a | |
22 // thread-safe way. Normally no work is done in constructors: LazyInstance is | |
23 // an exception. | |
24 class AVFoundationInternal { | |
25 public: | |
26 AVFoundationInternal() { | |
27 bundle_ = [NSBundle | |
28 bundleWithPath:@"/System/Library/Frameworks/AVFoundation.framework"]; | |
29 } | |
30 | |
31 NSBundle* bundle() const { return bundle_; } | |
32 | |
33 NSString* AVCaptureDeviceWasConnectedNotification() const { | |
34 return AVCaptureDeviceWasConnectedNotification_; | |
35 } | |
36 NSString* AVCaptureDeviceWasDisconnectedNotification() const { | |
37 return AVCaptureDeviceWasDisconnectedNotification_; | |
38 } | |
39 NSString* AVMediaTypeVideo() const { return AVMediaTypeVideo_; } | |
40 NSString* AVMediaTypeAudio() const { return AVMediaTypeAudio_; } | |
41 NSString* AVMediaTypeMuxed() const { return AVMediaTypeMuxed_; } | |
42 NSString* AVCaptureSessionRuntimeErrorNotification() const { | |
43 return AVCaptureSessionRuntimeErrorNotification_; | |
44 } | |
45 NSString* AVCaptureSessionDidStopRunningNotification() const { | |
46 return AVCaptureSessionDidStopRunningNotification_; | |
47 } | |
48 NSString* AVCaptureSessionErrorKey() const { | |
49 return AVCaptureSessionErrorKey_; | |
50 } | |
51 NSString* AVVideoScalingModeKey() const { return AVVideoScalingModeKey_; } | |
52 NSString* AVVideoScalingModeResizeAspectFill() const { | |
53 return AVVideoScalingModeResizeAspectFill_; | |
54 } | |
55 | |
56 private: | |
57 NSBundle* bundle_; | |
58 // The following members are replicas of the respectives in AVFoundation. | |
59 NSString* AVCaptureDeviceWasConnectedNotification_ = | |
60 ::AVCaptureDeviceWasConnectedNotification; | |
61 NSString* AVCaptureDeviceWasDisconnectedNotification_ = | |
62 ::AVCaptureDeviceWasDisconnectedNotification; | |
63 NSString* AVMediaTypeVideo_ = ::AVMediaTypeVideo; | |
64 NSString* AVMediaTypeAudio_ = ::AVMediaTypeAudio; | |
65 NSString* AVMediaTypeMuxed_ = ::AVMediaTypeMuxed; | |
66 NSString* AVCaptureSessionRuntimeErrorNotification_ = | |
67 ::AVCaptureSessionRuntimeErrorNotification; | |
68 NSString* AVCaptureSessionDidStopRunningNotification_ = | |
69 ::AVCaptureSessionDidStopRunningNotification; | |
70 NSString* AVCaptureSessionErrorKey_ = ::AVCaptureSessionErrorKey; | |
71 NSString* AVVideoScalingModeKey_ = ::AVVideoScalingModeKey; | |
72 NSString* AVVideoScalingModeResizeAspectFill_ = | |
73 ::AVVideoScalingModeResizeAspectFill; | |
74 | |
75 DISALLOW_COPY_AND_ASSIGN(AVFoundationInternal); | |
76 }; | |
77 | |
78 static base::ThreadLocalStorage::StaticSlot g_avfoundation_handle = | |
79 TLS_INITIALIZER; | |
80 | |
81 void TlsCleanup(void* value) { | |
82 delete static_cast<AVFoundationInternal*>(value); | |
83 } | |
84 | |
85 AVFoundationInternal* GetAVFoundationInternal() { | |
86 return static_cast<AVFoundationInternal*>(g_avfoundation_handle.Get()); | |
87 } | |
88 | |
89 // This contains the logic of checking whether AVFoundation is supported. | |
90 // It's called only once and the results are cached in a static bool. | |
91 bool LoadAVFoundationInternal() { | |
92 g_avfoundation_handle.Initialize(TlsCleanup); | |
93 g_avfoundation_handle.Set(new AVFoundationInternal()); | |
94 const bool ret = [AVFoundationGlue::AVFoundationBundle() load]; | |
95 CHECK(ret); | |
96 return ret; | |
97 } | |
98 | |
99 enum { | |
100 INITIALIZE_NOT_CALLED = 0, | |
101 AVFOUNDATION_IS_SUPPORTED, | |
102 AVFOUNDATION_NOT_SUPPORTED | |
103 } static g_avfoundation_initialization = INITIALIZE_NOT_CALLED; | |
104 | |
105 } // namespace | |
106 | |
107 void AVFoundationGlue::InitializeAVFoundation() { | |
108 TRACE_EVENT0("video", "AVFoundationGlue::InitializeAVFoundation"); | |
109 CHECK([NSThread isMainThread]); | |
110 if (g_avfoundation_initialization != INITIALIZE_NOT_CALLED) | |
111 return; | |
112 g_avfoundation_initialization = LoadAVFoundationInternal() ? | |
113 AVFOUNDATION_IS_SUPPORTED : AVFOUNDATION_NOT_SUPPORTED; | |
114 } | |
115 | |
116 NSBundle const* AVFoundationGlue::AVFoundationBundle() { | |
117 return GetAVFoundationInternal()->bundle(); | |
118 } | |
119 | |
120 NSString* AVFoundationGlue::AVCaptureDeviceWasConnectedNotification() { | |
121 return GetAVFoundationInternal()->AVCaptureDeviceWasConnectedNotification(); | |
122 } | |
123 | |
124 NSString* AVFoundationGlue::AVCaptureDeviceWasDisconnectedNotification() { | |
125 return GetAVFoundationInternal() | |
126 ->AVCaptureDeviceWasDisconnectedNotification(); | |
127 } | |
128 | |
129 NSString* AVFoundationGlue::AVMediaTypeVideo() { | |
130 return GetAVFoundationInternal()->AVMediaTypeVideo(); | |
131 } | |
132 | |
133 NSString* AVFoundationGlue::AVMediaTypeAudio() { | |
134 return GetAVFoundationInternal()->AVMediaTypeAudio(); | |
135 } | |
136 | |
137 NSString* AVFoundationGlue::AVMediaTypeMuxed() { | |
138 return GetAVFoundationInternal()->AVMediaTypeMuxed(); | |
139 } | |
140 | |
141 NSString* AVFoundationGlue::AVCaptureSessionRuntimeErrorNotification() { | |
142 return GetAVFoundationInternal()->AVCaptureSessionRuntimeErrorNotification(); | |
143 } | |
144 | |
145 NSString* AVFoundationGlue::AVCaptureSessionDidStopRunningNotification() { | |
146 return GetAVFoundationInternal() | |
147 ->AVCaptureSessionDidStopRunningNotification(); | |
148 } | |
149 | |
150 NSString* AVFoundationGlue::AVCaptureSessionErrorKey() { | |
151 return GetAVFoundationInternal()->AVCaptureSessionErrorKey(); | |
152 } | |
153 | |
154 NSString* AVFoundationGlue::AVVideoScalingModeKey() { | |
155 return GetAVFoundationInternal()->AVVideoScalingModeKey(); | |
156 } | |
157 | |
158 NSString* AVFoundationGlue::AVVideoScalingModeResizeAspectFill() { | |
159 return GetAVFoundationInternal()->AVVideoScalingModeResizeAspectFill(); | |
160 } | |
161 | |
162 Class AVFoundationGlue::AVCaptureSessionClass() { | |
163 return [AVFoundationBundle() classNamed:@"AVCaptureSession"]; | |
164 } | |
165 | |
166 Class AVFoundationGlue::AVCaptureVideoDataOutputClass() { | |
167 return [AVFoundationBundle() classNamed:@"AVCaptureVideoDataOutput"]; | |
168 } | |
169 | |
170 Class AVFoundationGlue::AVCaptureStillImageOutputClass() { | |
171 return [AVFoundationBundle() classNamed:@"AVCaptureStillImageOutput"]; | |
172 } | |
173 | |
174 @implementation AVCaptureDeviceGlue | |
175 | |
176 + (NSArray*)devices { | |
177 Class avcClass = | |
178 [AVFoundationGlue::AVFoundationBundle() classNamed:@"AVCaptureDevice"]; | |
179 if ([avcClass respondsToSelector:@selector(devices)]) { | |
180 return [avcClass performSelector:@selector(devices)]; | |
181 } | |
182 return nil; | |
183 } | |
184 | |
185 + (CrAVCaptureDevice*)deviceWithUniqueID:(NSString*)deviceUniqueID { | |
186 Class avcClass = | |
187 [AVFoundationGlue::AVFoundationBundle() classNamed:@"AVCaptureDevice"]; | |
188 return [avcClass performSelector:@selector(deviceWithUniqueID:) | |
189 withObject:deviceUniqueID]; | |
190 } | |
191 | |
192 @end // @implementation AVCaptureDeviceGlue | |
193 | |
194 @implementation AVCaptureDeviceInputGlue | |
195 | |
196 + (CrAVCaptureDeviceInput*)deviceInputWithDevice:(CrAVCaptureDevice*)device | |
197 error:(NSError**)outError { | |
198 return [[AVFoundationGlue::AVFoundationBundle() | |
199 classNamed:@"AVCaptureDeviceInput"] deviceInputWithDevice:device | |
200 error:outError]; | |
201 } | |
202 | |
203 @end // @implementation AVCaptureDeviceInputGlue | |
OLD | NEW |