| 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 |