| 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/location.h" | 10 #include "base/location.h" |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 127 IPC::Sender* sender_; | 127 IPC::Sender* sender_; |
| 128 }; | 128 }; |
| 129 | 129 |
| 130 GpuVideoDecodeAccelerator::GpuVideoDecodeAccelerator( | 130 GpuVideoDecodeAccelerator::GpuVideoDecodeAccelerator( |
| 131 int32_t host_route_id, | 131 int32_t host_route_id, |
| 132 GpuCommandBufferStub* stub, | 132 GpuCommandBufferStub* stub, |
| 133 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) | 133 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) |
| 134 : host_route_id_(host_route_id), | 134 : host_route_id_(host_route_id), |
| 135 stub_(stub), | 135 stub_(stub), |
| 136 texture_target_(0), | 136 texture_target_(0), |
| 137 textures_per_buffer_(0), |
| 137 filter_removed_(true, false), | 138 filter_removed_(true, false), |
| 138 child_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 139 child_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 139 io_task_runner_(io_task_runner), | 140 io_task_runner_(io_task_runner), |
| 140 weak_factory_for_io_(this) { | 141 weak_factory_for_io_(this) { |
| 141 DCHECK(stub_); | 142 DCHECK(stub_); |
| 142 stub_->AddDestructionObserver(this); | 143 stub_->AddDestructionObserver(this); |
| 143 make_context_current_ = | 144 make_context_current_ = |
| 144 base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr()); | 145 base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr()); |
| 145 } | 146 } |
| 146 | 147 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 } | 211 } |
| 211 | 212 |
| 212 void GpuVideoDecodeAccelerator::NotifyCdmAttached(bool success) { | 213 void GpuVideoDecodeAccelerator::NotifyCdmAttached(bool success) { |
| 213 if (!Send(new AcceleratedVideoDecoderHostMsg_CdmAttached(host_route_id_, | 214 if (!Send(new AcceleratedVideoDecoderHostMsg_CdmAttached(host_route_id_, |
| 214 success))) | 215 success))) |
| 215 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_CdmAttached) failed"; | 216 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_CdmAttached) failed"; |
| 216 } | 217 } |
| 217 | 218 |
| 218 void GpuVideoDecodeAccelerator::ProvidePictureBuffers( | 219 void GpuVideoDecodeAccelerator::ProvidePictureBuffers( |
| 219 uint32_t requested_num_of_buffers, | 220 uint32_t requested_num_of_buffers, |
| 221 uint32_t textures_per_buffer, |
| 220 const gfx::Size& dimensions, | 222 const gfx::Size& dimensions, |
| 221 uint32_t texture_target) { | 223 uint32_t texture_target) { |
| 222 if (dimensions.width() > media::limits::kMaxDimension || | 224 if (dimensions.width() > media::limits::kMaxDimension || |
| 223 dimensions.height() > media::limits::kMaxDimension || | 225 dimensions.height() > media::limits::kMaxDimension || |
| 224 dimensions.GetArea() > media::limits::kMaxCanvas) { | 226 dimensions.GetArea() > media::limits::kMaxCanvas) { |
| 225 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 227 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); |
| 226 return; | 228 return; |
| 227 } | 229 } |
| 228 if (!Send(new AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers( | 230 if (!Send(new AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers( |
| 229 host_route_id_, | 231 host_route_id_, requested_num_of_buffers, textures_per_buffer, |
| 230 requested_num_of_buffers, | 232 dimensions, texture_target))) { |
| 231 dimensions, | |
| 232 texture_target))) { | |
| 233 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers) " | 233 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers) " |
| 234 << "failed"; | 234 << "failed"; |
| 235 } | 235 } |
| 236 texture_dimensions_ = dimensions; | 236 texture_dimensions_ = dimensions; |
| 237 textures_per_buffer_ = textures_per_buffer; |
| 237 texture_target_ = texture_target; | 238 texture_target_ = texture_target; |
| 238 } | 239 } |
| 239 | 240 |
| 240 void GpuVideoDecodeAccelerator::DismissPictureBuffer( | 241 void GpuVideoDecodeAccelerator::DismissPictureBuffer( |
| 241 int32_t picture_buffer_id) { | 242 int32_t picture_buffer_id) { |
| 242 // Notify client that picture buffer is now unused. | 243 // Notify client that picture buffer is now unused. |
| 243 if (!Send(new AcceleratedVideoDecoderHostMsg_DismissPictureBuffer( | 244 if (!Send(new AcceleratedVideoDecoderHostMsg_DismissPictureBuffer( |
| 244 host_route_id_, picture_buffer_id))) { | 245 host_route_id_, picture_buffer_id))) { |
| 245 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_DismissPictureBuffer) " | 246 DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_DismissPictureBuffer) " |
| 246 << "failed"; | 247 << "failed"; |
| (...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 519 // Runs on IO thread if video_decode_accelerator_->CanDecodeOnIOThread() is | 520 // Runs on IO thread if video_decode_accelerator_->CanDecodeOnIOThread() is |
| 520 // true, otherwise on the main thread. | 521 // true, otherwise on the main thread. |
| 521 void GpuVideoDecodeAccelerator::OnDecode( | 522 void GpuVideoDecodeAccelerator::OnDecode( |
| 522 const media::BitstreamBuffer& bitstream_buffer) { | 523 const media::BitstreamBuffer& bitstream_buffer) { |
| 523 DCHECK(video_decode_accelerator_); | 524 DCHECK(video_decode_accelerator_); |
| 524 video_decode_accelerator_->Decode(bitstream_buffer); | 525 video_decode_accelerator_->Decode(bitstream_buffer); |
| 525 } | 526 } |
| 526 | 527 |
| 527 void GpuVideoDecodeAccelerator::OnAssignPictureBuffers( | 528 void GpuVideoDecodeAccelerator::OnAssignPictureBuffers( |
| 528 const std::vector<int32_t>& buffer_ids, | 529 const std::vector<int32_t>& buffer_ids, |
| 529 const std::vector<uint32_t>& texture_ids) { | 530 const std::vector<media::PictureBuffer::TextureIds>& texture_ids) { |
| 530 if (buffer_ids.size() != texture_ids.size()) { | 531 if (buffer_ids.size() != texture_ids.size()) { |
| 531 NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT); | 532 NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT); |
| 532 return; | 533 return; |
| 533 } | 534 } |
| 534 | 535 |
| 535 gpu::gles2::GLES2Decoder* command_decoder = stub_->decoder(); | 536 gpu::gles2::GLES2Decoder* command_decoder = stub_->decoder(); |
| 536 gpu::gles2::TextureManager* texture_manager = | 537 gpu::gles2::TextureManager* texture_manager = |
| 537 command_decoder->GetContextGroup()->texture_manager(); | 538 command_decoder->GetContextGroup()->texture_manager(); |
| 538 | 539 |
| 539 std::vector<media::PictureBuffer> buffers; | 540 std::vector<media::PictureBuffer> buffers; |
| 540 std::vector<scoped_refptr<gpu::gles2::TextureRef> > textures; | 541 std::vector<scoped_refptr<gpu::gles2::TextureRef> > textures; |
| 541 for (uint32_t i = 0; i < buffer_ids.size(); ++i) { | 542 for (uint32_t i = 0; i < buffer_ids.size(); ++i) { |
| 542 if (buffer_ids[i] < 0) { | 543 if (buffer_ids[i] < 0) { |
| 543 DLOG(ERROR) << "Buffer id " << buffer_ids[i] << " out of range"; | 544 DLOG(ERROR) << "Buffer id " << buffer_ids[i] << " out of range"; |
| 544 NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT); | 545 NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT); |
| 545 return; | 546 return; |
| 546 } | 547 } |
| 547 gpu::gles2::TextureRef* texture_ref = texture_manager->GetTexture( | 548 media::PictureBuffer::TextureIds buffer_texture_ids = texture_ids[i]; |
| 548 texture_ids[i]); | 549 media::PictureBuffer::TextureIds service_ids; |
| 549 if (!texture_ref) { | 550 for (size_t j = 0; j < textures_per_buffer_; j++) { |
| 550 DLOG(ERROR) << "Failed to find texture id " << texture_ids[i]; | 551 gpu::gles2::TextureRef* texture_ref = |
| 551 NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT); | 552 texture_manager->GetTexture(buffer_texture_ids.ids[j]); |
| 552 return; | 553 if (!texture_ref) { |
| 553 } | 554 DLOG(ERROR) << "Failed to find texture id " |
| 554 gpu::gles2::Texture* info = texture_ref->texture(); | 555 << buffer_texture_ids.ids[j]; |
| 555 if (info->target() != texture_target_) { | |
| 556 DLOG(ERROR) << "Texture target mismatch for texture id " | |
| 557 << texture_ids[i]; | |
| 558 NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT); | |
| 559 return; | |
| 560 } | |
| 561 if (texture_target_ == GL_TEXTURE_EXTERNAL_OES || | |
| 562 texture_target_ == GL_TEXTURE_RECTANGLE_ARB) { | |
| 563 // These textures have their dimensions defined by the underlying storage. | |
| 564 // Use |texture_dimensions_| for this size. | |
| 565 texture_manager->SetLevelInfo( | |
| 566 texture_ref, texture_target_, 0, GL_RGBA, texture_dimensions_.width(), | |
| 567 texture_dimensions_.height(), 1, 0, GL_RGBA, 0, gfx::Rect()); | |
| 568 } else { | |
| 569 // For other targets, texture dimensions should already be defined. | |
| 570 GLsizei width = 0, height = 0; | |
| 571 info->GetLevelSize(texture_target_, 0, &width, &height, nullptr); | |
| 572 if (width != texture_dimensions_.width() || | |
| 573 height != texture_dimensions_.height()) { | |
| 574 DLOG(ERROR) << "Size mismatch for texture id " << texture_ids[i]; | |
| 575 NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT); | 556 NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT); |
| 576 return; | 557 return; |
| 577 } | 558 } |
| 559 gpu::gles2::Texture* info = texture_ref->texture(); |
| 560 if (info->target() != texture_target_) { |
| 561 DLOG(ERROR) << "Texture target mismatch for texture id " |
| 562 << buffer_texture_ids.ids[j]; |
| 563 NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT); |
| 564 return; |
| 565 } |
| 566 if (texture_target_ == GL_TEXTURE_EXTERNAL_OES || |
| 567 texture_target_ == GL_TEXTURE_RECTANGLE_ARB) { |
| 568 // These textures have their dimensions defined by the underlying |
| 569 // storage. |
| 570 // Use |texture_dimensions_| for this size. |
| 571 texture_manager->SetLevelInfo(texture_ref, texture_target_, 0, GL_RGBA, |
| 572 texture_dimensions_.width(), |
| 573 texture_dimensions_.height(), 1, 0, |
| 574 GL_RGBA, 0, gfx::Rect()); |
| 575 } else { |
| 576 // For other targets, texture dimensions should already be defined. |
| 577 GLsizei width = 0, height = 0; |
| 578 info->GetLevelSize(texture_target_, 0, &width, &height, nullptr); |
| 579 if (width != texture_dimensions_.width() || |
| 580 height != texture_dimensions_.height()) { |
| 581 DLOG(ERROR) << "Size mismatch for texture id " |
| 582 << buffer_texture_ids.ids[j]; |
| 583 NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT); |
| 584 return; |
| 585 } |
| 578 | 586 |
| 579 // TODO(dshwang): after moving to D3D11, remove this. crbug.com/438691 | 587 // TODO(dshwang): after moving to D3D11, remove this. crbug.com/438691 |
| 580 GLenum format = | 588 GLenum format = |
| 581 video_decode_accelerator_.get()->GetSurfaceInternalFormat(); | 589 video_decode_accelerator_.get()->GetSurfaceInternalFormat(); |
| 582 if (format != GL_RGBA) { | 590 if (format != GL_RGBA) { |
| 583 texture_manager->SetLevelInfo(texture_ref, texture_target_, 0, format, | 591 texture_manager->SetLevelInfo(texture_ref, texture_target_, 0, format, |
| 584 width, height, 1, 0, format, 0, | 592 width, height, 1, 0, format, 0, |
| 585 gfx::Rect()); | 593 gfx::Rect()); |
| 594 } |
| 586 } | 595 } |
| 596 service_ids.ids[j] = texture_ref->service_id(); |
| 597 textures.push_back(texture_ref); |
| 587 } | 598 } |
| 588 buffers.push_back(media::PictureBuffer(buffer_ids[i], texture_dimensions_, | 599 buffers.push_back(media::PictureBuffer(buffer_ids[i], texture_dimensions_, |
| 589 texture_ref->service_id(), | 600 service_ids, buffer_texture_ids)); |
| 590 texture_ids[i])); | |
| 591 textures.push_back(texture_ref); | |
| 592 } | 601 } |
| 593 video_decode_accelerator_->AssignPictureBuffers(buffers); | 602 video_decode_accelerator_->AssignPictureBuffers(buffers); |
| 594 DebugAutoLock auto_lock(debug_uncleared_textures_lock_); | 603 DebugAutoLock auto_lock(debug_uncleared_textures_lock_); |
| 595 for (uint32_t i = 0; i < buffer_ids.size(); ++i) | 604 for (uint32_t i = 0; i < buffer_ids.size(); ++i) |
| 596 uncleared_textures_[buffer_ids[i]] = textures[i]; | 605 uncleared_textures_[buffer_ids[i]] = textures[i]; |
| 597 } | 606 } |
| 598 | 607 |
| 599 void GpuVideoDecodeAccelerator::OnReusePictureBuffer( | 608 void GpuVideoDecodeAccelerator::OnReusePictureBuffer( |
| 600 int32_t picture_buffer_id) { | 609 int32_t picture_buffer_id) { |
| 601 DCHECK(video_decode_accelerator_); | 610 DCHECK(video_decode_accelerator_); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 635 scoped_refptr<gpu::gles2::TextureRef> texture_ref = it->second; | 644 scoped_refptr<gpu::gles2::TextureRef> texture_ref = it->second; |
| 636 GLenum target = texture_ref->texture()->target(); | 645 GLenum target = texture_ref->texture()->target(); |
| 637 gpu::gles2::TextureManager* texture_manager = | 646 gpu::gles2::TextureManager* texture_manager = |
| 638 stub_->decoder()->GetContextGroup()->texture_manager(); | 647 stub_->decoder()->GetContextGroup()->texture_manager(); |
| 639 DCHECK(!texture_ref->texture()->IsLevelCleared(target, 0)); | 648 DCHECK(!texture_ref->texture()->IsLevelCleared(target, 0)); |
| 640 texture_manager->SetLevelCleared(texture_ref.get(), target, 0, true); | 649 texture_manager->SetLevelCleared(texture_ref.get(), target, 0, true); |
| 641 uncleared_textures_.erase(it); | 650 uncleared_textures_.erase(it); |
| 642 } | 651 } |
| 643 | 652 |
| 644 } // namespace content | 653 } // namespace content |
| OLD | NEW |