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 14 matching lines...) Expand all Loading... | |
25 using content_common_gpu_media::StubPathMap; | 25 using content_common_gpu_media::StubPathMap; |
26 | 26 |
27 #define NOTIFY_STATUS(name, status) \ | 27 #define NOTIFY_STATUS(name, status) \ |
28 do { \ | 28 do { \ |
29 OSSTATUS_DLOG(ERROR, status) << name; \ | 29 OSSTATUS_DLOG(ERROR, status) << name; \ |
30 NotifyError(PLATFORM_FAILURE); \ | 30 NotifyError(PLATFORM_FAILURE); \ |
31 } while (0) | 31 } while (0) |
32 | 32 |
33 namespace content { | 33 namespace content { |
34 | 34 |
35 // Track VideoToolbox loaded to make sure that loading is attempted once and | |
DaleCurtis
2014/12/04 01:57:31
Seems instead you should be using a LazyInstance::
sandersd (OOO until July 31)
2014/12/04 02:05:48
That seems rather complicated for this use case, s
| |
36 // only once, regardless of the --no-sandbox flag. | |
37 static bool vt_init_attempted = false; | |
38 static bool vt_init_successful = false; | |
39 | |
35 // Size to use for NALU length headers in AVC format (can be 1, 2, or 4). | 40 // Size to use for NALU length headers in AVC format (can be 1, 2, or 4). |
36 static const int kNALUHeaderLength = 4; | 41 static const int kNALUHeaderLength = 4; |
37 | 42 |
38 // We request 5 picture buffers from the client, each of which has a texture ID | 43 // We request 5 picture buffers from the client, each of which has a texture ID |
39 // that we can bind decoded frames to. We need enough to satisfy preroll, and | 44 // that we can bind decoded frames to. We need enough to satisfy preroll, and |
40 // enough to avoid unnecessary stalling, but no more than that. The resource | 45 // enough to avoid unnecessary stalling, but no more than that. The resource |
41 // requirements are low, as we don't need the textures to be backed by storage. | 46 // requirements are low, as we don't need the textures to be backed by storage. |
42 static const int kNumPictureBuffers = media::limits::kMaxVideoFrames + 1; | 47 static const int kNumPictureBuffers = media::limits::kMaxVideoFrames + 1; |
43 | 48 |
44 // Maximum number of frames to queue for reordering before we stop asking for | 49 // Maximum number of frames to queue for reordering before we stop asking for |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
79 // VideoToolbox normally loads the hardware-specific libraries lazily, so we | 84 // VideoToolbox normally loads the hardware-specific libraries lazily, so we |
80 // must actually create a decompression session. | 85 // must actually create a decompression session. |
81 // | 86 // |
82 // If creating a decompression session fails, hardware decoding will be disabled | 87 // If creating a decompression session fails, hardware decoding will be disabled |
83 // (Initialize() will always return false). If it succeeds but a required | 88 // (Initialize() will always return false). If it succeeds but a required |
84 // library is not loaded yet (I have not experienced this, but the details are | 89 // library is not loaded yet (I have not experienced this, but the details are |
85 // not documented), then VideoToolbox will fall back on software decoding | 90 // not documented), then VideoToolbox will fall back on software decoding |
86 // internally. If that happens, the likely solution is to expand the scope of | 91 // internally. If that happens, the likely solution is to expand the scope of |
87 // this initialization. | 92 // this initialization. |
88 void InitializeVideoToolbox() { | 93 void InitializeVideoToolbox() { |
94 vt_init_attempted = true; | |
95 | |
89 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 96 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
90 switches::kDisableAcceleratedVideoDecode)) { | 97 switches::kDisableAcceleratedVideoDecode)) { |
91 return; | 98 return; |
92 } | 99 } |
93 | 100 |
94 if (!IsVtInitialized()) { | 101 if (!IsVtInitialized()) { |
95 // CoreVideo is also required, but the loader stops after the first path is | 102 // CoreVideo is also required, but the loader stops after the first path is |
96 // loaded. Instead we rely on the transitive dependency from VideoToolbox to | 103 // loaded. Instead we rely on the transitive dependency from VideoToolbox to |
97 // CoreVideo. | 104 // CoreVideo. |
98 // TODO(sandersd): Fallback to PrivateFrameworks to support OS X < 10.8. | 105 // TODO(sandersd): Fallback to PrivateFrameworks to support OS X < 10.8. |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
152 decoder_config, // video_decoder_specification | 159 decoder_config, // video_decoder_specification |
153 image_config, // destination_image_buffer_attributes | 160 image_config, // destination_image_buffer_attributes |
154 &callback, // output_callback | 161 &callback, // output_callback |
155 session.InitializeInto()); | 162 session.InitializeInto()); |
156 if (status) { | 163 if (status) { |
157 OSSTATUS_LOG(ERROR, status) << "Failed to create VTDecompressionSession " | 164 OSSTATUS_LOG(ERROR, status) << "Failed to create VTDecompressionSession " |
158 << "while initializing VideoToolbox"; | 165 << "while initializing VideoToolbox"; |
159 content_common_gpu_media::UninitializeVt(); | 166 content_common_gpu_media::UninitializeVt(); |
160 return; | 167 return; |
161 } | 168 } |
169 | |
170 vt_init_successful = true; | |
162 } | 171 } |
163 | 172 |
164 // Route decoded frame callbacks back into the VTVideoDecodeAccelerator. | 173 // Route decoded frame callbacks back into the VTVideoDecodeAccelerator. |
165 static void OutputThunk( | 174 static void OutputThunk( |
166 void* decompression_output_refcon, | 175 void* decompression_output_refcon, |
167 void* source_frame_refcon, | 176 void* source_frame_refcon, |
168 OSStatus status, | 177 OSStatus status, |
169 VTDecodeInfoFlags info_flags, | 178 VTDecodeInfoFlags info_flags, |
170 CVImageBufferRef image_buffer, | 179 CVImageBufferRef image_buffer, |
171 CMTime presentation_time_stamp, | 180 CMTime presentation_time_stamp, |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
222 | 231 |
223 VTVideoDecodeAccelerator::~VTVideoDecodeAccelerator() { | 232 VTVideoDecodeAccelerator::~VTVideoDecodeAccelerator() { |
224 } | 233 } |
225 | 234 |
226 bool VTVideoDecodeAccelerator::Initialize( | 235 bool VTVideoDecodeAccelerator::Initialize( |
227 media::VideoCodecProfile profile, | 236 media::VideoCodecProfile profile, |
228 Client* client) { | 237 Client* client) { |
229 DCHECK(gpu_thread_checker_.CalledOnValidThread()); | 238 DCHECK(gpu_thread_checker_.CalledOnValidThread()); |
230 client_ = client; | 239 client_ = client; |
231 | 240 |
232 if (!IsVtInitialized()) | 241 if (!vt_init_attempted) |
242 InitializeVideoToolbox(); | |
243 | |
244 if (!vt_init_successful) | |
233 return false; | 245 return false; |
234 | 246 |
235 // Only H.264 is supported. | 247 // Only H.264 is supported. |
236 if (profile < media::H264PROFILE_MIN || profile > media::H264PROFILE_MAX) | 248 if (profile < media::H264PROFILE_MIN || profile > media::H264PROFILE_MAX) |
237 return false; | 249 return false; |
238 | 250 |
239 // Spawn a thread to handle parsing and calling VideoToolbox. | 251 // Spawn a thread to handle parsing and calling VideoToolbox. |
240 if (!decoder_thread_.Start()) | 252 if (!decoder_thread_.Start()) |
241 return false; | 253 return false; |
242 | 254 |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
467 if (config_changed) { | 479 if (config_changed) { |
468 if (last_sps_.size() == 0 || last_pps_.size() == 0) { | 480 if (last_sps_.size() == 0 || last_pps_.size() == 0) { |
469 DLOG(ERROR) << "Invalid configuration data"; | 481 DLOG(ERROR) << "Invalid configuration data"; |
470 NotifyError(INVALID_ARGUMENT); | 482 NotifyError(INVALID_ARGUMENT); |
471 return; | 483 return; |
472 } | 484 } |
473 if (!ConfigureDecoder()) | 485 if (!ConfigureDecoder()) |
474 return; | 486 return; |
475 } | 487 } |
476 | 488 |
477 // If there are no non-configuration units, drop the bitstream buffer by | 489 // If there are no image slices, drop the bitstream buffer by returning an |
478 // returning an empty frame. | 490 // empty frame. |
479 if (!data_size) { | 491 if (!data_size) { |
480 if (!FinishDelayedFrames()) | 492 if (!FinishDelayedFrames()) |
481 return; | 493 return; |
482 gpu_task_runner_->PostTask(FROM_HERE, base::Bind( | 494 gpu_task_runner_->PostTask(FROM_HERE, base::Bind( |
483 &VTVideoDecodeAccelerator::DecodeDone, weak_this_, frame)); | 495 &VTVideoDecodeAccelerator::DecodeDone, weak_this_, frame)); |
484 return; | 496 return; |
485 } | 497 } |
486 | 498 |
487 // If the session is not configured by this point, fail. | 499 // If the session is not configured by this point, fail. |
488 if (!session_) { | 500 if (!session_) { |
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
887 assigned_bitstream_ids_.clear(); | 899 assigned_bitstream_ids_.clear(); |
888 state_ = STATE_DESTROYING; | 900 state_ = STATE_DESTROYING; |
889 QueueFlush(TASK_DESTROY); | 901 QueueFlush(TASK_DESTROY); |
890 } | 902 } |
891 | 903 |
892 bool VTVideoDecodeAccelerator::CanDecodeOnIOThread() { | 904 bool VTVideoDecodeAccelerator::CanDecodeOnIOThread() { |
893 return false; | 905 return false; |
894 } | 906 } |
895 | 907 |
896 } // namespace content | 908 } // namespace content |
OLD | NEW |