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