| 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); | 131 stub_->channel()->AddRoute(host_route_id_, this); |
| 133 child_message_loop_ = base::MessageLoopProxy::current(); | 132 child_message_loop_ = base::MessageLoopProxy::current(); |
| 134 make_context_current_ = | 133 make_context_current_ = |
| 135 base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr()); | 134 base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr()); |
| 136 } | 135 } |
| 137 | 136 |
| 138 GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() { | 137 GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() { |
| 139 // This class can only be self-deleted from OnWillDestroyStub(), which means | 138 // This class can only be self-deleted from OnWillDestroyStub(), which means |
| 140 // the VDA has already been destroyed in there. | 139 // the VDA has already been destroyed in there. |
| 141 CHECK(!video_decode_accelerator_.get()); | 140 DCHECK(!video_decode_accelerator_); |
| 142 } | 141 } |
| 143 | 142 |
| 144 bool GpuVideoDecodeAccelerator::OnMessageReceived(const IPC::Message& msg) { | 143 bool GpuVideoDecodeAccelerator::OnMessageReceived(const IPC::Message& msg) { |
| 145 if (!video_decode_accelerator_) | 144 if (!video_decode_accelerator_) |
| 146 return false; | 145 return false; |
| 147 | 146 |
| 148 bool handled = true; | 147 bool handled = true; |
| 149 IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAccelerator, msg) | 148 IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAccelerator, msg) |
| 150 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Decode, OnDecode) | 149 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Decode, OnDecode) |
| 151 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_AssignPictureBuffers, | 150 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_AssignPictureBuffers, |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 if (!Send(new AcceleratedVideoDecoderHostMsg_PictureReady( | 209 if (!Send(new AcceleratedVideoDecoderHostMsg_PictureReady( |
| 211 host_route_id_, | 210 host_route_id_, |
| 212 picture.picture_buffer_id(), | 211 picture.picture_buffer_id(), |
| 213 picture.bitstream_buffer_id()))) { | 212 picture.bitstream_buffer_id()))) { |
| 214 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_PictureReady) failed"; | 213 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_PictureReady) failed"; |
| 215 } | 214 } |
| 216 } | 215 } |
| 217 | 216 |
| 218 void GpuVideoDecodeAccelerator::NotifyError( | 217 void GpuVideoDecodeAccelerator::NotifyError( |
| 219 media::VideoDecodeAccelerator::Error error) { | 218 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( | 219 if (!Send(new AcceleratedVideoDecoderHostMsg_ErrorNotification( |
| 231 host_route_id_, error))) { | 220 host_route_id_, error))) { |
| 232 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ErrorNotification) " | 221 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ErrorNotification) " |
| 233 << "failed"; | 222 << "failed"; |
| 234 } | 223 } |
| 235 } | 224 } |
| 236 | 225 |
| 237 void GpuVideoDecodeAccelerator::Initialize( | 226 void GpuVideoDecodeAccelerator::Initialize( |
| 238 const media::VideoCodecProfile profile, | 227 const media::VideoCodecProfile profile, |
| 239 IPC::Message* init_done_msg) { | 228 IPC::Message* init_done_msg) { |
| 240 DCHECK(!video_decode_accelerator_.get()); | 229 DCHECK(!video_decode_accelerator_.get()); |
| 241 DCHECK(!init_done_msg_); | |
| 242 DCHECK(init_done_msg); | |
| 243 init_done_msg_ = init_done_msg; | |
| 244 | 230 |
| 245 #if !defined(OS_WIN) | 231 #if !defined(OS_WIN) |
| 246 // Ensure we will be able to get a GL context at all before initializing | 232 // Ensure we will be able to get a GL context at all before initializing |
| 247 // non-Windows VDAs. | 233 // non-Windows VDAs. |
| 248 if (!make_context_current_.Run()) { | 234 if (!make_context_current_.Run()) { |
| 249 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 235 SendCreateDecoderReply(init_done_msg, MSG_ROUTING_NONE); |
| 250 return; | 236 return; |
| 251 } | 237 } |
| 252 #endif | 238 #endif |
| 253 | 239 |
| 254 #if defined(OS_WIN) | 240 #if defined(OS_WIN) |
| 255 if (base::win::GetVersion() < base::win::VERSION_WIN7) { | 241 if (base::win::GetVersion() < base::win::VERSION_WIN7) { |
| 256 NOTIMPLEMENTED() << "HW video decode acceleration not available."; | 242 NOTIMPLEMENTED() << "HW video decode acceleration not available."; |
| 257 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 243 SendCreateDecoderReply(init_done_msg, MSG_ROUTING_NONE); |
| 258 return; | 244 return; |
| 259 } | 245 } |
| 260 DVLOG(0) << "Initializing DXVA HW decoder for windows."; | 246 DVLOG(0) << "Initializing DXVA HW decoder for windows."; |
| 261 video_decode_accelerator_.reset( | 247 video_decode_accelerator_.reset( |
| 262 new DXVAVideoDecodeAccelerator(make_context_current_)); | 248 new DXVAVideoDecodeAccelerator(make_context_current_)); |
| 263 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11) | 249 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11) |
| 264 scoped_ptr<V4L2Device> device = | 250 scoped_ptr<V4L2Device> device = |
| 265 V4L2Device::Create(stub_->decoder()->GetGLContext()->GetHandle()); | 251 V4L2Device::Create(stub_->decoder()->GetGLContext()->GetHandle()); |
| 266 if (!device.get()) { | 252 if (!device.get()) { |
| 267 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 253 SendCreateDecoderReply(init_done_msg, MSG_ROUTING_NONE); |
| 268 return; | 254 return; |
| 269 } | 255 } |
| 270 video_decode_accelerator_.reset( | 256 video_decode_accelerator_.reset( |
| 271 new V4L2VideoDecodeAccelerator(gfx::GLSurfaceEGL::GetHardwareDisplay(), | 257 new V4L2VideoDecodeAccelerator(gfx::GLSurfaceEGL::GetHardwareDisplay(), |
| 272 weak_factory_for_io_.GetWeakPtr(), | 258 weak_factory_for_io_.GetWeakPtr(), |
| 273 make_context_current_, | 259 make_context_current_, |
| 274 device.Pass(), | 260 device.Pass(), |
| 275 io_message_loop_)); | 261 io_message_loop_)); |
| 276 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11) | 262 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11) |
| 277 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) { | 263 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) { |
| 278 VLOG(1) << "HW video decode acceleration not available without " | 264 VLOG(1) << "HW video decode acceleration not available without " |
| 279 "DesktopGL (GLX)."; | 265 "DesktopGL (GLX)."; |
| 280 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 266 SendCreateDecoderReply(init_done_msg, MSG_ROUTING_NONE); |
| 281 return; | 267 return; |
| 282 } | 268 } |
| 283 gfx::GLContextGLX* glx_context = | 269 gfx::GLContextGLX* glx_context = |
| 284 static_cast<gfx::GLContextGLX*>(stub_->decoder()->GetGLContext()); | 270 static_cast<gfx::GLContextGLX*>(stub_->decoder()->GetGLContext()); |
| 285 video_decode_accelerator_.reset(new VaapiVideoDecodeAccelerator( | 271 video_decode_accelerator_.reset(new VaapiVideoDecodeAccelerator( |
| 286 glx_context->display(), make_context_current_)); | 272 glx_context->display(), make_context_current_)); |
| 287 #elif defined(OS_ANDROID) | 273 #elif defined(OS_ANDROID) |
| 288 video_decode_accelerator_.reset(new AndroidVideoDecodeAccelerator( | 274 video_decode_accelerator_.reset(new AndroidVideoDecodeAccelerator( |
| 289 stub_->decoder()->AsWeakPtr(), | 275 stub_->decoder()->AsWeakPtr(), |
| 290 make_context_current_)); | 276 make_context_current_)); |
| 291 #else | 277 #else |
| 292 NOTIMPLEMENTED() << "HW video decode acceleration not available."; | 278 NOTIMPLEMENTED() << "HW video decode acceleration not available."; |
| 293 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 279 SendCreateDecoderReply(init_done_msg, MSG_ROUTING_NONE); |
| 294 return; | 280 return; |
| 295 #endif | 281 #endif |
| 296 | 282 |
| 297 if (video_decode_accelerator_->CanDecodeOnIOThread()) { | 283 if (video_decode_accelerator_->CanDecodeOnIOThread()) { |
| 298 filter_ = new MessageFilter(this, host_route_id_); | 284 filter_ = new MessageFilter(this, host_route_id_); |
| 299 stub_->channel()->AddFilter(filter_.get()); | 285 stub_->channel()->AddFilter(filter_.get()); |
| 300 } | 286 } |
| 301 | 287 |
| 302 if (!video_decode_accelerator_->Initialize(profile, this)) | 288 if (!video_decode_accelerator_->Initialize(profile, this)) { |
| 303 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 289 SendCreateDecoderReply(init_done_msg, MSG_ROUTING_NONE); |
| 290 return; |
| 291 } |
| 292 |
| 293 SendCreateDecoderReply(init_done_msg, host_route_id_); |
| 304 } | 294 } |
| 305 | 295 |
| 306 // Runs on IO thread if video_decode_accelerator_->CanDecodeOnIOThread() is | 296 // Runs on IO thread if video_decode_accelerator_->CanDecodeOnIOThread() is |
| 307 // true, otherwise on the main thread. | 297 // true, otherwise on the main thread. |
| 308 void GpuVideoDecodeAccelerator::OnDecode( | 298 void GpuVideoDecodeAccelerator::OnDecode( |
| 309 base::SharedMemoryHandle handle, int32 id, uint32 size) { | 299 base::SharedMemoryHandle handle, int32 id, uint32 size) { |
| 310 DCHECK(video_decode_accelerator_.get()); | 300 DCHECK(video_decode_accelerator_.get()); |
| 311 if (id < 0) { | 301 if (id < 0) { |
| 312 DLOG(ERROR) << "BitstreamBuffer id " << id << " out of range"; | 302 DLOG(ERROR) << "BitstreamBuffer id " << id << " out of range"; |
| 313 if (child_message_loop_->BelongsToCurrentThread()) { | 303 if (child_message_loop_->BelongsToCurrentThread()) { |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 430 void GpuVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer( | 420 void GpuVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer( |
| 431 int32 bitstream_buffer_id) { | 421 int32 bitstream_buffer_id) { |
| 432 if (!Send(new AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed( | 422 if (!Send(new AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed( |
| 433 host_route_id_, bitstream_buffer_id))) { | 423 host_route_id_, bitstream_buffer_id))) { |
| 434 DLOG(ERROR) | 424 DLOG(ERROR) |
| 435 << "Send(AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed) " | 425 << "Send(AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed) " |
| 436 << "failed"; | 426 << "failed"; |
| 437 } | 427 } |
| 438 } | 428 } |
| 439 | 429 |
| 440 void GpuVideoDecodeAccelerator::NotifyInitializeDone() { | |
| 441 GpuCommandBufferMsg_CreateVideoDecoder::WriteReplyParams( | |
| 442 init_done_msg_, host_route_id_); | |
| 443 if (!Send(init_done_msg_)) | |
| 444 DLOG(ERROR) << "Send(init_done_msg_) failed"; | |
| 445 init_done_msg_ = NULL; | |
| 446 } | |
| 447 | |
| 448 void GpuVideoDecodeAccelerator::NotifyFlushDone() { | 430 void GpuVideoDecodeAccelerator::NotifyFlushDone() { |
| 449 if (!Send(new AcceleratedVideoDecoderHostMsg_FlushDone(host_route_id_))) | 431 if (!Send(new AcceleratedVideoDecoderHostMsg_FlushDone(host_route_id_))) |
| 450 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_FlushDone) failed"; | 432 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_FlushDone) failed"; |
| 451 } | 433 } |
| 452 | 434 |
| 453 void GpuVideoDecodeAccelerator::NotifyResetDone() { | 435 void GpuVideoDecodeAccelerator::NotifyResetDone() { |
| 454 if (!Send(new AcceleratedVideoDecoderHostMsg_ResetDone(host_route_id_))) | 436 if (!Send(new AcceleratedVideoDecoderHostMsg_ResetDone(host_route_id_))) |
| 455 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ResetDone) failed"; | 437 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ResetDone) failed"; |
| 456 } | 438 } |
| 457 | 439 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 471 | 453 |
| 472 stub_->channel()->RemoveRoute(host_route_id_); | 454 stub_->channel()->RemoveRoute(host_route_id_); |
| 473 stub_->RemoveDestructionObserver(this); | 455 stub_->RemoveDestructionObserver(this); |
| 474 | 456 |
| 475 if (video_decode_accelerator_) | 457 if (video_decode_accelerator_) |
| 476 video_decode_accelerator_.release()->Destroy(); | 458 video_decode_accelerator_.release()->Destroy(); |
| 477 | 459 |
| 478 delete this; | 460 delete this; |
| 479 } | 461 } |
| 480 | 462 |
| 481 bool GpuVideoDecodeAccelerator::Send(IPC::Message* message) { | |
| 482 if (filter_.get() && io_message_loop_->BelongsToCurrentThread()) | |
| 483 return filter_->SendOnIOThread(message); | |
| 484 DCHECK(child_message_loop_->BelongsToCurrentThread()); | |
| 485 return stub_->channel()->Send(message); | |
| 486 } | |
| 487 | |
| 488 void GpuVideoDecodeAccelerator::SetTextureCleared( | 463 void GpuVideoDecodeAccelerator::SetTextureCleared( |
| 489 const media::Picture& picture) { | 464 const media::Picture& picture) { |
| 490 DCHECK(child_message_loop_->BelongsToCurrentThread()); | 465 DCHECK(child_message_loop_->BelongsToCurrentThread()); |
| 491 DebugAutoLock auto_lock(debug_uncleared_textures_lock_); | 466 DebugAutoLock auto_lock(debug_uncleared_textures_lock_); |
| 492 std::map<int32, scoped_refptr<gpu::gles2::TextureRef> >::iterator it; | 467 std::map<int32, scoped_refptr<gpu::gles2::TextureRef> >::iterator it; |
| 493 it = uncleared_textures_.find(picture.picture_buffer_id()); | 468 it = uncleared_textures_.find(picture.picture_buffer_id()); |
| 494 if (it == uncleared_textures_.end()) | 469 if (it == uncleared_textures_.end()) |
| 495 return; // the texture has been cleared | 470 return; // the texture has been cleared |
| 496 | 471 |
| 497 scoped_refptr<gpu::gles2::TextureRef> texture_ref = it->second; | 472 scoped_refptr<gpu::gles2::TextureRef> texture_ref = it->second; |
| 498 GLenum target = texture_ref->texture()->target(); | 473 GLenum target = texture_ref->texture()->target(); |
| 499 gpu::gles2::TextureManager* texture_manager = | 474 gpu::gles2::TextureManager* texture_manager = |
| 500 stub_->decoder()->GetContextGroup()->texture_manager(); | 475 stub_->decoder()->GetContextGroup()->texture_manager(); |
| 501 DCHECK(!texture_ref->texture()->IsLevelCleared(target, 0)); | 476 DCHECK(!texture_ref->texture()->IsLevelCleared(target, 0)); |
| 502 texture_manager->SetLevelCleared(texture_ref, target, 0, true); | 477 texture_manager->SetLevelCleared(texture_ref, target, 0, true); |
| 503 uncleared_textures_.erase(it); | 478 uncleared_textures_.erase(it); |
| 504 } | 479 } |
| 505 | 480 |
| 481 bool GpuVideoDecodeAccelerator::Send(IPC::Message* message) { |
| 482 if (filter_.get() && io_message_loop_->BelongsToCurrentThread()) |
| 483 return filter_->SendOnIOThread(message); |
| 484 DCHECK(child_message_loop_->BelongsToCurrentThread()); |
| 485 return stub_->channel()->Send(message); |
| 486 } |
| 487 |
| 488 void GpuVideoDecodeAccelerator::SendCreateDecoderReply(IPC::Message* message, |
| 489 int32 route_id) { |
| 490 GpuCommandBufferMsg_CreateVideoDecoder::WriteReplyParams(message, route_id); |
| 491 Send(message); |
| 492 } |
| 493 |
| 506 } // namespace content | 494 } // namespace content |
| OLD | NEW |