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 |