OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 <algorithm> | 5 #include <algorithm> |
6 | 6 |
7 #include <CoreVideo/CoreVideo.h> | 7 #include <CoreVideo/CoreVideo.h> |
8 #include <OpenGL/CGLIOSurface.h> | 8 #include <OpenGL/CGLIOSurface.h> |
9 #include <OpenGL/gl.h> | 9 #include <OpenGL/gl.h> |
10 #include <stddef.h> | 10 #include <stddef.h> |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 base::ScopedCFTypeRef<CMFormatDescriptionRef> format; | 117 base::ScopedCFTypeRef<CMFormatDescriptionRef> format; |
118 OSStatus status = CMVideoFormatDescriptionCreateFromH264ParameterSets( | 118 OSStatus status = CMVideoFormatDescriptionCreateFromH264ParameterSets( |
119 kCFAllocatorDefault, | 119 kCFAllocatorDefault, |
120 2, // parameter_set_count | 120 2, // parameter_set_count |
121 data_ptrs, // ¶meter_set_pointers | 121 data_ptrs, // ¶meter_set_pointers |
122 data_sizes, // ¶meter_set_sizes | 122 data_sizes, // ¶meter_set_sizes |
123 kNALUHeaderLength, // nal_unit_header_length | 123 kNALUHeaderLength, // nal_unit_header_length |
124 format.InitializeInto()); | 124 format.InitializeInto()); |
125 if (status) { | 125 if (status) { |
126 OSSTATUS_DLOG(WARNING, status) | 126 OSSTATUS_DLOG(WARNING, status) |
127 << "Failed to create CMVideoFormatDescription."; | 127 << "Failed to create CMVideoFormatDescription"; |
128 return false; | 128 return false; |
129 } | 129 } |
130 | 130 |
131 base::ScopedCFTypeRef<CFMutableDictionaryRef> decoder_config( | 131 base::ScopedCFTypeRef<CFMutableDictionaryRef> decoder_config( |
132 CFDictionaryCreateMutable( | 132 CFDictionaryCreateMutable( |
133 kCFAllocatorDefault, | 133 kCFAllocatorDefault, |
134 1, // capacity | 134 1, // capacity |
135 &kCFTypeDictionaryKeyCallBacks, | 135 &kCFTypeDictionaryKeyCallBacks, |
136 &kCFTypeDictionaryValueCallBacks)); | 136 &kCFTypeDictionaryValueCallBacks)); |
137 if (!decoder_config.get()) | 137 if (!decoder_config.get()) |
(...skipping 16 matching lines...) Expand all Loading... |
154 | 154 |
155 base::ScopedCFTypeRef<VTDecompressionSessionRef> session; | 155 base::ScopedCFTypeRef<VTDecompressionSessionRef> session; |
156 status = VTDecompressionSessionCreate( | 156 status = VTDecompressionSessionCreate( |
157 kCFAllocatorDefault, | 157 kCFAllocatorDefault, |
158 format, // video_format_description | 158 format, // video_format_description |
159 decoder_config, // video_decoder_specification | 159 decoder_config, // video_decoder_specification |
160 image_config, // destination_image_buffer_attributes | 160 image_config, // destination_image_buffer_attributes |
161 &callback, // output_callback | 161 &callback, // output_callback |
162 session.InitializeInto()); | 162 session.InitializeInto()); |
163 if (status) { | 163 if (status) { |
164 OSSTATUS_DLOG(WARNING, status) << "Failed to create VTDecompressionSession"; | 164 OSSTATUS_DLOG(WARNING, status) |
| 165 << "Failed to create VTDecompressionSession"; |
165 return false; | 166 return false; |
166 } | 167 } |
167 | 168 |
168 return true; | 169 return true; |
169 } | 170 } |
170 | 171 |
171 // The purpose of this function is to preload the generic and hardware-specific | 172 // The purpose of this function is to preload the generic and hardware-specific |
172 // libraries required by VideoToolbox before the GPU sandbox is enabled. | 173 // libraries required by VideoToolbox before the GPU sandbox is enabled. |
173 // VideoToolbox normally loads the hardware-specific libraries lazily, so we | 174 // VideoToolbox normally loads the hardware-specific libraries lazily, so we |
174 // must actually create a decompression session. If creating a decompression | 175 // must actually create a decompression session. If creating a decompression |
175 // session fails, hardware decoding will be disabled (Initialize() will always | 176 // session fails, hardware decoding will be disabled (Initialize() will always |
176 // return false). | 177 // return false). |
177 static bool InitializeVideoToolboxInternal() { | 178 static bool InitializeVideoToolboxInternal() { |
178 if (!IsVtInitialized()) { | 179 if (!IsVtInitialized()) { |
179 // CoreVideo is also required, but the loader stops after the first path is | 180 // CoreVideo is also required, but the loader stops after the first path is |
180 // loaded. Instead we rely on the transitive dependency from VideoToolbox to | 181 // loaded. Instead we rely on the transitive dependency from VideoToolbox to |
181 // CoreVideo. | 182 // CoreVideo. |
182 StubPathMap paths; | 183 StubPathMap paths; |
183 paths[kModuleVt].push_back(FILE_PATH_LITERAL( | 184 paths[kModuleVt].push_back(FILE_PATH_LITERAL( |
184 "/System/Library/Frameworks/VideoToolbox.framework/VideoToolbox")); | 185 "/System/Library/Frameworks/VideoToolbox.framework/VideoToolbox")); |
185 if (!InitializeStubs(paths)) { | 186 if (!InitializeStubs(paths)) { |
186 LOG(WARNING) << "Failed to initialize VideoToolbox framework. " | 187 DLOG(WARNING) << "Failed to initialize VideoToolbox framework"; |
187 << "Hardware accelerated video decoding will be disabled."; | |
188 return false; | 188 return false; |
189 } | 189 } |
190 } | 190 } |
191 | 191 |
192 // Create a hardware decoding session. | 192 // Create a hardware decoding session. |
193 // SPS and PPS data are taken from a 480p sample (buck2.mp4). | 193 // SPS and PPS data are taken from a 480p sample (buck2.mp4). |
194 const uint8_t sps_normal[] = {0x67, 0x64, 0x00, 0x1e, 0xac, 0xd9, 0x80, 0xd4, | 194 const uint8_t sps_normal[] = {0x67, 0x64, 0x00, 0x1e, 0xac, 0xd9, 0x80, 0xd4, |
195 0x3d, 0xa1, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, | 195 0x3d, 0xa1, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, |
196 0x00, 0x03, 0x00, 0x30, 0x8f, 0x16, 0x2d, 0x9a}; | 196 0x00, 0x03, 0x00, 0x30, 0x8f, 0x16, 0x2d, 0x9a}; |
197 const uint8_t pps_normal[] = {0x68, 0xe9, 0x7b, 0xcb}; | 197 const uint8_t pps_normal[] = {0x68, 0xe9, 0x7b, 0xcb}; |
198 if (!CreateVideoToolboxSession(sps_normal, arraysize(sps_normal), pps_normal, | 198 if (!CreateVideoToolboxSession(sps_normal, arraysize(sps_normal), pps_normal, |
199 arraysize(pps_normal), true)) { | 199 arraysize(pps_normal), true)) { |
200 LOG(WARNING) << "Failed to create hardware VideoToolbox session. " | 200 DLOG(WARNING) << "Failed to create hardware VideoToolbox session"; |
201 << "Hardware accelerated video decoding will be disabled."; | |
202 return false; | 201 return false; |
203 } | 202 } |
204 | 203 |
205 // Create a software decoding session. | 204 // Create a software decoding session. |
206 // SPS and PPS data are taken from a 18p sample (small2.mp4). | 205 // SPS and PPS data are taken from a 18p sample (small2.mp4). |
207 const uint8_t sps_small[] = {0x67, 0x64, 0x00, 0x0a, 0xac, 0xd9, 0x89, 0x7e, | 206 const uint8_t sps_small[] = {0x67, 0x64, 0x00, 0x0a, 0xac, 0xd9, 0x89, 0x7e, |
208 0x22, 0x10, 0x00, 0x00, 0x3e, 0x90, 0x00, 0x0e, | 207 0x22, 0x10, 0x00, 0x00, 0x3e, 0x90, 0x00, 0x0e, |
209 0xa6, 0x08, 0xf1, 0x22, 0x59, 0xa0}; | 208 0xa6, 0x08, 0xf1, 0x22, 0x59, 0xa0}; |
210 const uint8_t pps_small[] = {0x68, 0xe9, 0x79, 0x72, 0xc0}; | 209 const uint8_t pps_small[] = {0x68, 0xe9, 0x79, 0x72, 0xc0}; |
211 if (!CreateVideoToolboxSession(sps_small, arraysize(sps_small), pps_small, | 210 if (!CreateVideoToolboxSession(sps_small, arraysize(sps_small), pps_small, |
212 arraysize(pps_small), false)) { | 211 arraysize(pps_small), false)) { |
213 LOG(WARNING) << "Failed to create software VideoToolbox session. " | 212 DLOG(WARNING) << "Failed to create software VideoToolbox session"; |
214 << "Hardware accelerated video decoding will be disabled."; | |
215 return false; | 213 return false; |
216 } | 214 } |
217 | 215 |
218 return true; | 216 return true; |
219 } | 217 } |
220 | 218 |
221 bool InitializeVideoToolbox() { | 219 bool InitializeVideoToolbox() { |
222 // InitializeVideoToolbox() is called only from the GPU process main thread; | 220 // InitializeVideoToolbox() is called only from the GPU process main thread; |
223 // once for sandbox warmup, and then once each time a VTVideoDecodeAccelerator | 221 // once for sandbox warmup, and then once each time a VTVideoDecodeAccelerator |
224 // is initialized. | 222 // is initialized. |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 coded_size_.SetSize(coded_dimensions.width, coded_dimensions.height); | 404 coded_size_.SetSize(coded_dimensions.width, coded_dimensions.height); |
407 | 405 |
408 // Prepare VideoToolbox configuration dictionaries. | 406 // Prepare VideoToolbox configuration dictionaries. |
409 base::ScopedCFTypeRef<CFMutableDictionaryRef> decoder_config( | 407 base::ScopedCFTypeRef<CFMutableDictionaryRef> decoder_config( |
410 CFDictionaryCreateMutable( | 408 CFDictionaryCreateMutable( |
411 kCFAllocatorDefault, | 409 kCFAllocatorDefault, |
412 1, // capacity | 410 1, // capacity |
413 &kCFTypeDictionaryKeyCallBacks, | 411 &kCFTypeDictionaryKeyCallBacks, |
414 &kCFTypeDictionaryValueCallBacks)); | 412 &kCFTypeDictionaryValueCallBacks)); |
415 if (!decoder_config.get()) { | 413 if (!decoder_config.get()) { |
416 DLOG(ERROR) << "Failed to create CFMutableDictionary."; | 414 DLOG(ERROR) << "Failed to create CFMutableDictionary"; |
417 NotifyError(PLATFORM_FAILURE, SFT_PLATFORM_ERROR); | 415 NotifyError(PLATFORM_FAILURE, SFT_PLATFORM_ERROR); |
418 return false; | 416 return false; |
419 } | 417 } |
420 | 418 |
421 CFDictionarySetValue( | 419 CFDictionarySetValue( |
422 decoder_config, | 420 decoder_config, |
423 // kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder | 421 // kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder |
424 CFSTR("EnableHardwareAcceleratedVideoDecoder"), | 422 CFSTR("EnableHardwareAcceleratedVideoDecoder"), |
425 kCFBooleanTrue); | 423 kCFBooleanTrue); |
426 | 424 |
427 base::ScopedCFTypeRef<CFMutableDictionaryRef> image_config( | 425 base::ScopedCFTypeRef<CFMutableDictionaryRef> image_config( |
428 BuildImageConfig(coded_dimensions)); | 426 BuildImageConfig(coded_dimensions)); |
429 if (!image_config.get()) { | 427 if (!image_config.get()) { |
430 DLOG(ERROR) << "Failed to create decoder image configuration."; | 428 DLOG(ERROR) << "Failed to create decoder image configuration"; |
431 NotifyError(PLATFORM_FAILURE, SFT_PLATFORM_ERROR); | 429 NotifyError(PLATFORM_FAILURE, SFT_PLATFORM_ERROR); |
432 return false; | 430 return false; |
433 } | 431 } |
434 | 432 |
435 // Ensure that the old decoder emits all frames before the new decoder can | 433 // Ensure that the old decoder emits all frames before the new decoder can |
436 // emit any. | 434 // emit any. |
437 if (!FinishDelayedFrames()) | 435 if (!FinishDelayedFrames()) |
438 return false; | 436 return false; |
439 | 437 |
440 session_.reset(); | 438 session_.reset(); |
(...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
945 last_pps_.clear(); | 943 last_pps_.clear(); |
946 poc_.Reset(); | 944 poc_.Reset(); |
947 pending_flush_tasks_.pop(); | 945 pending_flush_tasks_.pop(); |
948 client_->NotifyResetDone(); | 946 client_->NotifyResetDone(); |
949 task_queue_.pop(); | 947 task_queue_.pop(); |
950 return true; | 948 return true; |
951 } | 949 } |
952 return false; | 950 return false; |
953 | 951 |
954 case TASK_DESTROY: | 952 case TASK_DESTROY: |
955 NOTREACHED() << "Can't destroy while in STATE_DECODING."; | 953 NOTREACHED() << "Can't destroy while in STATE_DECODING"; |
956 NotifyError(ILLEGAL_STATE, SFT_PLATFORM_ERROR); | 954 NotifyError(ILLEGAL_STATE, SFT_PLATFORM_ERROR); |
957 return false; | 955 return false; |
958 } | 956 } |
959 } | 957 } |
960 | 958 |
961 bool VTVideoDecodeAccelerator::ProcessReorderQueue() { | 959 bool VTVideoDecodeAccelerator::ProcessReorderQueue() { |
962 DCHECK(gpu_thread_checker_.CalledOnValidThread()); | 960 DCHECK(gpu_thread_checker_.CalledOnValidThread()); |
963 DCHECK_EQ(state_, STATE_DECODING); | 961 DCHECK_EQ(state_, STATE_DECODING); |
964 | 962 |
965 if (reorder_queue_.empty()) | 963 if (reorder_queue_.empty()) |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1143 SupportedProfile profile; | 1141 SupportedProfile profile; |
1144 profile.profile = supported_profile; | 1142 profile.profile = supported_profile; |
1145 profile.min_resolution.SetSize(16, 16); | 1143 profile.min_resolution.SetSize(16, 16); |
1146 profile.max_resolution.SetSize(4096, 2160); | 1144 profile.max_resolution.SetSize(4096, 2160); |
1147 profiles.push_back(profile); | 1145 profiles.push_back(profile); |
1148 } | 1146 } |
1149 return profiles; | 1147 return profiles; |
1150 } | 1148 } |
1151 | 1149 |
1152 } // namespace content | 1150 } // namespace content |
OLD | NEW |