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.
5 #include "media/base/mac/coremedia_glue.h"
8 #import <Foundation/Foundation.h>
10 #include "base/logging.h"
11 #include "base/lazy_instance.h"
15 // This class is used to retrieve some CoreMedia library functions. It must be
16 // used as a LazyInstance so that it is initialised once and in a thread-safe
17 // way. Normally no work is done in constructors: LazyInstance is an exception.
18 class CoreMediaLibraryInternal {
20 typedef CoreMediaGlue::CMTime (*CMTimeMakeMethod)(int64_t, int32_t);
22 typedef OSStatus (*CMBlockBufferCreateContiguousMethod)(
24 CoreMediaGlue::CMBlockBufferRef,
26 const CoreMediaGlue::CMBlockBufferCustomBlockSource*,
29 CoreMediaGlue::CMBlockBufferFlags,
30 CoreMediaGlue::CMBlockBufferRef*);
31 typedef size_t (*CMBlockBufferGetDataLengthMethod)(
32 CoreMediaGlue::CMBlockBufferRef);
33 typedef OSStatus (*CMBlockBufferGetDataPointerMethod)(
34 CoreMediaGlue::CMBlockBufferRef,
39 typedef Boolean (*CMBlockBufferIsRangeContiguousMethod)(
40 CoreMediaGlue::CMBlockBufferRef,
44 typedef CoreMediaGlue::CMBlockBufferRef (*CMSampleBufferGetDataBufferMethod)(
45 CoreMediaGlue::CMSampleBufferRef);
46 typedef CoreMediaGlue::CMFormatDescriptionRef (
47 *CMSampleBufferGetFormatDescriptionMethod)(
48 CoreMediaGlue::CMSampleBufferRef);
49 typedef CVImageBufferRef (*CMSampleBufferGetImageBufferMethod)(
50 CoreMediaGlue::CMSampleBufferRef);
51 typedef CFArrayRef (*CMSampleBufferGetSampleAttachmentsArrayMethod)(
52 CoreMediaGlue::CMSampleBufferRef,
55 typedef FourCharCode (*CMFormatDescriptionGetMediaSubTypeMethod)(
56 CoreMediaGlue::CMFormatDescriptionRef desc);
57 typedef CoreMediaGlue::CMVideoDimensions
58 (*CMVideoFormatDescriptionGetDimensionsMethod)(
59 CoreMediaGlue::CMVideoFormatDescriptionRef videoDesc);
60 typedef OSStatus (*CMVideoFormatDescriptionGetH264ParameterSetAtIndexMethod)(
61 CoreMediaGlue::CMFormatDescriptionRef,
68 CoreMediaLibraryInternal() {
69 NSBundle* bundle = [NSBundle
70 bundleWithPath:@"/System/Library/Frameworks/CoreMedia.framework"];
72 const char* path = [[bundle executablePath] fileSystemRepresentation];
74 void* library_handle = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
75 CHECK(library_handle) << dlerror();
77 // Now extract the methods.
78 cm_time_make_ = reinterpret_cast<CMTimeMakeMethod>(
79 dlsym(library_handle, "CMTimeMake"));
80 CHECK(cm_time_make_) << dlerror();
82 cm_block_buffer_create_contiguous_method_ =
83 reinterpret_cast<CMBlockBufferCreateContiguousMethod>(
84 dlsym(library_handle, "CMBlockBufferCreateContiguous"));
85 CHECK(cm_block_buffer_create_contiguous_method_) << dlerror();
86 cm_block_buffer_get_data_length_method_ =
87 reinterpret_cast<CMBlockBufferGetDataLengthMethod>(
88 dlsym(library_handle, "CMBlockBufferGetDataLength"));
89 CHECK(cm_block_buffer_get_data_length_method_) << dlerror();
90 cm_block_buffer_get_data_pointer_method_ =
91 reinterpret_cast<CMBlockBufferGetDataPointerMethod>(
92 dlsym(library_handle, "CMBlockBufferGetDataPointer"));
93 CHECK(cm_block_buffer_get_data_pointer_method_) << dlerror();
94 cm_block_buffer_is_range_contiguous_method_ =
95 reinterpret_cast<CMBlockBufferIsRangeContiguousMethod>(
96 dlsym(library_handle, "CMBlockBufferIsRangeContiguous"));
97 CHECK(cm_block_buffer_is_range_contiguous_method_) << dlerror();
99 cm_sample_buffer_get_data_buffer_method_ =
100 reinterpret_cast<CMSampleBufferGetDataBufferMethod>(
101 dlsym(library_handle, "CMSampleBufferGetDataBuffer"));
102 CHECK(cm_sample_buffer_get_data_buffer_method_) << dlerror();
103 cm_sample_buffer_get_format_description_method_ =
104 reinterpret_cast<CMSampleBufferGetFormatDescriptionMethod>(
105 dlsym(library_handle, "CMSampleBufferGetFormatDescription"));
106 CHECK(cm_sample_buffer_get_format_description_method_) << dlerror();
107 cm_sample_buffer_get_image_buffer_method_ =
108 reinterpret_cast<CMSampleBufferGetImageBufferMethod>(
109 dlsym(library_handle, "CMSampleBufferGetImageBuffer"));
110 CHECK(cm_sample_buffer_get_image_buffer_method_) << dlerror();
111 cm_sample_buffer_get_sample_attachments_array_method_ =
112 reinterpret_cast<CMSampleBufferGetSampleAttachmentsArrayMethod>(
113 dlsym(library_handle, "CMSampleBufferGetSampleAttachmentsArray"));
114 CHECK(cm_sample_buffer_get_sample_attachments_array_method_) << dlerror();
115 k_cm_sample_attachment_key_not_sync_ = reinterpret_cast<CFStringRef*>(
116 dlsym(library_handle, "kCMSampleAttachmentKey_NotSync"));
117 CHECK(k_cm_sample_attachment_key_not_sync_) << dlerror();
119 cm_format_description_get_media_sub_type_method_ =
120 reinterpret_cast<CMFormatDescriptionGetMediaSubTypeMethod>(
121 dlsym(library_handle, "CMFormatDescriptionGetMediaSubType"));
122 CHECK(cm_format_description_get_media_sub_type_method_) << dlerror();
123 cm_video_format_description_get_dimensions_method_ =
124 reinterpret_cast<CMVideoFormatDescriptionGetDimensionsMethod>(
125 dlsym(library_handle, "CMVideoFormatDescriptionGetDimensions"));
126 CHECK(cm_video_format_description_get_dimensions_method_) << dlerror();
128 // Available starting (OS X 10.9, iOS 7), allow to be null.
129 cm_video_format_description_get_h264_parameter_set_at_index_method_ =
131 CMVideoFormatDescriptionGetH264ParameterSetAtIndexMethod>(
132 dlsym(library_handle,
133 "CMVideoFormatDescriptionGetH264ParameterSetAtIndex"));
136 const CMTimeMakeMethod& cm_time_make() const { return cm_time_make_; }
138 const CMBlockBufferCreateContiguousMethod&
139 cm_block_buffer_create_contiguous_method() const {
140 return cm_block_buffer_create_contiguous_method_;
142 const CMBlockBufferGetDataLengthMethod&
143 cm_block_buffer_get_data_length_method() const {
144 return cm_block_buffer_get_data_length_method_;
146 const CMBlockBufferGetDataPointerMethod&
147 cm_block_buffer_get_data_pointer_method() const {
148 return cm_block_buffer_get_data_pointer_method_;
150 const CMBlockBufferIsRangeContiguousMethod&
151 cm_block_buffer_is_range_contiguous_method() const {
152 return cm_block_buffer_is_range_contiguous_method_;
155 const CMSampleBufferGetDataBufferMethod&
156 cm_sample_buffer_get_data_buffer_method() const {
157 return cm_sample_buffer_get_data_buffer_method_;
159 const CMSampleBufferGetFormatDescriptionMethod&
160 cm_sample_buffer_get_format_description_method() const {
161 return cm_sample_buffer_get_format_description_method_;
163 const CMSampleBufferGetImageBufferMethod&
164 cm_sample_buffer_get_image_buffer_method() const {
165 return cm_sample_buffer_get_image_buffer_method_;
167 const CMSampleBufferGetSampleAttachmentsArrayMethod&
168 cm_sample_buffer_get_sample_attachments_array_method() const {
169 return cm_sample_buffer_get_sample_attachments_array_method_;
171 CFStringRef* const& k_cm_sample_attachment_key_not_sync() const {
172 return k_cm_sample_attachment_key_not_sync_;
175 const CMFormatDescriptionGetMediaSubTypeMethod&
176 cm_format_description_get_media_sub_type_method() const {
177 return cm_format_description_get_media_sub_type_method_;
179 const CMVideoFormatDescriptionGetDimensionsMethod&
180 cm_video_format_description_get_dimensions_method() const {
181 return cm_video_format_description_get_dimensions_method_;
183 const CMVideoFormatDescriptionGetH264ParameterSetAtIndexMethod&
184 cm_video_format_description_get_h264_parameter_set_at_index_method() const {
185 return cm_video_format_description_get_h264_parameter_set_at_index_method_;
189 CMTimeMakeMethod cm_time_make_;
191 CMBlockBufferCreateContiguousMethod cm_block_buffer_create_contiguous_method_;
192 CMBlockBufferGetDataLengthMethod cm_block_buffer_get_data_length_method_;
193 CMBlockBufferGetDataPointerMethod cm_block_buffer_get_data_pointer_method_;
194 CMBlockBufferIsRangeContiguousMethod
195 cm_block_buffer_is_range_contiguous_method_;
197 CMSampleBufferGetDataBufferMethod cm_sample_buffer_get_data_buffer_method_;
198 CMSampleBufferGetFormatDescriptionMethod
199 cm_sample_buffer_get_format_description_method_;
200 CMSampleBufferGetImageBufferMethod cm_sample_buffer_get_image_buffer_method_;
201 CMSampleBufferGetSampleAttachmentsArrayMethod
202 cm_sample_buffer_get_sample_attachments_array_method_;
203 CFStringRef* k_cm_sample_attachment_key_not_sync_;
205 CMFormatDescriptionGetMediaSubTypeMethod
206 cm_format_description_get_media_sub_type_method_;
207 CMVideoFormatDescriptionGetDimensionsMethod
208 cm_video_format_description_get_dimensions_method_;
209 CMVideoFormatDescriptionGetH264ParameterSetAtIndexMethod
210 cm_video_format_description_get_h264_parameter_set_at_index_method_;
212 DISALLOW_COPY_AND_ASSIGN(CoreMediaLibraryInternal);
217 static base::LazyInstance<CoreMediaLibraryInternal> g_coremedia_handle =
218 LAZY_INSTANCE_INITIALIZER;
221 CoreMediaGlue::CMTime CoreMediaGlue::CMTimeMake(int64_t value,
223 return g_coremedia_handle.Get().cm_time_make()(value, timescale);
227 OSStatus CoreMediaGlue::CMBlockBufferCreateContiguous(
228 CFAllocatorRef structureAllocator,
229 CMBlockBufferRef sourceBuffer,
230 CFAllocatorRef blockAllocator,
231 const CMBlockBufferCustomBlockSource* customBlockSource,
234 CMBlockBufferFlags flags,
235 CMBlockBufferRef* newBBufOut) {
236 return g_coremedia_handle.Get().cm_block_buffer_create_contiguous_method()(
248 size_t CoreMediaGlue::CMBlockBufferGetDataLength(CMBlockBufferRef theBuffer) {
249 return g_coremedia_handle.Get().cm_block_buffer_get_data_length_method()(
254 OSStatus CoreMediaGlue::CMBlockBufferGetDataPointer(CMBlockBufferRef theBuffer,
256 size_t* lengthAtOffset,
258 char** dataPointer) {
259 return g_coremedia_handle.Get().cm_block_buffer_get_data_pointer_method()(
260 theBuffer, offset, lengthAtOffset, totalLength, dataPointer);
264 Boolean CoreMediaGlue::CMBlockBufferIsRangeContiguous(
265 CMBlockBufferRef theBuffer,
268 return g_coremedia_handle.Get().cm_block_buffer_is_range_contiguous_method()(
269 theBuffer, offset, length);
273 CoreMediaGlue::CMBlockBufferRef CoreMediaGlue::CMSampleBufferGetDataBuffer(
274 CMSampleBufferRef sbuf) {
275 return g_coremedia_handle.Get().cm_sample_buffer_get_data_buffer_method()(
280 CoreMediaGlue::CMFormatDescriptionRef
281 CoreMediaGlue::CMSampleBufferGetFormatDescription(
282 CoreMediaGlue::CMSampleBufferRef sbuf) {
283 return g_coremedia_handle.Get()
284 .cm_sample_buffer_get_format_description_method()(sbuf);
288 CVImageBufferRef CoreMediaGlue::CMSampleBufferGetImageBuffer(
289 CMSampleBufferRef buffer) {
290 return g_coremedia_handle.Get().cm_sample_buffer_get_image_buffer_method()(
295 CFArrayRef CoreMediaGlue::CMSampleBufferGetSampleAttachmentsArray(
296 CMSampleBufferRef sbuf,
297 Boolean createIfNecessary) {
298 return g_coremedia_handle.Get()
299 .cm_sample_buffer_get_sample_attachments_array_method()(
300 sbuf, createIfNecessary);
304 CFStringRef CoreMediaGlue::kCMSampleAttachmentKey_NotSync() {
305 return *g_coremedia_handle.Get().k_cm_sample_attachment_key_not_sync();
309 FourCharCode CoreMediaGlue::CMFormatDescriptionGetMediaSubType(
310 CMFormatDescriptionRef desc) {
311 return g_coremedia_handle.Get()
312 .cm_format_description_get_media_sub_type_method()(desc);
316 CoreMediaGlue::CMVideoDimensions
317 CoreMediaGlue::CMVideoFormatDescriptionGetDimensions(
318 CMVideoFormatDescriptionRef videoDesc) {
319 return g_coremedia_handle.Get()
320 .cm_video_format_description_get_dimensions_method()(videoDesc);
324 OSStatus CoreMediaGlue::CMVideoFormatDescriptionGetH264ParameterSetAtIndex(
325 CMFormatDescriptionRef videoDesc,
326 size_t parameterSetIndex,
327 const uint8_t** parameterSetPointerOut,
328 size_t* parameterSetSizeOut,
329 size_t* parameterSetCountOut,
330 int* NALUnitHeaderLengthOut) {
331 return g_coremedia_handle.Get()
332 .cm_video_format_description_get_h264_parameter_set_at_index_method()(
335 parameterSetPointerOut,
337 parameterSetCountOut,
338 NALUnitHeaderLengthOut);