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 "content/common/gpu/media/gpu_video_decode_accelerator.h" | 5 #include "content/common/gpu/media/gpu_video_decode_accelerator.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 24 matching lines...) Expand all Loading... | |
35 #elif defined(OS_ANDROID) | 35 #elif defined(OS_ANDROID) |
36 #include "content/common/gpu/media/android_video_decode_accelerator.h" | 36 #include "content/common/gpu/media/android_video_decode_accelerator.h" |
37 #endif | 37 #endif |
38 | 38 |
39 #include "ui/gfx/size.h" | 39 #include "ui/gfx/size.h" |
40 | 40 |
41 namespace content { | 41 namespace content { |
42 | 42 |
43 static bool MakeDecoderContextCurrent( | 43 static bool MakeDecoderContextCurrent( |
44 const base::WeakPtr<GpuCommandBufferStub> stub) { | 44 const base::WeakPtr<GpuCommandBufferStub> stub) { |
45 if (!stub.get()) { | 45 if (!stub) { |
46 DLOG(ERROR) << "Stub is gone; won't MakeCurrent()."; | 46 DLOG(ERROR) << "Stub is gone; won't MakeCurrent()."; |
47 return false; | 47 return false; |
48 } | 48 } |
49 | 49 |
50 if (!stub->decoder()->MakeCurrent()) { | 50 if (!stub->decoder()->MakeCurrent()) { |
51 DLOG(ERROR) << "Failed to MakeCurrent()"; | 51 DLOG(ERROR) << "Failed to MakeCurrent()"; |
52 return false; | 52 return false; |
53 } | 53 } |
54 | 54 |
55 return true; | 55 return true; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
113 GpuVideoDecodeAccelerator* owner_; | 113 GpuVideoDecodeAccelerator* owner_; |
114 int32 host_route_id_; | 114 int32 host_route_id_; |
115 // The channel to which this filter was added. | 115 // The channel to which this filter was added. |
116 IPC::Channel* channel_; | 116 IPC::Channel* channel_; |
117 }; | 117 }; |
118 | 118 |
119 GpuVideoDecodeAccelerator::GpuVideoDecodeAccelerator( | 119 GpuVideoDecodeAccelerator::GpuVideoDecodeAccelerator( |
120 int32 host_route_id, | 120 int32 host_route_id, |
121 GpuCommandBufferStub* stub, | 121 GpuCommandBufferStub* stub, |
122 const scoped_refptr<base::MessageLoopProxy>& io_message_loop) | 122 const scoped_refptr<base::MessageLoopProxy>& io_message_loop) |
123 : init_done_msg_(NULL), | 123 : host_route_id_(host_route_id), |
124 host_route_id_(host_route_id), | |
125 stub_(stub), | 124 stub_(stub), |
126 texture_target_(0), | 125 texture_target_(0), |
127 filter_removed_(true, false), | 126 filter_removed_(true, false), |
128 io_message_loop_(io_message_loop), | 127 io_message_loop_(io_message_loop), |
129 weak_factory_for_io_(this) { | 128 weak_factory_for_io_(this) { |
130 DCHECK(stub_); | 129 DCHECK(stub_); |
131 stub_->AddDestructionObserver(this); | 130 stub_->AddDestructionObserver(this); |
132 stub_->channel()->AddRoute(host_route_id_, this); | |
133 child_message_loop_ = base::MessageLoopProxy::current(); | 131 child_message_loop_ = base::MessageLoopProxy::current(); |
134 make_context_current_ = | 132 make_context_current_ = |
135 base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr()); | 133 base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr()); |
136 } | 134 } |
137 | 135 |
138 GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() { | 136 GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() { |
139 // This class can only be self-deleted from OnWillDestroyStub(), which means | 137 // This class can only be self-deleted from OnWillDestroyStub(), which means |
140 // the VDA has already been destroyed in there. | 138 // the VDA has already been destroyed in there. |
141 CHECK(!video_decode_accelerator_.get()); | 139 DCHECK(!video_decode_accelerator_); |
142 } | 140 } |
143 | 141 |
144 bool GpuVideoDecodeAccelerator::OnMessageReceived(const IPC::Message& msg) { | 142 bool GpuVideoDecodeAccelerator::OnMessageReceived(const IPC::Message& msg) { |
145 if (!video_decode_accelerator_) | 143 if (!video_decode_accelerator_) |
146 return false; | 144 return false; |
147 | 145 |
148 bool handled = true; | 146 bool handled = true; |
149 IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAccelerator, msg) | 147 IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAccelerator, msg) |
150 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Decode, OnDecode) | 148 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Decode, OnDecode) |
151 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_AssignPictureBuffers, | 149 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_AssignPictureBuffers, |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
196 | 194 |
197 void GpuVideoDecodeAccelerator::PictureReady( | 195 void GpuVideoDecodeAccelerator::PictureReady( |
198 const media::Picture& picture) { | 196 const media::Picture& picture) { |
199 // VDA may call PictureReady on IO thread. SetTextureCleared should run on | 197 // VDA may call PictureReady on IO thread. SetTextureCleared should run on |
200 // the child thread. VDA is responsible to call PictureReady on the child | 198 // the child thread. VDA is responsible to call PictureReady on the child |
201 // thread when a picture buffer is delivered the first time. | 199 // thread when a picture buffer is delivered the first time. |
202 if (child_message_loop_->BelongsToCurrentThread()) { | 200 if (child_message_loop_->BelongsToCurrentThread()) { |
203 SetTextureCleared(picture); | 201 SetTextureCleared(picture); |
204 } else { | 202 } else { |
205 DCHECK(io_message_loop_->BelongsToCurrentThread()); | 203 DCHECK(io_message_loop_->BelongsToCurrentThread()); |
206 DebugAutoLock auto_lock(debug_uncleared_textures_lock_); | 204 DebugAutoLock auto_lock(debug_uncleared_textures_lock_); |
Ami GONE FROM CHROMIUM
2014/03/18 23:53:19
this is tricky business; it replaces a run-time DC
sheu
2014/03/19 20:38:24
Rebase change :-(
DCHECK_IS_ON is now a compile-t
| |
207 DCHECK_EQ(0u, uncleared_textures_.count(picture.picture_buffer_id())); | 205 DCHECK_EQ(0u, uncleared_textures_.count(picture.picture_buffer_id())); |
208 } | 206 } |
209 | 207 |
210 if (!Send(new AcceleratedVideoDecoderHostMsg_PictureReady( | 208 if (!Send(new AcceleratedVideoDecoderHostMsg_PictureReady( |
211 host_route_id_, | 209 host_route_id_, |
212 picture.picture_buffer_id(), | 210 picture.picture_buffer_id(), |
213 picture.bitstream_buffer_id()))) { | 211 picture.bitstream_buffer_id()))) { |
214 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_PictureReady) failed"; | 212 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_PictureReady) failed"; |
215 } | 213 } |
216 } | 214 } |
217 | 215 |
218 void GpuVideoDecodeAccelerator::NotifyError( | 216 void GpuVideoDecodeAccelerator::NotifyError( |
219 media::VideoDecodeAccelerator::Error error) { | 217 media::VideoDecodeAccelerator::Error error) { |
220 if (init_done_msg_) { | |
221 // If we get an error while we're initializing, NotifyInitializeDone won't | |
222 // be called, so we need to send the reply (with an error) here. | |
223 GpuCommandBufferMsg_CreateVideoDecoder::WriteReplyParams( | |
224 init_done_msg_, -1); | |
225 if (!Send(init_done_msg_)) | |
226 DLOG(ERROR) << "Send(init_done_msg_) failed"; | |
227 init_done_msg_ = NULL; | |
228 return; | |
229 } | |
230 if (!Send(new AcceleratedVideoDecoderHostMsg_ErrorNotification( | 218 if (!Send(new AcceleratedVideoDecoderHostMsg_ErrorNotification( |
231 host_route_id_, error))) { | 219 host_route_id_, error))) { |
232 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ErrorNotification) " | 220 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ErrorNotification) " |
233 << "failed"; | 221 << "failed"; |
234 } | 222 } |
235 } | 223 } |
236 | 224 |
237 void GpuVideoDecodeAccelerator::Initialize( | 225 void GpuVideoDecodeAccelerator::Initialize( |
238 const media::VideoCodecProfile profile, | 226 const media::VideoCodecProfile profile, |
239 IPC::Message* init_done_msg) { | 227 IPC::Message* init_done_msg) { |
240 DCHECK(!video_decode_accelerator_.get()); | 228 DCHECK(!video_decode_accelerator_.get()); |
241 DCHECK(!init_done_msg_); | |
242 DCHECK(init_done_msg); | |
243 init_done_msg_ = init_done_msg; | |
244 | 229 |
245 #if !defined(OS_WIN) | 230 #if !defined(OS_WIN) |
246 // Ensure we will be able to get a GL context at all before initializing | 231 // Ensure we will be able to get a GL context at all before initializing |
247 // non-Windows VDAs. | 232 // non-Windows VDAs. |
248 if (!make_context_current_.Run()) { | 233 if (!make_context_current_.Run()) { |
249 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 234 SendCreateDecoderReply(init_done_msg, -1); |
250 return; | 235 return; |
251 } | 236 } |
252 #endif | 237 #endif |
253 | 238 |
254 #if defined(OS_WIN) | 239 #if defined(OS_WIN) |
255 if (base::win::GetVersion() < base::win::VERSION_WIN7) { | 240 if (base::win::GetVersion() < base::win::VERSION_WIN7) { |
256 NOTIMPLEMENTED() << "HW video decode acceleration not available."; | 241 NOTIMPLEMENTED() << "HW video decode acceleration not available."; |
257 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 242 SendCreateDecoderReply(init_done_msg, -1); |
258 return; | 243 return; |
259 } | 244 } |
260 DVLOG(0) << "Initializing DXVA HW decoder for windows."; | 245 DVLOG(0) << "Initializing DXVA HW decoder for windows."; |
261 video_decode_accelerator_.reset( | 246 video_decode_accelerator_.reset( |
262 new DXVAVideoDecodeAccelerator(make_context_current_)); | 247 new DXVAVideoDecodeAccelerator(make_context_current_)); |
263 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11) | 248 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11) |
264 scoped_ptr<V4L2Device> device = V4L2Device::Create(); | 249 scoped_ptr<V4L2Device> device = V4L2Device::Create(); |
265 if (!device.get()) { | 250 if (!device.get()) { |
266 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 251 SendCreateDecoderReply(init_done_msg, -1); |
267 return; | 252 return; |
268 } | 253 } |
269 video_decode_accelerator_.reset( | 254 video_decode_accelerator_.reset( |
270 new V4L2VideoDecodeAccelerator(gfx::GLSurfaceEGL::GetHardwareDisplay(), | 255 new V4L2VideoDecodeAccelerator(gfx::GLSurfaceEGL::GetHardwareDisplay(), |
271 weak_factory_for_io_.GetWeakPtr(), | 256 weak_factory_for_io_.GetWeakPtr(), |
272 make_context_current_, | 257 make_context_current_, |
273 device.Pass(), | 258 device.Pass(), |
274 io_message_loop_)); | 259 io_message_loop_)); |
275 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11) | 260 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11) |
276 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) { | 261 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) { |
277 VLOG(1) << "HW video decode acceleration not available without " | 262 VLOG(1) << "HW video decode acceleration not available without " |
278 "DesktopGL (GLX)."; | 263 "DesktopGL (GLX)."; |
279 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 264 SendCreateDecoderReply(init_done_msg, -1); |
280 return; | 265 return; |
281 } | 266 } |
282 gfx::GLContextGLX* glx_context = | 267 gfx::GLContextGLX* glx_context = |
283 static_cast<gfx::GLContextGLX*>(stub_->decoder()->GetGLContext()); | 268 static_cast<gfx::GLContextGLX*>(stub_->decoder()->GetGLContext()); |
284 video_decode_accelerator_.reset(new VaapiVideoDecodeAccelerator( | 269 video_decode_accelerator_.reset(new VaapiVideoDecodeAccelerator( |
285 glx_context->display(), make_context_current_)); | 270 glx_context->display(), make_context_current_)); |
286 #elif defined(OS_ANDROID) | 271 #elif defined(OS_ANDROID) |
287 video_decode_accelerator_.reset(new AndroidVideoDecodeAccelerator( | 272 video_decode_accelerator_.reset(new AndroidVideoDecodeAccelerator( |
288 stub_->decoder()->AsWeakPtr(), | 273 stub_->decoder()->AsWeakPtr(), |
289 make_context_current_)); | 274 make_context_current_)); |
290 #else | 275 #else |
291 NOTIMPLEMENTED() << "HW video decode acceleration not available."; | 276 NOTIMPLEMENTED() << "HW video decode acceleration not available."; |
292 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 277 SendCreateDecoderReply(init_done_msg, -1); |
293 return; | 278 return; |
294 #endif | 279 #endif |
295 | 280 |
296 if (video_decode_accelerator_->CanDecodeOnIOThread()) { | 281 if (video_decode_accelerator_->CanDecodeOnIOThread()) { |
297 filter_ = new MessageFilter(this, host_route_id_); | 282 filter_ = new MessageFilter(this, host_route_id_); |
298 stub_->channel()->AddFilter(filter_.get()); | 283 stub_->channel()->AddFilter(filter_.get()); |
299 } | 284 } |
300 | 285 |
301 if (!video_decode_accelerator_->Initialize(profile, this)) | 286 if (!video_decode_accelerator_->Initialize(profile, this)) { |
302 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 287 SendCreateDecoderReply(init_done_msg, -1); |
288 return; | |
289 } | |
290 | |
291 SendCreateDecoderReply(init_done_msg, host_route_id_); | |
303 } | 292 } |
304 | 293 |
305 // Runs on IO thread if video_decode_accelerator_->CanDecodeOnIOThread() is | 294 // Runs on IO thread if video_decode_accelerator_->CanDecodeOnIOThread() is |
306 // true, otherwise on the main thread. | 295 // true, otherwise on the main thread. |
307 void GpuVideoDecodeAccelerator::OnDecode( | 296 void GpuVideoDecodeAccelerator::OnDecode( |
308 base::SharedMemoryHandle handle, int32 id, uint32 size) { | 297 base::SharedMemoryHandle handle, int32 id, uint32 size) { |
309 DCHECK(video_decode_accelerator_.get()); | 298 DCHECK(video_decode_accelerator_.get()); |
310 if (id < 0) { | 299 if (id < 0) { |
311 DLOG(ERROR) << "BitstreamBuffer id " << id << " out of range"; | 300 DLOG(ERROR) << "BitstreamBuffer id " << id << " out of range"; |
312 if (child_message_loop_->BelongsToCurrentThread()) { | 301 if (child_message_loop_->BelongsToCurrentThread()) { |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
429 void GpuVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer( | 418 void GpuVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer( |
430 int32 bitstream_buffer_id) { | 419 int32 bitstream_buffer_id) { |
431 if (!Send(new AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed( | 420 if (!Send(new AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed( |
432 host_route_id_, bitstream_buffer_id))) { | 421 host_route_id_, bitstream_buffer_id))) { |
433 DLOG(ERROR) | 422 DLOG(ERROR) |
434 << "Send(AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed) " | 423 << "Send(AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed) " |
435 << "failed"; | 424 << "failed"; |
436 } | 425 } |
437 } | 426 } |
438 | 427 |
439 void GpuVideoDecodeAccelerator::NotifyInitializeDone() { | |
440 GpuCommandBufferMsg_CreateVideoDecoder::WriteReplyParams( | |
441 init_done_msg_, host_route_id_); | |
442 if (!Send(init_done_msg_)) | |
443 DLOG(ERROR) << "Send(init_done_msg_) failed"; | |
444 init_done_msg_ = NULL; | |
445 } | |
446 | |
447 void GpuVideoDecodeAccelerator::NotifyFlushDone() { | 428 void GpuVideoDecodeAccelerator::NotifyFlushDone() { |
448 if (!Send(new AcceleratedVideoDecoderHostMsg_FlushDone(host_route_id_))) | 429 if (!Send(new AcceleratedVideoDecoderHostMsg_FlushDone(host_route_id_))) |
449 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_FlushDone) failed"; | 430 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_FlushDone) failed"; |
450 } | 431 } |
451 | 432 |
452 void GpuVideoDecodeAccelerator::NotifyResetDone() { | 433 void GpuVideoDecodeAccelerator::NotifyResetDone() { |
453 if (!Send(new AcceleratedVideoDecoderHostMsg_ResetDone(host_route_id_))) | 434 if (!Send(new AcceleratedVideoDecoderHostMsg_ResetDone(host_route_id_))) |
454 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ResetDone) failed"; | 435 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ResetDone) failed"; |
455 } | 436 } |
456 | 437 |
(...skipping 13 matching lines...) Expand all Loading... | |
470 | 451 |
471 stub_->channel()->RemoveRoute(host_route_id_); | 452 stub_->channel()->RemoveRoute(host_route_id_); |
472 stub_->RemoveDestructionObserver(this); | 453 stub_->RemoveDestructionObserver(this); |
473 | 454 |
474 if (video_decode_accelerator_) | 455 if (video_decode_accelerator_) |
475 video_decode_accelerator_.release()->Destroy(); | 456 video_decode_accelerator_.release()->Destroy(); |
476 | 457 |
477 delete this; | 458 delete this; |
478 } | 459 } |
479 | 460 |
480 bool GpuVideoDecodeAccelerator::Send(IPC::Message* message) { | |
481 if (filter_.get() && io_message_loop_->BelongsToCurrentThread()) | |
482 return filter_->SendOnIOThread(message); | |
483 DCHECK(child_message_loop_->BelongsToCurrentThread()); | |
484 return stub_->channel()->Send(message); | |
485 } | |
486 | |
487 void GpuVideoDecodeAccelerator::SetTextureCleared( | 461 void GpuVideoDecodeAccelerator::SetTextureCleared( |
488 const media::Picture& picture) { | 462 const media::Picture& picture) { |
489 DCHECK(child_message_loop_->BelongsToCurrentThread()); | 463 DCHECK(child_message_loop_->BelongsToCurrentThread()); |
490 DebugAutoLock auto_lock(debug_uncleared_textures_lock_); | 464 DebugAutoLock auto_lock(debug_uncleared_textures_lock_); |
491 std::map<int32, scoped_refptr<gpu::gles2::TextureRef> >::iterator it; | 465 std::map<int32, scoped_refptr<gpu::gles2::TextureRef> >::iterator it; |
492 it = uncleared_textures_.find(picture.picture_buffer_id()); | 466 it = uncleared_textures_.find(picture.picture_buffer_id()); |
493 if (it == uncleared_textures_.end()) | 467 if (it == uncleared_textures_.end()) |
494 return; // the texture has been cleared | 468 return; // the texture has been cleared |
495 | 469 |
496 scoped_refptr<gpu::gles2::TextureRef> texture_ref = it->second; | 470 scoped_refptr<gpu::gles2::TextureRef> texture_ref = it->second; |
497 GLenum target = texture_ref->texture()->target(); | 471 GLenum target = texture_ref->texture()->target(); |
498 gpu::gles2::TextureManager* texture_manager = | 472 gpu::gles2::TextureManager* texture_manager = |
499 stub_->decoder()->GetContextGroup()->texture_manager(); | 473 stub_->decoder()->GetContextGroup()->texture_manager(); |
500 DCHECK(!texture_ref->texture()->IsLevelCleared(target, 0)); | 474 DCHECK(!texture_ref->texture()->IsLevelCleared(target, 0)); |
501 texture_manager->SetLevelCleared(texture_ref, target, 0, true); | 475 texture_manager->SetLevelCleared(texture_ref, target, 0, true); |
502 uncleared_textures_.erase(it); | 476 uncleared_textures_.erase(it); |
503 } | 477 } |
504 | 478 |
479 bool GpuVideoDecodeAccelerator::Send(IPC::Message* message) { | |
480 if (filter_.get() && io_message_loop_->BelongsToCurrentThread()) | |
481 return filter_->SendOnIOThread(message); | |
482 DCHECK(child_message_loop_->BelongsToCurrentThread()); | |
483 return stub_->channel()->Send(message); | |
484 } | |
485 | |
486 void GpuVideoDecodeAccelerator::SendCreateDecoderReply(IPC::Message* message, | |
487 int32 route_id) { | |
488 GpuCommandBufferMsg_CreateVideoDecoder::WriteReplyParams(message, route_id); | |
489 Send(message); | |
490 } | |
491 | |
505 } // namespace content | 492 } // namespace content |
OLD | NEW |