OLD | NEW |
| (Empty) |
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 #include "media/base/mac/coremedia_glue.h" | |
6 | |
7 #include <dlfcn.h> | |
8 #import <Foundation/Foundation.h> | |
9 | |
10 #include "base/lazy_instance.h" | |
11 #include "base/logging.h" | |
12 #include "base/macros.h" | |
13 | |
14 namespace { | |
15 | |
16 // This class is used to retrieve some CoreMedia library functions. It must be | |
17 // used as a LazyInstance so that it is initialised once and in a thread-safe | |
18 // way. Normally no work is done in constructors: LazyInstance is an exception. | |
19 class CoreMediaLibraryInternal { | |
20 public: | |
21 typedef CoreMediaGlue::CMTime (*CMTimeMakeMethod)(int64_t, int32_t); | |
22 | |
23 typedef OSStatus (*CMBlockBufferCreateContiguousMethod)( | |
24 CFAllocatorRef, | |
25 CoreMediaGlue::CMBlockBufferRef, | |
26 CFAllocatorRef, | |
27 const CoreMediaGlue::CMBlockBufferCustomBlockSource*, | |
28 size_t, | |
29 size_t, | |
30 CoreMediaGlue::CMBlockBufferFlags, | |
31 CoreMediaGlue::CMBlockBufferRef*); | |
32 typedef size_t (*CMBlockBufferGetDataLengthMethod)( | |
33 CoreMediaGlue::CMBlockBufferRef); | |
34 typedef OSStatus (*CMBlockBufferGetDataPointerMethod)( | |
35 CoreMediaGlue::CMBlockBufferRef, | |
36 size_t, | |
37 size_t*, | |
38 size_t*, | |
39 char**); | |
40 typedef Boolean (*CMBlockBufferIsRangeContiguousMethod)( | |
41 CoreMediaGlue::CMBlockBufferRef, | |
42 size_t, | |
43 size_t); | |
44 | |
45 typedef CoreMediaGlue::CMBlockBufferRef (*CMSampleBufferGetDataBufferMethod)( | |
46 CoreMediaGlue::CMSampleBufferRef); | |
47 typedef CoreMediaGlue::CMFormatDescriptionRef ( | |
48 *CMSampleBufferGetFormatDescriptionMethod)( | |
49 CoreMediaGlue::CMSampleBufferRef); | |
50 typedef CVImageBufferRef (*CMSampleBufferGetImageBufferMethod)( | |
51 CoreMediaGlue::CMSampleBufferRef); | |
52 typedef CFArrayRef (*CMSampleBufferGetSampleAttachmentsArrayMethod)( | |
53 CoreMediaGlue::CMSampleBufferRef, | |
54 Boolean); | |
55 typedef CoreMediaGlue::CMTime (*CMSampleBufferGetPresentationTimeStampMethod)( | |
56 CoreMediaGlue::CMSampleBufferRef); | |
57 | |
58 typedef FourCharCode (*CMFormatDescriptionGetMediaSubTypeMethod)( | |
59 CoreMediaGlue::CMFormatDescriptionRef desc); | |
60 typedef CoreMediaGlue::CMVideoDimensions | |
61 (*CMVideoFormatDescriptionGetDimensionsMethod)( | |
62 CoreMediaGlue::CMVideoFormatDescriptionRef videoDesc); | |
63 typedef OSStatus (*CMVideoFormatDescriptionGetH264ParameterSetAtIndexMethod)( | |
64 CoreMediaGlue::CMFormatDescriptionRef, | |
65 size_t, | |
66 const uint8_t**, | |
67 size_t*, | |
68 size_t*, | |
69 int*); | |
70 | |
71 CoreMediaLibraryInternal() { | |
72 NSBundle* bundle = [NSBundle | |
73 bundleWithPath:@"/System/Library/Frameworks/CoreMedia.framework"]; | |
74 | |
75 const char* path = [[bundle executablePath] fileSystemRepresentation]; | |
76 CHECK(path); | |
77 void* library_handle = dlopen(path, RTLD_LAZY | RTLD_LOCAL); | |
78 CHECK(library_handle) << dlerror(); | |
79 | |
80 // Now extract the methods. | |
81 cm_time_make_ = reinterpret_cast<CMTimeMakeMethod>( | |
82 dlsym(library_handle, "CMTimeMake")); | |
83 CHECK(cm_time_make_) << dlerror(); | |
84 | |
85 cm_block_buffer_create_contiguous_method_ = | |
86 reinterpret_cast<CMBlockBufferCreateContiguousMethod>( | |
87 dlsym(library_handle, "CMBlockBufferCreateContiguous")); | |
88 CHECK(cm_block_buffer_create_contiguous_method_) << dlerror(); | |
89 cm_block_buffer_get_data_length_method_ = | |
90 reinterpret_cast<CMBlockBufferGetDataLengthMethod>( | |
91 dlsym(library_handle, "CMBlockBufferGetDataLength")); | |
92 CHECK(cm_block_buffer_get_data_length_method_) << dlerror(); | |
93 cm_block_buffer_get_data_pointer_method_ = | |
94 reinterpret_cast<CMBlockBufferGetDataPointerMethod>( | |
95 dlsym(library_handle, "CMBlockBufferGetDataPointer")); | |
96 CHECK(cm_block_buffer_get_data_pointer_method_) << dlerror(); | |
97 cm_block_buffer_is_range_contiguous_method_ = | |
98 reinterpret_cast<CMBlockBufferIsRangeContiguousMethod>( | |
99 dlsym(library_handle, "CMBlockBufferIsRangeContiguous")); | |
100 CHECK(cm_block_buffer_is_range_contiguous_method_) << dlerror(); | |
101 | |
102 cm_sample_buffer_get_data_buffer_method_ = | |
103 reinterpret_cast<CMSampleBufferGetDataBufferMethod>( | |
104 dlsym(library_handle, "CMSampleBufferGetDataBuffer")); | |
105 CHECK(cm_sample_buffer_get_data_buffer_method_) << dlerror(); | |
106 cm_sample_buffer_get_format_description_method_ = | |
107 reinterpret_cast<CMSampleBufferGetFormatDescriptionMethod>( | |
108 dlsym(library_handle, "CMSampleBufferGetFormatDescription")); | |
109 CHECK(cm_sample_buffer_get_format_description_method_) << dlerror(); | |
110 cm_sample_buffer_get_image_buffer_method_ = | |
111 reinterpret_cast<CMSampleBufferGetImageBufferMethod>( | |
112 dlsym(library_handle, "CMSampleBufferGetImageBuffer")); | |
113 CHECK(cm_sample_buffer_get_image_buffer_method_) << dlerror(); | |
114 cm_sample_buffer_get_sample_attachments_array_method_ = | |
115 reinterpret_cast<CMSampleBufferGetSampleAttachmentsArrayMethod>( | |
116 dlsym(library_handle, "CMSampleBufferGetSampleAttachmentsArray")); | |
117 CHECK(cm_sample_buffer_get_sample_attachments_array_method_) << dlerror(); | |
118 cm_sample_buffer_get_presentation_timestamp_method_ = | |
119 reinterpret_cast<CMSampleBufferGetPresentationTimeStampMethod>( | |
120 dlsym(library_handle, "CMSampleBufferGetPresentationTimeStamp")); | |
121 CHECK(cm_sample_buffer_get_presentation_timestamp_method_) << dlerror(); | |
122 k_cm_sample_attachment_key_not_sync_ = reinterpret_cast<CFStringRef*>( | |
123 dlsym(library_handle, "kCMSampleAttachmentKey_NotSync")); | |
124 CHECK(k_cm_sample_attachment_key_not_sync_) << dlerror(); | |
125 | |
126 cm_format_description_get_media_sub_type_method_ = | |
127 reinterpret_cast<CMFormatDescriptionGetMediaSubTypeMethod>( | |
128 dlsym(library_handle, "CMFormatDescriptionGetMediaSubType")); | |
129 CHECK(cm_format_description_get_media_sub_type_method_) << dlerror(); | |
130 cm_video_format_description_get_dimensions_method_ = | |
131 reinterpret_cast<CMVideoFormatDescriptionGetDimensionsMethod>( | |
132 dlsym(library_handle, "CMVideoFormatDescriptionGetDimensions")); | |
133 CHECK(cm_video_format_description_get_dimensions_method_) << dlerror(); | |
134 | |
135 // Available starting (OS X 10.9, iOS 7), allow to be null. | |
136 cm_video_format_description_get_h264_parameter_set_at_index_method_ = | |
137 reinterpret_cast< | |
138 CMVideoFormatDescriptionGetH264ParameterSetAtIndexMethod>( | |
139 dlsym(library_handle, | |
140 "CMVideoFormatDescriptionGetH264ParameterSetAtIndex")); | |
141 } | |
142 | |
143 const CMTimeMakeMethod& cm_time_make() const { return cm_time_make_; } | |
144 | |
145 const CMBlockBufferCreateContiguousMethod& | |
146 cm_block_buffer_create_contiguous_method() const { | |
147 return cm_block_buffer_create_contiguous_method_; | |
148 } | |
149 const CMBlockBufferGetDataLengthMethod& | |
150 cm_block_buffer_get_data_length_method() const { | |
151 return cm_block_buffer_get_data_length_method_; | |
152 } | |
153 const CMBlockBufferGetDataPointerMethod& | |
154 cm_block_buffer_get_data_pointer_method() const { | |
155 return cm_block_buffer_get_data_pointer_method_; | |
156 } | |
157 const CMBlockBufferIsRangeContiguousMethod& | |
158 cm_block_buffer_is_range_contiguous_method() const { | |
159 return cm_block_buffer_is_range_contiguous_method_; | |
160 } | |
161 | |
162 const CMSampleBufferGetDataBufferMethod& | |
163 cm_sample_buffer_get_data_buffer_method() const { | |
164 return cm_sample_buffer_get_data_buffer_method_; | |
165 } | |
166 const CMSampleBufferGetFormatDescriptionMethod& | |
167 cm_sample_buffer_get_format_description_method() const { | |
168 return cm_sample_buffer_get_format_description_method_; | |
169 } | |
170 const CMSampleBufferGetImageBufferMethod& | |
171 cm_sample_buffer_get_image_buffer_method() const { | |
172 return cm_sample_buffer_get_image_buffer_method_; | |
173 } | |
174 const CMSampleBufferGetSampleAttachmentsArrayMethod& | |
175 cm_sample_buffer_get_sample_attachments_array_method() const { | |
176 return cm_sample_buffer_get_sample_attachments_array_method_; | |
177 } | |
178 const CMSampleBufferGetPresentationTimeStampMethod& | |
179 cm_sample_buffer_get_presentation_timestamp_method() const { | |
180 return cm_sample_buffer_get_presentation_timestamp_method_; | |
181 } | |
182 CFStringRef* const& k_cm_sample_attachment_key_not_sync() const { | |
183 return k_cm_sample_attachment_key_not_sync_; | |
184 } | |
185 | |
186 const CMFormatDescriptionGetMediaSubTypeMethod& | |
187 cm_format_description_get_media_sub_type_method() const { | |
188 return cm_format_description_get_media_sub_type_method_; | |
189 } | |
190 const CMVideoFormatDescriptionGetDimensionsMethod& | |
191 cm_video_format_description_get_dimensions_method() const { | |
192 return cm_video_format_description_get_dimensions_method_; | |
193 } | |
194 const CMVideoFormatDescriptionGetH264ParameterSetAtIndexMethod& | |
195 cm_video_format_description_get_h264_parameter_set_at_index_method() const { | |
196 return cm_video_format_description_get_h264_parameter_set_at_index_method_; | |
197 } | |
198 | |
199 private: | |
200 CMTimeMakeMethod cm_time_make_; | |
201 | |
202 CMBlockBufferCreateContiguousMethod cm_block_buffer_create_contiguous_method_; | |
203 CMBlockBufferGetDataLengthMethod cm_block_buffer_get_data_length_method_; | |
204 CMBlockBufferGetDataPointerMethod cm_block_buffer_get_data_pointer_method_; | |
205 CMBlockBufferIsRangeContiguousMethod | |
206 cm_block_buffer_is_range_contiguous_method_; | |
207 | |
208 CMSampleBufferGetDataBufferMethod cm_sample_buffer_get_data_buffer_method_; | |
209 CMSampleBufferGetFormatDescriptionMethod | |
210 cm_sample_buffer_get_format_description_method_; | |
211 CMSampleBufferGetImageBufferMethod cm_sample_buffer_get_image_buffer_method_; | |
212 CMSampleBufferGetSampleAttachmentsArrayMethod | |
213 cm_sample_buffer_get_sample_attachments_array_method_; | |
214 CFStringRef* k_cm_sample_attachment_key_not_sync_; | |
215 | |
216 CMFormatDescriptionGetMediaSubTypeMethod | |
217 cm_format_description_get_media_sub_type_method_; | |
218 CMVideoFormatDescriptionGetDimensionsMethod | |
219 cm_video_format_description_get_dimensions_method_; | |
220 CMVideoFormatDescriptionGetH264ParameterSetAtIndexMethod | |
221 cm_video_format_description_get_h264_parameter_set_at_index_method_; | |
222 CMSampleBufferGetPresentationTimeStampMethod | |
223 cm_sample_buffer_get_presentation_timestamp_method_; | |
224 | |
225 DISALLOW_COPY_AND_ASSIGN(CoreMediaLibraryInternal); | |
226 }; | |
227 | |
228 } // namespace | |
229 | |
230 static base::LazyInstance<CoreMediaLibraryInternal> g_coremedia_handle = | |
231 LAZY_INSTANCE_INITIALIZER; | |
232 | |
233 // static | |
234 CoreMediaGlue::CMTime CoreMediaGlue::CMTimeMake(int64_t value, | |
235 int32_t timescale) { | |
236 return g_coremedia_handle.Get().cm_time_make()(value, timescale); | |
237 } | |
238 | |
239 // static | |
240 OSStatus CoreMediaGlue::CMBlockBufferCreateContiguous( | |
241 CFAllocatorRef structureAllocator, | |
242 CMBlockBufferRef sourceBuffer, | |
243 CFAllocatorRef blockAllocator, | |
244 const CMBlockBufferCustomBlockSource* customBlockSource, | |
245 size_t offsetToData, | |
246 size_t dataLength, | |
247 CMBlockBufferFlags flags, | |
248 CMBlockBufferRef* newBBufOut) { | |
249 return g_coremedia_handle.Get().cm_block_buffer_create_contiguous_method()( | |
250 structureAllocator, | |
251 sourceBuffer, | |
252 blockAllocator, | |
253 customBlockSource, | |
254 offsetToData, | |
255 dataLength, | |
256 flags, | |
257 newBBufOut); | |
258 } | |
259 | |
260 // static | |
261 size_t CoreMediaGlue::CMBlockBufferGetDataLength(CMBlockBufferRef theBuffer) { | |
262 return g_coremedia_handle.Get().cm_block_buffer_get_data_length_method()( | |
263 theBuffer); | |
264 } | |
265 | |
266 // static | |
267 OSStatus CoreMediaGlue::CMBlockBufferGetDataPointer(CMBlockBufferRef theBuffer, | |
268 size_t offset, | |
269 size_t* lengthAtOffset, | |
270 size_t* totalLength, | |
271 char** dataPointer) { | |
272 return g_coremedia_handle.Get().cm_block_buffer_get_data_pointer_method()( | |
273 theBuffer, offset, lengthAtOffset, totalLength, dataPointer); | |
274 } | |
275 | |
276 // static | |
277 Boolean CoreMediaGlue::CMBlockBufferIsRangeContiguous( | |
278 CMBlockBufferRef theBuffer, | |
279 size_t offset, | |
280 size_t length) { | |
281 return g_coremedia_handle.Get().cm_block_buffer_is_range_contiguous_method()( | |
282 theBuffer, offset, length); | |
283 } | |
284 | |
285 // static | |
286 CoreMediaGlue::CMBlockBufferRef CoreMediaGlue::CMSampleBufferGetDataBuffer( | |
287 CMSampleBufferRef sbuf) { | |
288 return g_coremedia_handle.Get().cm_sample_buffer_get_data_buffer_method()( | |
289 sbuf); | |
290 } | |
291 | |
292 // static | |
293 CoreMediaGlue::CMFormatDescriptionRef | |
294 CoreMediaGlue::CMSampleBufferGetFormatDescription( | |
295 CoreMediaGlue::CMSampleBufferRef sbuf) { | |
296 return g_coremedia_handle.Get() | |
297 .cm_sample_buffer_get_format_description_method()(sbuf); | |
298 } | |
299 | |
300 // static | |
301 CVImageBufferRef CoreMediaGlue::CMSampleBufferGetImageBuffer( | |
302 CMSampleBufferRef buffer) { | |
303 return g_coremedia_handle.Get().cm_sample_buffer_get_image_buffer_method()( | |
304 buffer); | |
305 } | |
306 | |
307 // static | |
308 CFArrayRef CoreMediaGlue::CMSampleBufferGetSampleAttachmentsArray( | |
309 CMSampleBufferRef sbuf, | |
310 Boolean createIfNecessary) { | |
311 return g_coremedia_handle.Get() | |
312 .cm_sample_buffer_get_sample_attachments_array_method()( | |
313 sbuf, createIfNecessary); | |
314 } | |
315 | |
316 // static | |
317 CoreMediaGlue::CMTime CoreMediaGlue::CMSampleBufferGetPresentationTimeStamp( | |
318 CMSampleBufferRef sbuf) { | |
319 return g_coremedia_handle.Get() | |
320 .cm_sample_buffer_get_presentation_timestamp_method()(sbuf); | |
321 } | |
322 | |
323 // static | |
324 CFStringRef CoreMediaGlue::kCMSampleAttachmentKey_NotSync() { | |
325 return *g_coremedia_handle.Get().k_cm_sample_attachment_key_not_sync(); | |
326 } | |
327 | |
328 // static | |
329 FourCharCode CoreMediaGlue::CMFormatDescriptionGetMediaSubType( | |
330 CMFormatDescriptionRef desc) { | |
331 return g_coremedia_handle.Get() | |
332 .cm_format_description_get_media_sub_type_method()(desc); | |
333 } | |
334 | |
335 // static | |
336 CoreMediaGlue::CMVideoDimensions | |
337 CoreMediaGlue::CMVideoFormatDescriptionGetDimensions( | |
338 CMVideoFormatDescriptionRef videoDesc) { | |
339 return g_coremedia_handle.Get() | |
340 .cm_video_format_description_get_dimensions_method()(videoDesc); | |
341 } | |
342 | |
343 // static | |
344 OSStatus CoreMediaGlue::CMVideoFormatDescriptionGetH264ParameterSetAtIndex( | |
345 CMFormatDescriptionRef videoDesc, | |
346 size_t parameterSetIndex, | |
347 const uint8_t** parameterSetPointerOut, | |
348 size_t* parameterSetSizeOut, | |
349 size_t* parameterSetCountOut, | |
350 int* NALUnitHeaderLengthOut) { | |
351 return g_coremedia_handle.Get() | |
352 .cm_video_format_description_get_h264_parameter_set_at_index_method()( | |
353 videoDesc, | |
354 parameterSetIndex, | |
355 parameterSetPointerOut, | |
356 parameterSetSizeOut, | |
357 parameterSetCountOut, | |
358 NALUnitHeaderLengthOut); | |
359 } | |
OLD | NEW |