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