• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/video/capture/mac/avfoundation_glue.h"
6
7#include <dlfcn.h>
8
9#include "base/command_line.h"
10#include "base/lazy_instance.h"
11#include "base/mac/mac_util.h"
12#include "media/base/media_switches.h"
13
14namespace {
15
16// This class is used to retrieve AVFoundation NSBundle and library handle. It
17// must be used as a LazyInstance so that it is initialised once and in a
18// thread-safe way. Normally no work is done in constructors: LazyInstance is
19// an exception.
20class AVFoundationInternal {
21 public:
22  AVFoundationInternal() {
23    bundle_ = [NSBundle
24        bundleWithPath:@"/System/Library/Frameworks/AVFoundation.framework"];
25
26    const char* path = [[bundle_ executablePath] fileSystemRepresentation];
27    CHECK(path);
28    library_handle_ = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
29    CHECK(library_handle_) << dlerror();
30  }
31  NSBundle* bundle() const { return bundle_; }
32  void* library_handle() const { return library_handle_; }
33
34 private:
35  NSBundle* bundle_;
36  void* library_handle_;
37
38  DISALLOW_COPY_AND_ASSIGN(AVFoundationInternal);
39};
40
41}  // namespace
42
43static base::LazyInstance<AVFoundationInternal> g_avfoundation_handle =
44    LAZY_INSTANCE_INITIALIZER;
45
46namespace media {
47
48// TODO(mcasas):http://crbug.com/323536 cache the string pointers.
49static NSString* ReadNSStringPtr(const char* symbol) {
50  NSString** string_pointer = reinterpret_cast<NSString**>(
51      dlsym(AVFoundationGlue::AVFoundationLibraryHandle(), symbol));
52  DCHECK(string_pointer) << dlerror();
53  return *string_pointer;
54}
55
56}  // namespace media
57
58bool AVFoundationGlue::IsAVFoundationSupported() {
59  const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
60  return cmd_line->HasSwitch(switches::kEnableAVFoundation) &&
61      base::mac::IsOSLionOrLater() && [AVFoundationBundle() load];
62}
63
64NSBundle const* AVFoundationGlue::AVFoundationBundle() {
65  return g_avfoundation_handle.Get().bundle();
66}
67
68void* AVFoundationGlue::AVFoundationLibraryHandle() {
69  return g_avfoundation_handle.Get().library_handle();
70}
71
72NSString* AVFoundationGlue::AVCaptureDeviceWasConnectedNotification() {
73  return media::ReadNSStringPtr("AVCaptureDeviceWasConnectedNotification");
74}
75
76NSString* AVFoundationGlue::AVCaptureDeviceWasDisconnectedNotification() {
77  return media::ReadNSStringPtr("AVCaptureDeviceWasDisconnectedNotification");
78}
79
80NSString* AVFoundationGlue::AVMediaTypeVideo() {
81  return media::ReadNSStringPtr("AVMediaTypeVideo");
82}
83
84NSString* AVFoundationGlue::AVMediaTypeAudio() {
85  return media::ReadNSStringPtr("AVMediaTypeAudio");
86}
87
88NSString* AVFoundationGlue::AVMediaTypeMuxed() {
89  return media::ReadNSStringPtr("AVMediaTypeMuxed");
90}
91
92NSString* AVFoundationGlue::AVCaptureSessionRuntimeErrorNotification() {
93  return media::ReadNSStringPtr("AVCaptureSessionRuntimeErrorNotification");
94}
95
96NSString* AVFoundationGlue::AVCaptureSessionDidStopRunningNotification() {
97  return media::ReadNSStringPtr("AVCaptureSessionDidStopRunningNotification");
98}
99
100NSString* AVFoundationGlue::AVCaptureSessionErrorKey() {
101  return media::ReadNSStringPtr("AVCaptureSessionErrorKey");
102}
103
104NSString* AVFoundationGlue::AVCaptureSessionPreset320x240() {
105  return media::ReadNSStringPtr("AVCaptureSessionPreset320x240");
106}
107
108NSString* AVFoundationGlue::AVCaptureSessionPreset640x480() {
109  return media::ReadNSStringPtr("AVCaptureSessionPreset640x480");
110}
111
112NSString* AVFoundationGlue::AVCaptureSessionPreset1280x720() {
113  return media::ReadNSStringPtr("AVCaptureSessionPreset1280x720");
114}
115
116NSString* AVFoundationGlue::AVVideoScalingModeKey() {
117  return media::ReadNSStringPtr("AVVideoScalingModeKey");
118}
119
120NSString* AVFoundationGlue::AVVideoScalingModeResizeAspect() {
121  return media::ReadNSStringPtr("AVVideoScalingModeResizeAspect");
122}
123
124Class AVFoundationGlue::AVCaptureSessionClass() {
125  return [AVFoundationBundle() classNamed:@"AVCaptureSession"];
126}
127
128Class AVFoundationGlue::AVCaptureVideoDataOutputClass() {
129  return [AVFoundationBundle() classNamed:@"AVCaptureVideoDataOutput"];
130}
131
132@implementation AVCaptureDeviceGlue
133
134+ (NSArray*)devices {
135  Class avcClass =
136      [AVFoundationGlue::AVFoundationBundle() classNamed:@"AVCaptureDevice"];
137  if ([avcClass respondsToSelector:@selector(devices)]) {
138    return [avcClass performSelector:@selector(devices)];
139  }
140  return nil;
141}
142
143+ (CrAVCaptureDevice*)deviceWithUniqueID:(NSString*)deviceUniqueID {
144  Class avcClass =
145      [AVFoundationGlue::AVFoundationBundle() classNamed:@"AVCaptureDevice"];
146  return [avcClass performSelector:@selector(deviceWithUniqueID:)
147                        withObject:deviceUniqueID];
148}
149
150@end  // @implementation AVCaptureDeviceGlue
151
152@implementation AVCaptureDeviceInputGlue
153
154+ (CrAVCaptureDeviceInput*)deviceInputWithDevice:(CrAVCaptureDevice*)device
155                                           error:(NSError**)outError {
156  return [[AVFoundationGlue::AVFoundationBundle()
157      classNamed:@"AVCaptureDeviceInput"] deviceInputWithDevice:device
158                                                          error:outError];
159}
160
161@end  // @implementation AVCaptureDeviceInputGlue
162