Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / media / base / mac / videotoolbox_glue.mm
blob18a4f0017b48cdaf7feecc73b12a2141c953a39f
1 // Copyright 2014 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.
5 #include "media/base/mac/videotoolbox_glue.h"
7 #include <dlfcn.h>
8 #import <Foundation/Foundation.h>
10 #include "base/lazy_instance.h"
11 #include "base/memory/scoped_ptr.h"
13 // This class stores VideoToolbox library symbol pointers.
14 struct VideoToolboxGlue::Library {
15   typedef OSStatus (*VTCompressionSessionCreateMethod)(
16       CFAllocatorRef,
17       int32_t,
18       int32_t,
19       CoreMediaGlue::CMVideoCodecType,
20       CFDictionaryRef,
21       CFDictionaryRef,
22       CFAllocatorRef,
23       VTCompressionOutputCallback,
24       void*,
25       VTCompressionSessionRef*);
26   typedef OSStatus (*VTCompressionSessionEncodeFrameMethod)(
27       VTCompressionSessionRef,
28       CVImageBufferRef,
29       CoreMediaGlue::CMTime,
30       CoreMediaGlue::CMTime,
31       CFDictionaryRef,
32       void*,
33       VTEncodeInfoFlags*);
34   typedef CVPixelBufferPoolRef (*VTCompressionSessionGetPixelBufferPoolMethod)(
35       VTCompressionSessionRef);
36   typedef void (*VTCompressionSessionInvalidateMethod)(VTCompressionSessionRef);
37   typedef OSStatus (*VTCompressionSessionCompleteFramesMethod)(
38       VTCompressionSessionRef,
39       CoreMediaGlue::CMTime);
40   typedef OSStatus (*VTSessionSetPropertyMethod)(VTSessionRef,
41                                                  CFStringRef,
42                                                  CFTypeRef);
44   VTCompressionSessionCreateMethod VTCompressionSessionCreate;
45   VTCompressionSessionEncodeFrameMethod VTCompressionSessionEncodeFrame;
46   VTCompressionSessionGetPixelBufferPoolMethod
47       VTCompressionSessionGetPixelBufferPool;
48   VTCompressionSessionInvalidateMethod VTCompressionSessionInvalidate;
49   VTCompressionSessionCompleteFramesMethod VTCompressionSessionCompleteFrames;
50   VTSessionSetPropertyMethod VTSessionSetProperty;
52   CFStringRef* kVTCompressionPropertyKey_AllowFrameReordering;
53   CFStringRef* kVTCompressionPropertyKey_AverageBitRate;
54   CFStringRef* kVTCompressionPropertyKey_ColorPrimaries;
55   CFStringRef* kVTCompressionPropertyKey_ExpectedFrameRate;
56   CFStringRef* kVTCompressionPropertyKey_MaxFrameDelayCount;
57   CFStringRef* kVTCompressionPropertyKey_MaxKeyFrameInterval;
58   CFStringRef* kVTCompressionPropertyKey_MaxKeyFrameIntervalDuration;
59   CFStringRef* kVTCompressionPropertyKey_ProfileLevel;
60   CFStringRef* kVTCompressionPropertyKey_RealTime;
61   CFStringRef* kVTCompressionPropertyKey_TransferFunction;
62   CFStringRef* kVTCompressionPropertyKey_YCbCrMatrix;
63   CFStringRef* kVTEncodeFrameOptionKey_ForceKeyFrame;
64   CFStringRef* kVTProfileLevel_H264_Baseline_AutoLevel;
65   CFStringRef* kVTProfileLevel_H264_Main_AutoLevel;
66   CFStringRef* kVTProfileLevel_H264_Extended_AutoLevel;
67   CFStringRef* kVTProfileLevel_H264_High_AutoLevel;
68   CFStringRef*
69       kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder;
72 // Lazy-instance responsible for loading VideoToolbox.
73 class VideoToolboxGlue::Loader {
74  public:
75   Loader() {
76     NSBundle* bundle = [NSBundle
77         bundleWithPath:@"/System/Library/Frameworks/VideoToolbox.framework"];
78     const char* path = [[bundle executablePath] fileSystemRepresentation];
79     if (!path)
80       return;
82     handle_ = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
83     if (!handle_)
84       return;
86 #define LOAD_SYMBOL(SYMBOL)                                             \
87   if (!LoadSymbol(#SYMBOL, reinterpret_cast<void**>(&library_.SYMBOL))) \
88     return;
90     LOAD_SYMBOL(VTCompressionSessionCreate)
91     LOAD_SYMBOL(VTCompressionSessionEncodeFrame)
92     LOAD_SYMBOL(VTCompressionSessionGetPixelBufferPool)
93     LOAD_SYMBOL(VTCompressionSessionInvalidate)
94     LOAD_SYMBOL(VTCompressionSessionCompleteFrames)
95     LOAD_SYMBOL(VTSessionSetProperty)
97     LOAD_SYMBOL(kVTCompressionPropertyKey_AllowFrameReordering)
98     LOAD_SYMBOL(kVTCompressionPropertyKey_AverageBitRate)
99     LOAD_SYMBOL(kVTCompressionPropertyKey_ColorPrimaries)
100     LOAD_SYMBOL(kVTCompressionPropertyKey_ExpectedFrameRate)
101     LOAD_SYMBOL(kVTCompressionPropertyKey_MaxFrameDelayCount)
102     LOAD_SYMBOL(kVTCompressionPropertyKey_MaxKeyFrameInterval)
103     LOAD_SYMBOL(kVTCompressionPropertyKey_MaxKeyFrameIntervalDuration)
104     LOAD_SYMBOL(kVTCompressionPropertyKey_ProfileLevel)
105     LOAD_SYMBOL(kVTCompressionPropertyKey_RealTime)
106     LOAD_SYMBOL(kVTCompressionPropertyKey_TransferFunction)
107     LOAD_SYMBOL(kVTCompressionPropertyKey_YCbCrMatrix)
108     LOAD_SYMBOL(kVTEncodeFrameOptionKey_ForceKeyFrame);
109     LOAD_SYMBOL(kVTProfileLevel_H264_Baseline_AutoLevel)
110     LOAD_SYMBOL(kVTProfileLevel_H264_Main_AutoLevel)
111     LOAD_SYMBOL(kVTProfileLevel_H264_Extended_AutoLevel)
112     LOAD_SYMBOL(kVTProfileLevel_H264_High_AutoLevel)
113     LOAD_SYMBOL(
114         kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder)
116 #undef LOAD_SYMBOL
118     glue_.library_ = &library_;
119   }
121   const VideoToolboxGlue* glue() const {
122     return (glue_.library_) ? &glue_ : NULL;
123   }
125  private:
126   bool LoadSymbol(const char* name, void** symbol_out) {
127     *symbol_out = dlsym(handle_, name);
128     return *symbol_out != NULL;
129   }
131   Library library_;
132   VideoToolboxGlue glue_;
133   void* handle_;
135   DISALLOW_COPY_AND_ASSIGN(Loader);
138 static base::LazyInstance<VideoToolboxGlue::Loader> g_videotoolbox_loader =
139     LAZY_INSTANCE_INITIALIZER;
141 // static
142 const VideoToolboxGlue* VideoToolboxGlue::Get() {
143   return g_videotoolbox_loader.Get().glue();
146 VideoToolboxGlue::VideoToolboxGlue() : library_(NULL) {
149 OSStatus VideoToolboxGlue::VTCompressionSessionCreate(
150     CFAllocatorRef allocator,
151     int32_t width,
152     int32_t height,
153     CoreMediaGlue::CMVideoCodecType codecType,
154     CFDictionaryRef encoderSpecification,
155     CFDictionaryRef sourceImageBufferAttributes,
156     CFAllocatorRef compressedDataAllocator,
157     VTCompressionOutputCallback outputCallback,
158     void* outputCallbackRefCon,
159     VTCompressionSessionRef* compressionSessionOut) const {
160   return library_->VTCompressionSessionCreate(allocator,
161                                               width,
162                                               height,
163                                               codecType,
164                                               encoderSpecification,
165                                               sourceImageBufferAttributes,
166                                               compressedDataAllocator,
167                                               outputCallback,
168                                               outputCallbackRefCon,
169                                               compressionSessionOut);
172 OSStatus VideoToolboxGlue::VTCompressionSessionEncodeFrame(
173     VTCompressionSessionRef session,
174     CVImageBufferRef imageBuffer,
175     CoreMediaGlue::CMTime presentationTimeStamp,
176     CoreMediaGlue::CMTime duration,
177     CFDictionaryRef frameProperties,
178     void* sourceFrameRefCon,
179     VTEncodeInfoFlags* infoFlagsOut) const {
180   return library_->VTCompressionSessionEncodeFrame(session,
181                                                    imageBuffer,
182                                                    presentationTimeStamp,
183                                                    duration,
184                                                    frameProperties,
185                                                    sourceFrameRefCon,
186                                                    infoFlagsOut);
189 CVPixelBufferPoolRef VideoToolboxGlue::VTCompressionSessionGetPixelBufferPool(
190     VTCompressionSessionRef session) const {
191   return library_->VTCompressionSessionGetPixelBufferPool(session);
194 void VideoToolboxGlue::VTCompressionSessionInvalidate(
195     VTCompressionSessionRef session) const {
196   library_->VTCompressionSessionInvalidate(session);
199 OSStatus VideoToolboxGlue::VTCompressionSessionCompleteFrames(
200     VTCompressionSessionRef session,
201     CoreMediaGlue::CMTime completeUntilPresentationTimeStamp) const {
202   return library_->VTCompressionSessionCompleteFrames(
203       session, completeUntilPresentationTimeStamp);
206 OSStatus VideoToolboxGlue::VTSessionSetProperty(VTSessionRef session,
207                                                 CFStringRef propertyKey,
208                                                 CFTypeRef propertyValue) const {
209   return library_->VTSessionSetProperty(session, propertyKey, propertyValue);
212 #define KEY_ACCESSOR(KEY) \
213   CFStringRef VideoToolboxGlue::KEY() const { return *library_->KEY; }
215 KEY_ACCESSOR(kVTCompressionPropertyKey_AllowFrameReordering)
216 KEY_ACCESSOR(kVTCompressionPropertyKey_AverageBitRate)
217 KEY_ACCESSOR(kVTCompressionPropertyKey_ColorPrimaries)
218 KEY_ACCESSOR(kVTCompressionPropertyKey_ExpectedFrameRate)
219 KEY_ACCESSOR(kVTCompressionPropertyKey_MaxFrameDelayCount)
220 KEY_ACCESSOR(kVTCompressionPropertyKey_MaxKeyFrameInterval)
221 KEY_ACCESSOR(kVTCompressionPropertyKey_MaxKeyFrameIntervalDuration)
222 KEY_ACCESSOR(kVTCompressionPropertyKey_ProfileLevel)
223 KEY_ACCESSOR(kVTCompressionPropertyKey_RealTime)
224 KEY_ACCESSOR(kVTCompressionPropertyKey_TransferFunction)
225 KEY_ACCESSOR(kVTCompressionPropertyKey_YCbCrMatrix)
226 KEY_ACCESSOR(kVTEncodeFrameOptionKey_ForceKeyFrame)
227 KEY_ACCESSOR(kVTProfileLevel_H264_Baseline_AutoLevel)
228 KEY_ACCESSOR(kVTProfileLevel_H264_Main_AutoLevel)
229 KEY_ACCESSOR(kVTProfileLevel_H264_Extended_AutoLevel)
230 KEY_ACCESSOR(kVTProfileLevel_H264_High_AutoLevel)
231 KEY_ACCESSOR(kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder)
233 #undef KEY_ACCESSOR