blob: 010767c8ee140cb923bbdb00d26d5a9b99e091a1 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/base/mac/videotoolbox_glue.h"
#include <dlfcn.h>
#import <Foundation/Foundation.h>
#include "base/lazy_instance.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
// This class stores VideoToolbox library symbol pointers.
struct VideoToolboxGlue::Library {
typedef OSStatus (*VTCompressionSessionCreateMethod)(
CFAllocatorRef,
int32_t,
int32_t,
CoreMediaGlue::CMVideoCodecType,
CFDictionaryRef,
CFDictionaryRef,
CFAllocatorRef,
VTCompressionOutputCallback,
void*,
VTCompressionSessionRef*);
typedef OSStatus (*VTCompressionSessionEncodeFrameMethod)(
VTCompressionSessionRef,
CVImageBufferRef,
CoreMediaGlue::CMTime,
CoreMediaGlue::CMTime,
CFDictionaryRef,
void*,
VTEncodeInfoFlags*);
typedef CVPixelBufferPoolRef (*VTCompressionSessionGetPixelBufferPoolMethod)(
VTCompressionSessionRef);
typedef void (*VTCompressionSessionInvalidateMethod)(VTCompressionSessionRef);
typedef OSStatus (*VTCompressionSessionCompleteFramesMethod)(
VTCompressionSessionRef,
CoreMediaGlue::CMTime);
typedef OSStatus (*VTSessionSetPropertyMethod)(VTSessionRef,
CFStringRef,
CFTypeRef);
VTCompressionSessionCreateMethod VTCompressionSessionCreate;
VTCompressionSessionEncodeFrameMethod VTCompressionSessionEncodeFrame;
VTCompressionSessionGetPixelBufferPoolMethod
VTCompressionSessionGetPixelBufferPool;
VTCompressionSessionInvalidateMethod VTCompressionSessionInvalidate;
VTCompressionSessionCompleteFramesMethod VTCompressionSessionCompleteFrames;
VTSessionSetPropertyMethod VTSessionSetProperty;
CFStringRef* kVTCompressionPropertyKey_AllowFrameReordering;
CFStringRef* kVTCompressionPropertyKey_AverageBitRate;
CFStringRef* kVTCompressionPropertyKey_ColorPrimaries;
CFStringRef* kVTCompressionPropertyKey_ExpectedFrameRate;
CFStringRef* kVTCompressionPropertyKey_MaxFrameDelayCount;
CFStringRef* kVTCompressionPropertyKey_MaxKeyFrameInterval;
CFStringRef* kVTCompressionPropertyKey_MaxKeyFrameIntervalDuration;
CFStringRef* kVTCompressionPropertyKey_ProfileLevel;
CFStringRef* kVTCompressionPropertyKey_RealTime;
CFStringRef* kVTCompressionPropertyKey_TransferFunction;
CFStringRef* kVTCompressionPropertyKey_YCbCrMatrix;
CFStringRef* kVTEncodeFrameOptionKey_ForceKeyFrame;
CFStringRef* kVTProfileLevel_H264_Baseline_AutoLevel;
CFStringRef* kVTProfileLevel_H264_Main_AutoLevel;
CFStringRef* kVTProfileLevel_H264_Extended_AutoLevel;
CFStringRef* kVTProfileLevel_H264_High_AutoLevel;
CFStringRef*
kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder;
};
// Lazy-instance responsible for loading VideoToolbox.
class VideoToolboxGlue::Loader {
public:
Loader() {
NSBundle* bundle = [NSBundle
bundleWithPath:@"/System/Library/Frameworks/VideoToolbox.framework"];
const char* path = [[bundle executablePath] fileSystemRepresentation];
if (!path)
return;
handle_ = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
if (!handle_)
return;
#define LOAD_SYMBOL(SYMBOL) \
if (!LoadSymbol(#SYMBOL, reinterpret_cast<void**>(&library_.SYMBOL))) \
return;
LOAD_SYMBOL(VTCompressionSessionCreate)
LOAD_SYMBOL(VTCompressionSessionEncodeFrame)
LOAD_SYMBOL(VTCompressionSessionGetPixelBufferPool)
LOAD_SYMBOL(VTCompressionSessionInvalidate)
LOAD_SYMBOL(VTCompressionSessionCompleteFrames)
LOAD_SYMBOL(VTSessionSetProperty)
LOAD_SYMBOL(kVTCompressionPropertyKey_AllowFrameReordering)
LOAD_SYMBOL(kVTCompressionPropertyKey_AverageBitRate)
LOAD_SYMBOL(kVTCompressionPropertyKey_ColorPrimaries)
LOAD_SYMBOL(kVTCompressionPropertyKey_ExpectedFrameRate)
LOAD_SYMBOL(kVTCompressionPropertyKey_MaxFrameDelayCount)
LOAD_SYMBOL(kVTCompressionPropertyKey_MaxKeyFrameInterval)
LOAD_SYMBOL(kVTCompressionPropertyKey_MaxKeyFrameIntervalDuration)
LOAD_SYMBOL(kVTCompressionPropertyKey_ProfileLevel)
LOAD_SYMBOL(kVTCompressionPropertyKey_RealTime)
LOAD_SYMBOL(kVTCompressionPropertyKey_TransferFunction)
LOAD_SYMBOL(kVTCompressionPropertyKey_YCbCrMatrix)
LOAD_SYMBOL(kVTEncodeFrameOptionKey_ForceKeyFrame);
LOAD_SYMBOL(kVTProfileLevel_H264_Baseline_AutoLevel)
LOAD_SYMBOL(kVTProfileLevel_H264_Main_AutoLevel)
LOAD_SYMBOL(kVTProfileLevel_H264_Extended_AutoLevel)
LOAD_SYMBOL(kVTProfileLevel_H264_High_AutoLevel)
LOAD_SYMBOL(
kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder)
#undef LOAD_SYMBOL
glue_.library_ = &library_;
}
const VideoToolboxGlue* glue() const {
return (glue_.library_) ? &glue_ : NULL;
}
private:
bool LoadSymbol(const char* name, void** symbol_out) {
*symbol_out = dlsym(handle_, name);
return *symbol_out != NULL;
}
Library library_;
VideoToolboxGlue glue_;
void* handle_;
DISALLOW_COPY_AND_ASSIGN(Loader);
};
static base::LazyInstance<VideoToolboxGlue::Loader> g_videotoolbox_loader =
LAZY_INSTANCE_INITIALIZER;
// static
const VideoToolboxGlue* VideoToolboxGlue::Get() {
return g_videotoolbox_loader.Get().glue();
}
VideoToolboxGlue::VideoToolboxGlue() : library_(NULL) {
}
OSStatus VideoToolboxGlue::VTCompressionSessionCreate(
CFAllocatorRef allocator,
int32_t width,
int32_t height,
CoreMediaGlue::CMVideoCodecType codecType,
CFDictionaryRef encoderSpecification,
CFDictionaryRef sourceImageBufferAttributes,
CFAllocatorRef compressedDataAllocator,
VTCompressionOutputCallback outputCallback,
void* outputCallbackRefCon,
VTCompressionSessionRef* compressionSessionOut) const {
return library_->VTCompressionSessionCreate(allocator,
width,
height,
codecType,
encoderSpecification,
sourceImageBufferAttributes,
compressedDataAllocator,
outputCallback,
outputCallbackRefCon,
compressionSessionOut);
}
OSStatus VideoToolboxGlue::VTCompressionSessionEncodeFrame(
VTCompressionSessionRef session,
CVImageBufferRef imageBuffer,
CoreMediaGlue::CMTime presentationTimeStamp,
CoreMediaGlue::CMTime duration,
CFDictionaryRef frameProperties,
void* sourceFrameRefCon,
VTEncodeInfoFlags* infoFlagsOut) const {
return library_->VTCompressionSessionEncodeFrame(session,
imageBuffer,
presentationTimeStamp,
duration,
frameProperties,
sourceFrameRefCon,
infoFlagsOut);
}
CVPixelBufferPoolRef VideoToolboxGlue::VTCompressionSessionGetPixelBufferPool(
VTCompressionSessionRef session) const {
return library_->VTCompressionSessionGetPixelBufferPool(session);
}
void VideoToolboxGlue::VTCompressionSessionInvalidate(
VTCompressionSessionRef session) const {
library_->VTCompressionSessionInvalidate(session);
}
OSStatus VideoToolboxGlue::VTCompressionSessionCompleteFrames(
VTCompressionSessionRef session,
CoreMediaGlue::CMTime completeUntilPresentationTimeStamp) const {
return library_->VTCompressionSessionCompleteFrames(
session, completeUntilPresentationTimeStamp);
}
OSStatus VideoToolboxGlue::VTSessionSetProperty(VTSessionRef session,
CFStringRef propertyKey,
CFTypeRef propertyValue) const {
return library_->VTSessionSetProperty(session, propertyKey, propertyValue);
}
#define KEY_ACCESSOR(KEY) \
CFStringRef VideoToolboxGlue::KEY() const { return *library_->KEY; }
KEY_ACCESSOR(kVTCompressionPropertyKey_AllowFrameReordering)
KEY_ACCESSOR(kVTCompressionPropertyKey_AverageBitRate)
KEY_ACCESSOR(kVTCompressionPropertyKey_ColorPrimaries)
KEY_ACCESSOR(kVTCompressionPropertyKey_ExpectedFrameRate)
KEY_ACCESSOR(kVTCompressionPropertyKey_MaxFrameDelayCount)
KEY_ACCESSOR(kVTCompressionPropertyKey_MaxKeyFrameInterval)
KEY_ACCESSOR(kVTCompressionPropertyKey_MaxKeyFrameIntervalDuration)
KEY_ACCESSOR(kVTCompressionPropertyKey_ProfileLevel)
KEY_ACCESSOR(kVTCompressionPropertyKey_RealTime)
KEY_ACCESSOR(kVTCompressionPropertyKey_TransferFunction)
KEY_ACCESSOR(kVTCompressionPropertyKey_YCbCrMatrix)
KEY_ACCESSOR(kVTEncodeFrameOptionKey_ForceKeyFrame)
KEY_ACCESSOR(kVTProfileLevel_H264_Baseline_AutoLevel)
KEY_ACCESSOR(kVTProfileLevel_H264_Main_AutoLevel)
KEY_ACCESSOR(kVTProfileLevel_H264_Extended_AutoLevel)
KEY_ACCESSOR(kVTProfileLevel_H264_High_AutoLevel)
KEY_ACCESSOR(kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder)
#undef KEY_ACCESSOR