| 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 | 10 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 // libraries required by VideoToolbox before the GPU sandbox is enabled. | 79 // libraries required by VideoToolbox before the GPU sandbox is enabled. |
| 80 // VideoToolbox normally loads the hardware-specific libraries lazily, so we | 80 // VideoToolbox normally loads the hardware-specific libraries lazily, so we |
| 81 // must actually create a decompression session. | 81 // must actually create a decompression session. |
| 82 // | 82 // |
| 83 // If creating a decompression session fails, hardware decoding will be disabled | 83 // If creating a decompression session fails, hardware decoding will be disabled |
| 84 // (Initialize() will always return false). If it succeeds but a required | 84 // (Initialize() will always return false). If it succeeds but a required |
| 85 // library is not loaded yet (I have not experienced this, but the details are | 85 // library is not loaded yet (I have not experienced this, but the details are |
| 86 // not documented), then VideoToolbox will fall back on software decoding | 86 // not documented), then VideoToolbox will fall back on software decoding |
| 87 // internally. If that happens, the likely solution is to expand the scope of | 87 // internally. If that happens, the likely solution is to expand the scope of |
| 88 // this initialization. | 88 // this initialization. |
| 89 void InitializeVideoToolbox() { | 89 static bool InitializeVideoToolboxInternal() { |
| 90 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 90 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 91 switches::kDisableAcceleratedVideoDecode)) { | 91 switches::kDisableAcceleratedVideoDecode)) { |
| 92 return; | 92 return false; |
| 93 } | 93 } |
| 94 | 94 |
| 95 if (!IsVtInitialized()) { | 95 if (!IsVtInitialized()) { |
| 96 // CoreVideo is also required, but the loader stops after the first path is | 96 // CoreVideo is also required, but the loader stops after the first path is |
| 97 // loaded. Instead we rely on the transitive dependency from VideoToolbox to | 97 // loaded. Instead we rely on the transitive dependency from VideoToolbox to |
| 98 // CoreVideo. | 98 // CoreVideo. |
| 99 // TODO(sandersd): Fallback to PrivateFrameworks to support OS X < 10.8. | 99 // TODO(sandersd): Fallback to PrivateFrameworks to support OS X < 10.8. |
| 100 StubPathMap paths; | 100 StubPathMap paths; |
| 101 paths[kModuleVt].push_back(FILE_PATH_LITERAL( | 101 paths[kModuleVt].push_back(FILE_PATH_LITERAL( |
| 102 "/System/Library/Frameworks/VideoToolbox.framework/VideoToolbox")); | 102 "/System/Library/Frameworks/VideoToolbox.framework/VideoToolbox")); |
| 103 if (!InitializeStubs(paths)) | 103 if (!InitializeStubs(paths)) |
| 104 return; | 104 return false; |
| 105 } | 105 } |
| 106 | 106 |
| 107 // Create a decoding session. | 107 // Create a decoding session. |
| 108 // SPS and PPS data were taken from the 480p encoding of Big Buck Bunny. | 108 // SPS and PPS data were taken from the 480p encoding of Big Buck Bunny. |
| 109 const uint8_t sps[] = {0x67, 0x64, 0x00, 0x1e, 0xac, 0xd9, 0x80, 0xd4, 0x3d, | 109 const uint8_t sps[] = {0x67, 0x64, 0x00, 0x1e, 0xac, 0xd9, 0x80, 0xd4, 0x3d, |
| 110 0xa1, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x03, | 110 0xa1, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x03, |
| 111 0x00, 0x30, 0x8f, 0x16, 0x2d, 0x9a}; | 111 0x00, 0x30, 0x8f, 0x16, 0x2d, 0x9a}; |
| 112 const uint8_t pps[] = {0x68, 0xe9, 0x7b, 0xcb}; | 112 const uint8_t pps[] = {0x68, 0xe9, 0x7b, 0xcb}; |
| 113 const uint8_t* data_ptrs[] = {sps, pps}; | 113 const uint8_t* data_ptrs[] = {sps, pps}; |
| 114 const size_t data_sizes[] = {arraysize(sps), arraysize(pps)}; | 114 const size_t data_sizes[] = {arraysize(sps), arraysize(pps)}; |
| 115 | 115 |
| 116 base::ScopedCFTypeRef<CMFormatDescriptionRef> format; | 116 base::ScopedCFTypeRef<CMFormatDescriptionRef> format; |
| 117 OSStatus status = CMVideoFormatDescriptionCreateFromH264ParameterSets( | 117 OSStatus status = CMVideoFormatDescriptionCreateFromH264ParameterSets( |
| 118 kCFAllocatorDefault, | 118 kCFAllocatorDefault, |
| 119 2, // parameter_set_count | 119 2, // parameter_set_count |
| 120 data_ptrs, // ¶meter_set_pointers | 120 data_ptrs, // ¶meter_set_pointers |
| 121 data_sizes, // ¶meter_set_sizes | 121 data_sizes, // ¶meter_set_sizes |
| 122 kNALUHeaderLength, // nal_unit_header_length | 122 kNALUHeaderLength, // nal_unit_header_length |
| 123 format.InitializeInto()); | 123 format.InitializeInto()); |
| 124 if (status) { | 124 if (status) { |
| 125 OSSTATUS_LOG(ERROR, status) << "Failed to create CMVideoFormatDescription " | 125 OSSTATUS_LOG(ERROR, status) << "Failed to create CMVideoFormatDescription " |
| 126 << "while initializing VideoToolbox"; | 126 << "while initializing VideoToolbox"; |
| 127 content_common_gpu_media::UninitializeVt(); | 127 return false; |
| 128 return; | |
| 129 } | 128 } |
| 130 | 129 |
| 131 base::ScopedCFTypeRef<CFMutableDictionaryRef> decoder_config( | 130 base::ScopedCFTypeRef<CFMutableDictionaryRef> decoder_config( |
| 132 CFDictionaryCreateMutable( | 131 CFDictionaryCreateMutable( |
| 133 kCFAllocatorDefault, | 132 kCFAllocatorDefault, |
| 134 1, // capacity | 133 1, // capacity |
| 135 &kCFTypeDictionaryKeyCallBacks, | 134 &kCFTypeDictionaryKeyCallBacks, |
| 136 &kCFTypeDictionaryValueCallBacks)); | 135 &kCFTypeDictionaryValueCallBacks)); |
| 137 | 136 |
| 138 CFDictionarySetValue( | 137 CFDictionarySetValue( |
| (...skipping 11 matching lines...) Expand all Loading... |
| 150 status = VTDecompressionSessionCreate( | 149 status = VTDecompressionSessionCreate( |
| 151 kCFAllocatorDefault, | 150 kCFAllocatorDefault, |
| 152 format, // video_format_description | 151 format, // video_format_description |
| 153 decoder_config, // video_decoder_specification | 152 decoder_config, // video_decoder_specification |
| 154 image_config, // destination_image_buffer_attributes | 153 image_config, // destination_image_buffer_attributes |
| 155 &callback, // output_callback | 154 &callback, // output_callback |
| 156 session.InitializeInto()); | 155 session.InitializeInto()); |
| 157 if (status) { | 156 if (status) { |
| 158 OSSTATUS_LOG(ERROR, status) << "Failed to create VTDecompressionSession " | 157 OSSTATUS_LOG(ERROR, status) << "Failed to create VTDecompressionSession " |
| 159 << "while initializing VideoToolbox"; | 158 << "while initializing VideoToolbox"; |
| 160 content_common_gpu_media::UninitializeVt(); | 159 return false; |
| 161 return; | |
| 162 } | 160 } |
| 161 |
| 162 return true; |
| 163 } |
| 164 |
| 165 bool InitializeVideoToolbox() { |
| 166 // InitializeVideoToolbox() is called during GPU process sandbox warmup, |
| 167 // and then only from the GPU process main thread. |
| 168 static bool attempted = false; |
| 169 static bool succeeded = false; |
| 170 |
| 171 if (!attempted) { |
| 172 attempted = true; |
| 173 succeeded = InitializeVideoToolboxInternal(); |
| 174 } |
| 175 |
| 176 return succeeded; |
| 163 } | 177 } |
| 164 | 178 |
| 165 // Route decoded frame callbacks back into the VTVideoDecodeAccelerator. | 179 // Route decoded frame callbacks back into the VTVideoDecodeAccelerator. |
| 166 static void OutputThunk( | 180 static void OutputThunk( |
| 167 void* decompression_output_refcon, | 181 void* decompression_output_refcon, |
| 168 void* source_frame_refcon, | 182 void* source_frame_refcon, |
| 169 OSStatus status, | 183 OSStatus status, |
| 170 VTDecodeInfoFlags info_flags, | 184 VTDecodeInfoFlags info_flags, |
| 171 CVImageBufferRef image_buffer, | 185 CVImageBufferRef image_buffer, |
| 172 CMTime presentation_time_stamp, | 186 CMTime presentation_time_stamp, |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 | 237 |
| 224 VTVideoDecodeAccelerator::~VTVideoDecodeAccelerator() { | 238 VTVideoDecodeAccelerator::~VTVideoDecodeAccelerator() { |
| 225 } | 239 } |
| 226 | 240 |
| 227 bool VTVideoDecodeAccelerator::Initialize( | 241 bool VTVideoDecodeAccelerator::Initialize( |
| 228 media::VideoCodecProfile profile, | 242 media::VideoCodecProfile profile, |
| 229 Client* client) { | 243 Client* client) { |
| 230 DCHECK(gpu_thread_checker_.CalledOnValidThread()); | 244 DCHECK(gpu_thread_checker_.CalledOnValidThread()); |
| 231 client_ = client; | 245 client_ = client; |
| 232 | 246 |
| 233 if (!IsVtInitialized()) | 247 if (!InitializeVideoToolbox()) |
| 234 return false; | 248 return false; |
| 235 | 249 |
| 236 // Only H.264 is supported. | 250 // Only H.264 is supported. |
| 237 if (profile < media::H264PROFILE_MIN || profile > media::H264PROFILE_MAX) | 251 if (profile < media::H264PROFILE_MIN || profile > media::H264PROFILE_MAX) |
| 238 return false; | 252 return false; |
| 239 | 253 |
| 240 // Spawn a thread to handle parsing and calling VideoToolbox. | 254 // Spawn a thread to handle parsing and calling VideoToolbox. |
| 241 if (!decoder_thread_.Start()) | 255 if (!decoder_thread_.Start()) |
| 242 return false; | 256 return false; |
| 243 | 257 |
| (...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 898 assigned_bitstream_ids_.clear(); | 912 assigned_bitstream_ids_.clear(); |
| 899 state_ = STATE_DESTROYING; | 913 state_ = STATE_DESTROYING; |
| 900 QueueFlush(TASK_DESTROY); | 914 QueueFlush(TASK_DESTROY); |
| 901 } | 915 } |
| 902 | 916 |
| 903 bool VTVideoDecodeAccelerator::CanDecodeOnIOThread() { | 917 bool VTVideoDecodeAccelerator::CanDecodeOnIOThread() { |
| 904 return false; | 918 return false; |
| 905 } | 919 } |
| 906 | 920 |
| 907 } // namespace content | 921 } // namespace content |
| OLD | NEW |