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