| 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" |
| 11 #include "base/location.h" |
| 11 #include "base/logging.h" | 12 #include "base/logging.h" |
| 12 #include "base/memory/ref_counted.h" | 13 #include "base/memory/ref_counted.h" |
| 13 #include "base/message_loop/message_loop_proxy.h" | 14 #include "base/single_thread_task_runner.h" |
| 14 #include "base/stl_util.h" | 15 #include "base/stl_util.h" |
| 16 #include "base/thread_task_runner_handle.h" |
| 15 | 17 |
| 16 #include "content/common/gpu/gpu_channel.h" | 18 #include "content/common/gpu/gpu_channel.h" |
| 17 #include "content/common/gpu/gpu_messages.h" | 19 #include "content/common/gpu/gpu_messages.h" |
| 18 #include "content/common/gpu/media/gpu_video_accelerator_util.h" | 20 #include "content/common/gpu/media/gpu_video_accelerator_util.h" |
| 19 #include "content/public/common/content_switches.h" | 21 #include "content/public/common/content_switches.h" |
| 20 #include "gpu/command_buffer/common/command_buffer.h" | 22 #include "gpu/command_buffer/common/command_buffer.h" |
| 21 #include "ipc/ipc_message_macros.h" | 23 #include "ipc/ipc_message_macros.h" |
| 22 #include "ipc/ipc_message_utils.h" | 24 #include "ipc/ipc_message_utils.h" |
| 23 #include "ipc/message_filter.h" | 25 #include "ipc/message_filter.h" |
| 24 #include "media/base/limits.h" | 26 #include "media/base/limits.h" |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 private: | 122 private: |
| 121 GpuVideoDecodeAccelerator* const owner_; | 123 GpuVideoDecodeAccelerator* const owner_; |
| 122 const int32 host_route_id_; | 124 const int32 host_route_id_; |
| 123 // The sender to which this filter was added. | 125 // The sender to which this filter was added. |
| 124 IPC::Sender* sender_; | 126 IPC::Sender* sender_; |
| 125 }; | 127 }; |
| 126 | 128 |
| 127 GpuVideoDecodeAccelerator::GpuVideoDecodeAccelerator( | 129 GpuVideoDecodeAccelerator::GpuVideoDecodeAccelerator( |
| 128 int32 host_route_id, | 130 int32 host_route_id, |
| 129 GpuCommandBufferStub* stub, | 131 GpuCommandBufferStub* stub, |
| 130 const scoped_refptr<base::MessageLoopProxy>& io_message_loop) | 132 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) |
| 131 : host_route_id_(host_route_id), | 133 : host_route_id_(host_route_id), |
| 132 stub_(stub), | 134 stub_(stub), |
| 133 texture_target_(0), | 135 texture_target_(0), |
| 134 filter_removed_(true, false), | 136 filter_removed_(true, false), |
| 135 child_message_loop_(base::MessageLoopProxy::current()), | 137 child_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 136 io_message_loop_(io_message_loop), | 138 io_task_runner_(io_task_runner), |
| 137 weak_factory_for_io_(this) { | 139 weak_factory_for_io_(this) { |
| 138 DCHECK(stub_); | 140 DCHECK(stub_); |
| 139 stub_->AddDestructionObserver(this); | 141 stub_->AddDestructionObserver(this); |
| 140 make_context_current_ = | 142 make_context_current_ = |
| 141 base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr()); | 143 base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr()); |
| 142 } | 144 } |
| 143 | 145 |
| 144 GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() { | 146 GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() { |
| 145 // This class can only be self-deleted from OnWillDestroyStub(), which means | 147 // This class can only be self-deleted from OnWillDestroyStub(), which means |
| 146 // the VDA has already been destroyed in there. | 148 // the VDA has already been destroyed in there. |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 } | 200 } |
| 199 DebugAutoLock auto_lock(debug_uncleared_textures_lock_); | 201 DebugAutoLock auto_lock(debug_uncleared_textures_lock_); |
| 200 uncleared_textures_.erase(picture_buffer_id); | 202 uncleared_textures_.erase(picture_buffer_id); |
| 201 } | 203 } |
| 202 | 204 |
| 203 void GpuVideoDecodeAccelerator::PictureReady( | 205 void GpuVideoDecodeAccelerator::PictureReady( |
| 204 const media::Picture& picture) { | 206 const media::Picture& picture) { |
| 205 // VDA may call PictureReady on IO thread. SetTextureCleared should run on | 207 // VDA may call PictureReady on IO thread. SetTextureCleared should run on |
| 206 // the child thread. VDA is responsible to call PictureReady on the child | 208 // the child thread. VDA is responsible to call PictureReady on the child |
| 207 // thread when a picture buffer is delivered the first time. | 209 // thread when a picture buffer is delivered the first time. |
| 208 if (child_message_loop_->BelongsToCurrentThread()) { | 210 if (child_task_runner_->BelongsToCurrentThread()) { |
| 209 SetTextureCleared(picture); | 211 SetTextureCleared(picture); |
| 210 } else { | 212 } else { |
| 211 DCHECK(io_message_loop_->BelongsToCurrentThread()); | 213 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
| 212 DebugAutoLock auto_lock(debug_uncleared_textures_lock_); | 214 DebugAutoLock auto_lock(debug_uncleared_textures_lock_); |
| 213 DCHECK_EQ(0u, uncleared_textures_.count(picture.picture_buffer_id())); | 215 DCHECK_EQ(0u, uncleared_textures_.count(picture.picture_buffer_id())); |
| 214 } | 216 } |
| 215 | 217 |
| 216 if (!Send(new AcceleratedVideoDecoderHostMsg_PictureReady( | 218 if (!Send(new AcceleratedVideoDecoderHostMsg_PictureReady( |
| 217 host_route_id_, picture.picture_buffer_id(), | 219 host_route_id_, picture.picture_buffer_id(), |
| 218 picture.bitstream_buffer_id(), picture.visible_rect(), | 220 picture.bitstream_buffer_id(), picture.visible_rect(), |
| 219 picture.allow_overlay()))) { | 221 picture.allow_overlay()))) { |
| 220 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_PictureReady) failed"; | 222 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_PictureReady) failed"; |
| 221 } | 223 } |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 418 return GpuVideoAcceleratorUtil::ConvertMediaToGpuDecodeProfiles(profiles); | 420 return GpuVideoAcceleratorUtil::ConvertMediaToGpuDecodeProfiles(profiles); |
| 419 } | 421 } |
| 420 | 422 |
| 421 // Runs on IO thread if video_decode_accelerator_->CanDecodeOnIOThread() is | 423 // Runs on IO thread if video_decode_accelerator_->CanDecodeOnIOThread() is |
| 422 // true, otherwise on the main thread. | 424 // true, otherwise on the main thread. |
| 423 void GpuVideoDecodeAccelerator::OnDecode( | 425 void GpuVideoDecodeAccelerator::OnDecode( |
| 424 base::SharedMemoryHandle handle, int32 id, uint32 size) { | 426 base::SharedMemoryHandle handle, int32 id, uint32 size) { |
| 425 DCHECK(video_decode_accelerator_.get()); | 427 DCHECK(video_decode_accelerator_.get()); |
| 426 if (id < 0) { | 428 if (id < 0) { |
| 427 DLOG(ERROR) << "BitstreamBuffer id " << id << " out of range"; | 429 DLOG(ERROR) << "BitstreamBuffer id " << id << " out of range"; |
| 428 if (child_message_loop_->BelongsToCurrentThread()) { | 430 if (child_task_runner_->BelongsToCurrentThread()) { |
| 429 NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT); | 431 NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT); |
| 430 } else { | 432 } else { |
| 431 child_message_loop_->PostTask( | 433 child_task_runner_->PostTask( |
| 432 FROM_HERE, | 434 FROM_HERE, |
| 433 base::Bind(&GpuVideoDecodeAccelerator::NotifyError, | 435 base::Bind(&GpuVideoDecodeAccelerator::NotifyError, |
| 434 base::Unretained(this), | 436 base::Unretained(this), |
| 435 media::VideoDecodeAccelerator::INVALID_ARGUMENT)); | 437 media::VideoDecodeAccelerator::INVALID_ARGUMENT)); |
| 436 } | 438 } |
| 437 return; | 439 return; |
| 438 } | 440 } |
| 439 video_decode_accelerator_->Decode(media::BitstreamBuffer(id, handle, size)); | 441 video_decode_accelerator_->Decode(media::BitstreamBuffer(id, handle, size)); |
| 440 } | 442 } |
| 441 | 443 |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 581 | 583 |
| 582 stub_->channel()->RemoveRoute(host_route_id_); | 584 stub_->channel()->RemoveRoute(host_route_id_); |
| 583 stub_->RemoveDestructionObserver(this); | 585 stub_->RemoveDestructionObserver(this); |
| 584 | 586 |
| 585 video_decode_accelerator_.reset(); | 587 video_decode_accelerator_.reset(); |
| 586 delete this; | 588 delete this; |
| 587 } | 589 } |
| 588 | 590 |
| 589 void GpuVideoDecodeAccelerator::SetTextureCleared( | 591 void GpuVideoDecodeAccelerator::SetTextureCleared( |
| 590 const media::Picture& picture) { | 592 const media::Picture& picture) { |
| 591 DCHECK(child_message_loop_->BelongsToCurrentThread()); | 593 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 592 DebugAutoLock auto_lock(debug_uncleared_textures_lock_); | 594 DebugAutoLock auto_lock(debug_uncleared_textures_lock_); |
| 593 std::map<int32, scoped_refptr<gpu::gles2::TextureRef> >::iterator it; | 595 std::map<int32, scoped_refptr<gpu::gles2::TextureRef> >::iterator it; |
| 594 it = uncleared_textures_.find(picture.picture_buffer_id()); | 596 it = uncleared_textures_.find(picture.picture_buffer_id()); |
| 595 if (it == uncleared_textures_.end()) | 597 if (it == uncleared_textures_.end()) |
| 596 return; // the texture has been cleared | 598 return; // the texture has been cleared |
| 597 | 599 |
| 598 scoped_refptr<gpu::gles2::TextureRef> texture_ref = it->second; | 600 scoped_refptr<gpu::gles2::TextureRef> texture_ref = it->second; |
| 599 GLenum target = texture_ref->texture()->target(); | 601 GLenum target = texture_ref->texture()->target(); |
| 600 gpu::gles2::TextureManager* texture_manager = | 602 gpu::gles2::TextureManager* texture_manager = |
| 601 stub_->decoder()->GetContextGroup()->texture_manager(); | 603 stub_->decoder()->GetContextGroup()->texture_manager(); |
| 602 DCHECK(!texture_ref->texture()->IsLevelCleared(target, 0)); | 604 DCHECK(!texture_ref->texture()->IsLevelCleared(target, 0)); |
| 603 texture_manager->SetLevelCleared(texture_ref.get(), target, 0, true); | 605 texture_manager->SetLevelCleared(texture_ref.get(), target, 0, true); |
| 604 uncleared_textures_.erase(it); | 606 uncleared_textures_.erase(it); |
| 605 } | 607 } |
| 606 | 608 |
| 607 bool GpuVideoDecodeAccelerator::Send(IPC::Message* message) { | 609 bool GpuVideoDecodeAccelerator::Send(IPC::Message* message) { |
| 608 if (filter_.get() && io_message_loop_->BelongsToCurrentThread()) | 610 if (filter_.get() && io_task_runner_->BelongsToCurrentThread()) |
| 609 return filter_->SendOnIOThread(message); | 611 return filter_->SendOnIOThread(message); |
| 610 DCHECK(child_message_loop_->BelongsToCurrentThread()); | 612 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 611 return stub_->channel()->Send(message); | 613 return stub_->channel()->Send(message); |
| 612 } | 614 } |
| 613 | 615 |
| 614 void GpuVideoDecodeAccelerator::SendCreateDecoderReply(IPC::Message* message, | 616 void GpuVideoDecodeAccelerator::SendCreateDecoderReply(IPC::Message* message, |
| 615 bool succeeded) { | 617 bool succeeded) { |
| 616 GpuCommandBufferMsg_CreateVideoDecoder::WriteReplyParams(message, succeeded); | 618 GpuCommandBufferMsg_CreateVideoDecoder::WriteReplyParams(message, succeeded); |
| 617 Send(message); | 619 Send(message); |
| 618 } | 620 } |
| 619 | 621 |
| 620 } // namespace content | 622 } // namespace content |
| OLD | NEW |