OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "media/filters/gpu_video_decoder.h" | 5 #include "media/filters/gpu_video_decoder.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/callback_helpers.h" | 11 #include "base/callback_helpers.h" |
12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
13 #include "base/cpu.h" | 13 #include "base/cpu.h" |
14 #include "base/message_loop/message_loop.h" | 14 #include "base/message_loop/message_loop.h" |
15 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
16 #include "base/stl_util.h" | 16 #include "base/stl_util.h" |
17 #include "base/task_runner_util.h" | 17 #include "base/task_runner_util.h" |
18 #include "build/build_config.h" | 18 #include "build/build_config.h" |
19 #include "gpu/command_buffer/common/mailbox_holder.h" | 19 #include "gpu/command_buffer/common/mailbox_holder.h" |
20 #include "media/base/bind_to_current_loop.h" | 20 #include "media/base/bind_to_current_loop.h" |
21 #include "media/base/decoder_buffer.h" | 21 #include "media/base/decoder_buffer.h" |
22 #include "media/base/media_switches.h" | 22 #include "media/base/media_switches.h" |
23 #include "media/base/pipeline.h" | 23 #include "media/base/pipeline.h" |
| 24 #include "media/base/surface_manager.h" |
24 #include "media/base/video_decoder_config.h" | 25 #include "media/base/video_decoder_config.h" |
25 #include "media/renderers/gpu_video_accelerator_factories.h" | 26 #include "media/renderers/gpu_video_accelerator_factories.h" |
26 #include "third_party/skia/include/core/SkBitmap.h" | 27 #include "third_party/skia/include/core/SkBitmap.h" |
27 | 28 |
28 namespace media { | 29 namespace media { |
29 | 30 |
30 const char GpuVideoDecoder::kDecoderName[] = "GpuVideoDecoder"; | 31 const char GpuVideoDecoder::kDecoderName[] = "GpuVideoDecoder"; |
31 | 32 |
32 // Maximum number of concurrent VDA::Decode() operations GVD will maintain. | 33 // Maximum number of concurrent VDA::Decode() operations GVD will maintain. |
33 // Higher values allow better pipelining in the GPU, but also require more | 34 // Higher values allow better pipelining in the GPU, but also require more |
(...skipping 23 matching lines...) Expand all Loading... |
57 base::TimeDelta ts, | 58 base::TimeDelta ts, |
58 const gfx::Rect& vr, | 59 const gfx::Rect& vr, |
59 const gfx::Size& ns) | 60 const gfx::Size& ns) |
60 : bitstream_buffer_id(bbid), | 61 : bitstream_buffer_id(bbid), |
61 timestamp(ts), | 62 timestamp(ts), |
62 visible_rect(vr), | 63 visible_rect(vr), |
63 natural_size(ns) {} | 64 natural_size(ns) {} |
64 | 65 |
65 GpuVideoDecoder::BufferData::~BufferData() {} | 66 GpuVideoDecoder::BufferData::~BufferData() {} |
66 | 67 |
67 GpuVideoDecoder::GpuVideoDecoder(GpuVideoAcceleratorFactories* factories) | 68 GpuVideoDecoder::GpuVideoDecoder(GpuVideoAcceleratorFactories* factories, |
| 69 const RequestSurfaceCB& request_surface_cb) |
68 : needs_bitstream_conversion_(false), | 70 : needs_bitstream_conversion_(false), |
69 factories_(factories), | 71 factories_(factories), |
70 state_(kNormal), | 72 state_(kNormal), |
| 73 request_surface_cb_(request_surface_cb), |
71 decoder_texture_target_(0), | 74 decoder_texture_target_(0), |
72 next_picture_buffer_id_(0), | 75 next_picture_buffer_id_(0), |
73 next_bitstream_buffer_id_(0), | 76 next_bitstream_buffer_id_(0), |
74 available_pictures_(0), | 77 available_pictures_(0), |
75 needs_all_picture_buffers_to_decode_(false), | 78 needs_all_picture_buffers_to_decode_(false), |
76 weak_factory_(this) { | 79 weak_factory_(this) { |
77 DCHECK(factories_); | 80 DCHECK(factories_); |
78 } | 81 } |
79 | 82 |
80 void GpuVideoDecoder::Reset(const base::Closure& closure) { | 83 void GpuVideoDecoder::Reset(const base::Closure& closure) { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
140 BindToCurrentLoop(init_cb)); | 143 BindToCurrentLoop(init_cb)); |
141 | 144 |
142 #if !defined(OS_ANDROID) | 145 #if !defined(OS_ANDROID) |
143 if (config.is_encrypted()) { | 146 if (config.is_encrypted()) { |
144 DVLOG(1) << "Encrypted stream not supported."; | 147 DVLOG(1) << "Encrypted stream not supported."; |
145 bound_init_cb.Run(false); | 148 bound_init_cb.Run(false); |
146 return; | 149 return; |
147 } | 150 } |
148 #endif | 151 #endif |
149 | 152 |
150 bool previously_initialized = config_.IsValidConfig(); | |
151 DVLOG(1) << "(Re)initializing GVD with config: " | |
152 << config.AsHumanReadableString(); | |
153 | |
154 // TODO(posciak): destroy and create a new VDA on codec/profile change | 153 // TODO(posciak): destroy and create a new VDA on codec/profile change |
155 // (http://crbug.com/260224). | 154 // (http://crbug.com/260224). |
| 155 bool previously_initialized = config_.IsValidConfig(); |
| 156 DVLOG(1) << (previously_initialized ? "Reinitializing" : "Initializing") |
| 157 << "GVD with config: " << config.AsHumanReadableString(); |
| 158 |
156 if (previously_initialized && (config_.profile() != config.profile())) { | 159 if (previously_initialized && (config_.profile() != config.profile())) { |
157 DVLOG(1) << "Codec or profile changed, cannot reinitialize."; | 160 DVLOG(1) << "Codec or profile changed, cannot reinitialize."; |
158 bound_init_cb.Run(false); | 161 bound_init_cb.Run(false); |
159 return; | 162 return; |
160 } | 163 } |
161 | 164 |
162 VideoDecodeAccelerator::Capabilities capabilities = | 165 VideoDecodeAccelerator::Capabilities capabilities = |
163 factories_->GetVideoDecodeAcceleratorCapabilities(); | 166 factories_->GetVideoDecodeAcceleratorCapabilities(); |
164 if (!IsProfileSupported(capabilities, config.profile(), | 167 if (!IsProfileSupported(capabilities, config.profile(), |
165 config.coded_size())) { | 168 config.coded_size())) { |
(...skipping 14 matching lines...) Expand all Loading... |
180 DVLOG(3) << __FUNCTION__ | 183 DVLOG(3) << __FUNCTION__ |
181 << " Expecting initialized VDA to detect in-stream config change."; | 184 << " Expecting initialized VDA to detect in-stream config change."; |
182 // Reinitialization with a different config (but same codec and profile). | 185 // Reinitialization with a different config (but same codec and profile). |
183 // VDA should handle it by detecting this in-stream by itself, | 186 // VDA should handle it by detecting this in-stream by itself, |
184 // no need to notify it. | 187 // no need to notify it. |
185 bound_init_cb.Run(true); | 188 bound_init_cb.Run(true); |
186 return; | 189 return; |
187 } | 190 } |
188 | 191 |
189 vda_ = factories_->CreateVideoDecodeAccelerator(); | 192 vda_ = factories_->CreateVideoDecodeAccelerator(); |
190 | 193 if (!vda_) { |
191 VideoDecodeAccelerator::Config vda_config(config); | 194 DVLOG(1) << "Failed to create a VDA."; |
192 | |
193 if (!vda_ || !vda_->Initialize(vda_config, this)) { | |
194 DVLOG(1) << "VDA initialization failed."; | |
195 bound_init_cb.Run(false); | 195 bound_init_cb.Run(false); |
196 return; | 196 return; |
197 } | 197 } |
198 | 198 |
| 199 // CompleteInitialization will clear both of these callbacks. |
| 200 init_cb_ = bound_init_cb; |
199 if (config.is_encrypted()) { | 201 if (config.is_encrypted()) { |
200 init_cb_ = bound_init_cb; | |
201 set_cdm_ready_cb_ = set_cdm_ready_cb; | 202 set_cdm_ready_cb_ = set_cdm_ready_cb; |
| 203 } |
| 204 |
| 205 if (!request_surface_cb_.is_null()) { |
| 206 // If we have surface request callback we should call it and complete |
| 207 // initialization with the returned surface. |
| 208 request_surface_cb_.Run(BindToCurrentLoop(base::Bind( |
| 209 &GpuVideoDecoder::CompleteInitialization, weak_factory_.GetWeakPtr()))); |
| 210 return; |
| 211 } |
| 212 |
| 213 CompleteInitialization(VideoDecodeAccelerator::Config::kNoSurfaceID); |
| 214 } |
| 215 |
| 216 void GpuVideoDecoder::CompleteInitialization(int surface_id) { |
| 217 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 218 DCHECK(!init_cb_.is_null()); |
| 219 |
| 220 VideoDecodeAccelerator::Config vda_config(config_); |
| 221 vda_config.surface_id = surface_id; |
| 222 if (!vda_->Initialize(vda_config, this)) { |
| 223 DVLOG(1) << "VDA::Initialize failed."; |
| 224 base::ResetAndReturn(&init_cb_).Run(false); |
| 225 return; |
| 226 } |
| 227 |
| 228 // If the stream is encrypted we need to request and attach the CDM |
| 229 // before completing initialization. |
| 230 if (config_.is_encrypted()) { |
202 set_cdm_ready_cb_.Run(BindToCurrentLoop( | 231 set_cdm_ready_cb_.Run(BindToCurrentLoop( |
203 base::Bind(&GpuVideoDecoder::SetCdm, weak_factory_.GetWeakPtr()))); | 232 base::Bind(&GpuVideoDecoder::SetCdm, weak_factory_.GetWeakPtr()))); |
204 return; | 233 return; |
205 } | 234 } |
206 | 235 |
207 DVLOG(3) << "GpuVideoDecoder::Initialize() succeeded."; | 236 base::ResetAndReturn(&init_cb_).Run(true); |
208 bound_init_cb.Run(true); | |
209 } | 237 } |
210 | 238 |
211 void GpuVideoDecoder::SetCdm(CdmContext* cdm_context, | 239 void GpuVideoDecoder::SetCdm(CdmContext* cdm_context, |
212 const CdmAttachedCB& cdm_attached_cb) { | 240 const CdmAttachedCB& cdm_attached_cb) { |
213 DVLOG(2) << __FUNCTION__; | 241 DVLOG(2) << __FUNCTION__; |
214 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 242 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
215 | 243 |
216 DCHECK(!init_cb_.is_null()); | 244 DCHECK(!init_cb_.is_null()); |
217 DCHECK(!set_cdm_ready_cb_.is_null()); | 245 DCHECK(!set_cdm_ready_cb_.is_null()); |
218 set_cdm_ready_cb_.Reset(); | 246 set_cdm_ready_cb_.Reset(); |
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
686 } | 714 } |
687 return false; | 715 return false; |
688 } | 716 } |
689 | 717 |
690 void GpuVideoDecoder::DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent() | 718 void GpuVideoDecoder::DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent() |
691 const { | 719 const { |
692 DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread()); | 720 DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread()); |
693 } | 721 } |
694 | 722 |
695 } // namespace media | 723 } // namespace media |
OLD | NEW |