| 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" |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 260 DVLOG_IF(2, !success) << __FUNCTION__ << ": CDM not attached."; | 260 DVLOG_IF(2, !success) << __FUNCTION__ << ": CDM not attached."; |
| 261 DCHECK(!init_cb_.is_null()); | 261 DCHECK(!init_cb_.is_null()); |
| 262 | 262 |
| 263 base::ResetAndReturn(&init_cb_).Run(success); | 263 base::ResetAndReturn(&init_cb_).Run(success); |
| 264 } | 264 } |
| 265 | 265 |
| 266 void GpuVideoDecoder::DestroyPictureBuffers(PictureBufferMap* buffers) { | 266 void GpuVideoDecoder::DestroyPictureBuffers(PictureBufferMap* buffers) { |
| 267 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 267 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 268 for (PictureBufferMap::iterator it = buffers->begin(); it != buffers->end(); | 268 for (PictureBufferMap::iterator it = buffers->begin(); it != buffers->end(); |
| 269 ++it) { | 269 ++it) { |
| 270 factories_->DeleteTexture(it->second.texture_id()); | 270 for (uint32_t id : it->second.texture_ids()) |
| 271 factories_->DeleteTexture(id); |
| 271 } | 272 } |
| 272 | 273 |
| 273 buffers->clear(); | 274 buffers->clear(); |
| 274 } | 275 } |
| 275 | 276 |
| 276 void GpuVideoDecoder::DestroyVDA() { | 277 void GpuVideoDecoder::DestroyVDA() { |
| 277 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 278 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 278 | 279 |
| 279 vda_.reset(); | 280 vda_.reset(); |
| 280 | 281 |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 400 (!needs_all_picture_buffers_to_decode_ && available_pictures_ > 0) || | 401 (!needs_all_picture_buffers_to_decode_ && available_pictures_ > 0) || |
| 401 available_pictures_ == | 402 available_pictures_ == |
| 402 static_cast<int>(assigned_picture_buffers_.size()); | 403 static_cast<int>(assigned_picture_buffers_.size()); |
| 403 } | 404 } |
| 404 | 405 |
| 405 int GpuVideoDecoder::GetMaxDecodeRequests() const { | 406 int GpuVideoDecoder::GetMaxDecodeRequests() const { |
| 406 return kMaxInFlightDecodes; | 407 return kMaxInFlightDecodes; |
| 407 } | 408 } |
| 408 | 409 |
| 409 void GpuVideoDecoder::ProvidePictureBuffers(uint32_t count, | 410 void GpuVideoDecoder::ProvidePictureBuffers(uint32_t count, |
| 411 uint32_t textures_per_buffer, |
| 410 const gfx::Size& size, | 412 const gfx::Size& size, |
| 411 uint32_t texture_target) { | 413 uint32_t texture_target) { |
| 412 DVLOG(3) << "ProvidePictureBuffers(" << count << ", " | 414 DVLOG(3) << "ProvidePictureBuffers(" << count << ", " |
| 413 << size.width() << "x" << size.height() << ")"; | 415 << size.width() << "x" << size.height() << ")"; |
| 414 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 416 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 415 | 417 |
| 416 std::vector<uint32_t> texture_ids; | 418 std::vector<uint32_t> texture_ids; |
| 417 std::vector<gpu::Mailbox> texture_mailboxes; | 419 std::vector<gpu::Mailbox> texture_mailboxes; |
| 418 decoder_texture_target_ = texture_target; | 420 decoder_texture_target_ = texture_target; |
| 419 if (!factories_->CreateTextures(count, | 421 if (!factories_->CreateTextures(count * textures_per_buffer, size, |
| 420 size, | 422 &texture_ids, &texture_mailboxes, |
| 421 &texture_ids, | |
| 422 &texture_mailboxes, | |
| 423 decoder_texture_target_)) { | 423 decoder_texture_target_)) { |
| 424 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); | 424 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); |
| 425 return; | 425 return; |
| 426 } | 426 } |
| 427 DCHECK_EQ(count, texture_ids.size()); | 427 DCHECK_EQ(count * textures_per_buffer, texture_ids.size()); |
| 428 DCHECK_EQ(count, texture_mailboxes.size()); | 428 DCHECK_EQ(count * textures_per_buffer, texture_mailboxes.size()); |
| 429 | 429 |
| 430 if (!vda_) | 430 if (!vda_) |
| 431 return; | 431 return; |
| 432 | 432 |
| 433 std::vector<PictureBuffer> picture_buffers; | 433 std::vector<PictureBuffer> picture_buffers; |
| 434 for (size_t i = 0; i < texture_ids.size(); ++i) { | 434 size_t index = 0; |
| 435 picture_buffers.push_back(PictureBuffer( | 435 for (size_t i = 0; i < count; ++i) { |
| 436 next_picture_buffer_id_++, size, texture_ids[i], texture_mailboxes[i])); | 436 PictureBuffer::TextureIds ids; |
| 437 std::vector<gpu::Mailbox> mailboxes; |
| 438 for (size_t j = 0; j < textures_per_buffer; j++) { |
| 439 ids.push_back(texture_ids[index]); |
| 440 mailboxes.push_back(texture_mailboxes[index]); |
| 441 index++; |
| 442 } |
| 443 |
| 444 picture_buffers.push_back( |
| 445 PictureBuffer(next_picture_buffer_id_++, size, ids, mailboxes)); |
| 437 bool inserted = assigned_picture_buffers_.insert(std::make_pair( | 446 bool inserted = assigned_picture_buffers_.insert(std::make_pair( |
| 438 picture_buffers.back().id(), picture_buffers.back())).second; | 447 picture_buffers.back().id(), picture_buffers.back())).second; |
| 439 DCHECK(inserted); | 448 DCHECK(inserted); |
| 440 } | 449 } |
| 441 | 450 |
| 442 available_pictures_ += count; | 451 available_pictures_ += count; |
| 443 | 452 |
| 444 vda_->AssignPictureBuffers(picture_buffers); | 453 vda_->AssignPictureBuffers(picture_buffers); |
| 445 } | 454 } |
| 446 | 455 |
| 447 void GpuVideoDecoder::DismissPictureBuffer(int32_t id) { | 456 void GpuVideoDecoder::DismissPictureBuffer(int32_t id) { |
| 448 DVLOG(3) << "DismissPictureBuffer(" << id << ")"; | 457 DVLOG(3) << "DismissPictureBuffer(" << id << ")"; |
| 449 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 458 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 450 | 459 |
| 451 PictureBufferMap::iterator it = assigned_picture_buffers_.find(id); | 460 PictureBufferMap::iterator it = assigned_picture_buffers_.find(id); |
| 452 if (it == assigned_picture_buffers_.end()) { | 461 if (it == assigned_picture_buffers_.end()) { |
| 453 NOTREACHED() << "Missing picture buffer: " << id; | 462 NOTREACHED() << "Missing picture buffer: " << id; |
| 454 return; | 463 return; |
| 455 } | 464 } |
| 456 | 465 |
| 457 PictureBuffer buffer_to_dismiss = it->second; | 466 PictureBuffer buffer_to_dismiss = it->second; |
| 458 assigned_picture_buffers_.erase(it); | 467 assigned_picture_buffers_.erase(it); |
| 459 | 468 |
| 460 if (!picture_buffers_at_display_.count(id)) { | 469 if (!picture_buffers_at_display_.count(id)) { |
| 461 // We can delete the texture immediately as it's not being displayed. | 470 // We can delete the texture immediately as it's not being displayed. |
| 462 factories_->DeleteTexture(buffer_to_dismiss.texture_id()); | 471 for (uint32_t id : buffer_to_dismiss.texture_ids()) |
| 472 factories_->DeleteTexture(id); |
| 463 CHECK_GT(available_pictures_, 0); | 473 CHECK_GT(available_pictures_, 0); |
| 464 --available_pictures_; | 474 --available_pictures_; |
| 465 } | 475 } |
| 466 // Not destroying a texture in display in |picture_buffers_at_display_|. | 476 // Not destroying a texture in display in |picture_buffers_at_display_|. |
| 467 // Postpone deletion until after it's returned to us. | 477 // Postpone deletion until after it's returned to us. |
| 468 } | 478 } |
| 469 | 479 |
| 470 void GpuVideoDecoder::PictureReady(const media::Picture& picture) { | 480 void GpuVideoDecoder::PictureReady(const media::Picture& picture) { |
| 471 DVLOG(3) << "PictureReady()"; | 481 DVLOG(3) << "PictureReady()"; |
| 472 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 482 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 509 << " is larger than coded size " << pb.size().ToString(); | 519 << " is larger than coded size " << pb.size().ToString(); |
| 510 visible_rect = gfx::Rect(pb.size()); | 520 visible_rect = gfx::Rect(pb.size()); |
| 511 } | 521 } |
| 512 | 522 |
| 513 DCHECK(decoder_texture_target_); | 523 DCHECK(decoder_texture_target_); |
| 514 | 524 |
| 515 bool opaque = IsOpaque(config_.format()); | 525 bool opaque = IsOpaque(config_.format()); |
| 516 | 526 |
| 517 scoped_refptr<VideoFrame> frame(VideoFrame::WrapNativeTexture( | 527 scoped_refptr<VideoFrame> frame(VideoFrame::WrapNativeTexture( |
| 518 opaque ? PIXEL_FORMAT_XRGB : PIXEL_FORMAT_ARGB, | 528 opaque ? PIXEL_FORMAT_XRGB : PIXEL_FORMAT_ARGB, |
| 519 gpu::MailboxHolder(pb.texture_mailbox(), gpu::SyncToken(), | 529 gpu::MailboxHolder(pb.texture_mailbox(0), gpu::SyncToken(), |
| 520 decoder_texture_target_), | 530 decoder_texture_target_), |
| 521 BindToCurrentLoop(base::Bind( | 531 BindToCurrentLoop(base::Bind( |
| 522 &GpuVideoDecoder::ReleaseMailbox, weak_factory_.GetWeakPtr(), | 532 &GpuVideoDecoder::ReleaseMailbox, weak_factory_.GetWeakPtr(), |
| 523 factories_, picture.picture_buffer_id(), pb.texture_id())), | 533 factories_, picture.picture_buffer_id(), pb.texture_ids())), |
| 524 pb.size(), visible_rect, natural_size, timestamp)); | 534 pb.size(), visible_rect, natural_size, timestamp)); |
| 525 if (!frame) { | 535 if (!frame) { |
| 526 DLOG(ERROR) << "Create frame failed for: " << picture.picture_buffer_id(); | 536 DLOG(ERROR) << "Create frame failed for: " << picture.picture_buffer_id(); |
| 527 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); | 537 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); |
| 528 return; | 538 return; |
| 529 } | 539 } |
| 530 if (picture.allow_overlay()) | 540 if (picture.allow_overlay()) |
| 531 frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true); | 541 frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY, true); |
| 532 CHECK_GT(available_pictures_, 0); | 542 CHECK_GT(available_pictures_, 0); |
| 533 --available_pictures_; | 543 --available_pictures_; |
| 544 |
| 534 bool inserted = | 545 bool inserted = |
| 535 picture_buffers_at_display_.insert(std::make_pair( | 546 picture_buffers_at_display_ |
| 536 picture.picture_buffer_id(), | 547 .insert(std::make_pair(picture.picture_buffer_id(), pb.texture_ids())) |
| 537 pb.texture_id())).second; | 548 .second; |
| 538 DCHECK(inserted); | 549 DCHECK(inserted); |
| 539 | 550 |
| 540 DeliverFrame(frame); | 551 DeliverFrame(frame); |
| 541 } | 552 } |
| 542 | 553 |
| 543 void GpuVideoDecoder::DeliverFrame( | 554 void GpuVideoDecoder::DeliverFrame( |
| 544 const scoped_refptr<VideoFrame>& frame) { | 555 const scoped_refptr<VideoFrame>& frame) { |
| 545 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 556 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 546 | 557 |
| 547 // During a pending vda->Reset(), we don't accumulate frames. Drop it on the | 558 // During a pending vda->Reset(), we don't accumulate frames. Drop it on the |
| 548 // floor and return. | 559 // floor and return. |
| 549 if (!pending_reset_cb_.is_null()) | 560 if (!pending_reset_cb_.is_null()) |
| 550 return; | 561 return; |
| 551 | 562 |
| 552 output_cb_.Run(frame); | 563 output_cb_.Run(frame); |
| 553 } | 564 } |
| 554 | 565 |
| 555 // static | 566 // static |
| 556 void GpuVideoDecoder::ReleaseMailbox( | 567 void GpuVideoDecoder::ReleaseMailbox( |
| 557 base::WeakPtr<GpuVideoDecoder> decoder, | 568 base::WeakPtr<GpuVideoDecoder> decoder, |
| 558 media::GpuVideoAcceleratorFactories* factories, | 569 media::GpuVideoAcceleratorFactories* factories, |
| 559 int64_t picture_buffer_id, | 570 int64_t picture_buffer_id, |
| 560 uint32_t texture_id, | 571 PictureBuffer::TextureIds ids, |
| 561 const gpu::SyncToken& release_sync_token) { | 572 const gpu::SyncToken& release_sync_token) { |
| 562 DCHECK(factories->GetTaskRunner()->BelongsToCurrentThread()); | 573 DCHECK(factories->GetTaskRunner()->BelongsToCurrentThread()); |
| 563 factories->WaitSyncToken(release_sync_token); | 574 factories->WaitSyncToken(release_sync_token); |
| 564 | 575 |
| 565 if (decoder) { | 576 if (decoder) { |
| 566 decoder->ReusePictureBuffer(picture_buffer_id); | 577 decoder->ReusePictureBuffer(picture_buffer_id); |
| 567 return; | 578 return; |
| 568 } | 579 } |
| 569 // It's the last chance to delete the texture after display, | 580 // It's the last chance to delete the texture after display, |
| 570 // because GpuVideoDecoder was destructed. | 581 // because GpuVideoDecoder was destructed. |
| 571 factories->DeleteTexture(texture_id); | 582 for (uint32_t id : ids) |
| 583 factories->DeleteTexture(id); |
| 572 } | 584 } |
| 573 | 585 |
| 574 void GpuVideoDecoder::ReusePictureBuffer(int64_t picture_buffer_id) { | 586 void GpuVideoDecoder::ReusePictureBuffer(int64_t picture_buffer_id) { |
| 575 DVLOG(3) << "ReusePictureBuffer(" << picture_buffer_id << ")"; | 587 DVLOG(3) << "ReusePictureBuffer(" << picture_buffer_id << ")"; |
| 576 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 588 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 577 | 589 |
| 578 DCHECK(!picture_buffers_at_display_.empty()); | 590 DCHECK(!picture_buffers_at_display_.empty()); |
| 579 PictureBufferTextureMap::iterator display_iterator = | 591 PictureBufferTextureMap::iterator display_iterator = |
| 580 picture_buffers_at_display_.find(picture_buffer_id); | 592 picture_buffers_at_display_.find(picture_buffer_id); |
| 581 uint32_t texture_id = display_iterator->second; | 593 PictureBuffer::TextureIds ids = display_iterator->second; |
| 582 DCHECK(display_iterator != picture_buffers_at_display_.end()); | 594 DCHECK(display_iterator != picture_buffers_at_display_.end()); |
| 583 picture_buffers_at_display_.erase(display_iterator); | 595 picture_buffers_at_display_.erase(display_iterator); |
| 584 | 596 |
| 585 if (!assigned_picture_buffers_.count(picture_buffer_id)) { | 597 if (!assigned_picture_buffers_.count(picture_buffer_id)) { |
| 586 // This picture was dismissed while in display, so we postponed deletion. | 598 // This picture was dismissed while in display, so we postponed deletion. |
| 587 factories_->DeleteTexture(texture_id); | 599 for (uint32_t id : ids) |
| 600 factories_->DeleteTexture(id); |
| 588 return; | 601 return; |
| 589 } | 602 } |
| 590 | 603 |
| 591 ++available_pictures_; | 604 ++available_pictures_; |
| 592 | 605 |
| 593 // DestroyVDA() might already have been called. | 606 // DestroyVDA() might already have been called. |
| 594 if (vda_) | 607 if (vda_) |
| 595 vda_->ReusePictureBuffer(picture_buffer_id); | 608 vda_->ReusePictureBuffer(picture_buffer_id); |
| 596 } | 609 } |
| 597 | 610 |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 728 } | 741 } |
| 729 return false; | 742 return false; |
| 730 } | 743 } |
| 731 | 744 |
| 732 void GpuVideoDecoder::DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent() | 745 void GpuVideoDecoder::DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent() |
| 733 const { | 746 const { |
| 734 DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread()); | 747 DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread()); |
| 735 } | 748 } |
| 736 | 749 |
| 737 } // namespace media | 750 } // namespace media |
| OLD | NEW |