1/*
2 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11/*
12 *  video_capture_mac.cc
13 *
14 */
15
16#include <QuickTime/QuickTime.h>
17
18#include "webrtc/modules/video_capture/device_info_impl.h"
19#include "webrtc/modules/video_capture/video_capture_config.h"
20#include "webrtc/modules/video_capture/video_capture_impl.h"
21#include "webrtc/system_wrappers/interface/ref_count.h"
22#include "webrtc/system_wrappers/interface/trace.h"
23
24// 10.4 support must be decided runtime. We will just decide which framework to
25// use at compile time "work" classes. One for QTKit, one for QuickTime
26#if __MAC_OS_X_VERSION_MIN_REQUIRED == __MAC_10_4 // QuickTime version
27#include <QuickTime/video_capture_quick_time.h>
28#include <QuickTime/video_capture_quick_time_info.h>
29#else
30#include "webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit.h"
31#include "webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_info.h"
32#endif
33
34namespace webrtc
35{
36namespace videocapturemodule
37{
38
39// static
40bool CheckOSVersion()
41{
42    // Check OSX version
43    OSErr err = noErr;
44
45    SInt32 version;
46
47    err = Gestalt(gestaltSystemVersion, &version);
48    if (err != noErr)
49    {
50        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, 0,
51                     "Could not get OS version");
52        return false;
53    }
54
55    if (version < 0x00001040) // Older version than Mac OSX 10.4
56    {
57        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, 0,
58                     "OS version too old: 0x%x", version);
59        return false;
60    }
61
62    WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, 0,
63                 "OS version compatible: 0x%x", version);
64
65    return true;
66}
67
68// static
69bool CheckQTVersion()
70{
71    // Check OSX version
72    OSErr err = noErr;
73
74    SInt32 version;
75
76    err = Gestalt(gestaltQuickTime, &version);
77    if (err != noErr)
78    {
79        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, 0,
80                     "Could not get QuickTime version");
81        return false;
82    }
83
84    if (version < 0x07000000) // QT v. 7.x or newer (QT 5.0.2 0x05020000)
85    {
86        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, 0,
87                     "QuickTime version too old: 0x%x", version);
88        return false;
89    }
90
91    WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, 0,
92                 "QuickTime version compatible: 0x%x", version);
93    return true;
94}
95
96/**************************************************************************
97 *
98 *    Create/Destroy a VideoCaptureModule
99 *
100 ***************************************************************************/
101
102/*
103 *   Returns version of the module and its components
104 *
105 *   version                 - buffer to which the version will be written
106 *   remainingBufferInBytes  - remaining number of int8_t in the version
107 *                             buffer
108 *   position                - position of the next empty int8_t in the
109 *                             version buffer
110 */
111
112VideoCaptureModule* VideoCaptureImpl::Create(
113    const int32_t id, const char* deviceUniqueIdUTF8)
114{
115
116    if (webrtc::videocapturemodule::CheckOSVersion() == false)
117    {
118        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, id,
119                     "OS version is too old. Could not create video capture "
120                     "module. Returning NULL");
121        return NULL;
122    }
123
124#if __MAC_OS_X_VERSION_MIN_REQUIRED == __MAC_10_4 // QuickTime version
125    if (webrtc::videocapturemodule::CheckQTVersion() == false)
126    {
127        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, id,
128                     "QuickTime version is too old. Could not create video "
129                     "capture module. Returning NULL");
130        return NULL;
131    }
132
133    WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, id,
134                 "%s line %d. QTKit is not supported on this machine. Using "
135                 "QuickTime framework to capture video",
136                 __FILE__, __LINE__);
137
138    RefCountImpl<videocapturemodule::VideoCaptureMacQuickTime>*
139        newCaptureModule =
140            new RefCountImpl<videocapturemodule::VideoCaptureMacQuickTime>(id);
141
142    if (!newCaptureModule)
143    {
144        WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, id,
145                     "could not Create for unique device %s, !newCaptureModule",
146                     deviceUniqueIdUTF8);
147        return NULL;
148    }
149
150    if (newCaptureModule->Init(id, deviceUniqueIdUTF8) != 0)
151    {
152        WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, id,
153                     "could not Create for unique device %s, "
154                     "newCaptureModule->Init()!=0",
155                     deviceUniqueIdUTF8);
156        delete newCaptureModule;
157        return NULL;
158    }
159
160    // Successfully created VideoCaptureMacQuicktime. Return it
161    WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, id,
162                 "Module created for unique device %s. Will use QuickTime "
163                 "framework to capture",
164                 deviceUniqueIdUTF8);
165    return newCaptureModule;
166
167#else // QTKit version
168
169    WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, id,
170                 "Using QTKit framework to capture video", id);
171
172    RefCountImpl<videocapturemodule::VideoCaptureMacQTKit>* newCaptureModule =
173        new RefCountImpl<videocapturemodule::VideoCaptureMacQTKit>(id);
174
175    if(!newCaptureModule)
176    {
177        WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, id,
178                     "could not Create for unique device %s, !newCaptureModule",
179                     deviceUniqueIdUTF8);
180        return NULL;
181    }
182    if(newCaptureModule->Init(id, deviceUniqueIdUTF8) != 0)
183    {
184        WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, id,
185                     "could not Create for unique device %s, "
186                     "newCaptureModule->Init()!=0", deviceUniqueIdUTF8);
187        delete newCaptureModule;
188        return NULL;
189    }
190
191    // Successfully created VideoCaptureMacQuicktime. Return it
192    WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, id,
193                 "Module created for unique device %s, will use QTKit "
194                 "framework",deviceUniqueIdUTF8);
195    return newCaptureModule;
196#endif
197}
198
199/**************************************************************************
200 *
201 *    Create/Destroy a DeviceInfo
202 *
203 ***************************************************************************/
204
205VideoCaptureModule::DeviceInfo*
206VideoCaptureImpl::CreateDeviceInfo(const int32_t id)
207{
208
209
210    if (webrtc::videocapturemodule::CheckOSVersion() == false)
211    {
212        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, id,
213                     "OS version is too old. Could not create video capture "
214                     "module. Returning NULL");
215        return NULL;
216    }
217
218#if __MAC_OS_X_VERSION_MIN_REQUIRED == __MAC_10_4 // QuickTime version
219    if (webrtc::videocapturemodule::CheckQTVersion() == false)
220    {
221        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, id,
222                     "QuickTime version is too old. Could not create video "
223                     "capture module. Returning NULL");
224        return NULL;
225    }
226
227    webrtc::videocapturemodule::VideoCaptureMacQuickTimeInfo* newCaptureInfoModule =
228        new webrtc::videocapturemodule::VideoCaptureMacQuickTimeInfo(id);
229
230    if (!newCaptureInfoModule || newCaptureInfoModule->Init() != 0)
231    {
232        Destroy(newCaptureInfoModule);
233        newCaptureInfoModule = NULL;
234        WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, id,
235                     "Failed to Init newCaptureInfoModule created with id %d "
236                     "and device \"\" ", id);
237        return NULL;
238    }
239    WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, id,
240                 "VideoCaptureModule created for id", id);
241    return newCaptureInfoModule;
242
243#else // QTKit version
244    webrtc::videocapturemodule::VideoCaptureMacQTKitInfo* newCaptureInfoModule =
245        new webrtc::videocapturemodule::VideoCaptureMacQTKitInfo(id);
246
247    if(!newCaptureInfoModule || newCaptureInfoModule->Init() != 0)
248    {
249        //Destroy(newCaptureInfoModule);
250        delete newCaptureInfoModule;
251        newCaptureInfoModule = NULL;
252        WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, id,
253                     "Failed to Init newCaptureInfoModule created with id %d "
254                     "and device \"\" ", id);
255        return NULL;
256    }
257    WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, id,
258                 "VideoCaptureModule created for id", id);
259    return newCaptureInfoModule;
260
261#endif
262
263}
264
265/**************************************************************************
266 *
267 *    End Create/Destroy VideoCaptureModule
268 *
269 ***************************************************************************/
270}  // namespace videocapturemodule
271}  // namespace webrtc
272