| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/renderer/media/gpu/rtc_video_decoder.h" | 5 #include "content/renderer/media/gpu/rtc_video_decoder.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 } | 298 } |
| 299 if (next_bitstream_buffer_id_ != 0) | 299 if (next_bitstream_buffer_id_ != 0) |
| 300 reset_bitstream_buffer_id_ = next_bitstream_buffer_id_ - 1; | 300 reset_bitstream_buffer_id_ = next_bitstream_buffer_id_ - 1; |
| 301 else | 301 else |
| 302 reset_bitstream_buffer_id_ = ID_LAST; | 302 reset_bitstream_buffer_id_ = ID_LAST; |
| 303 frame_size_.SetSize(0, 0); | 303 frame_size_.SetSize(0, 0); |
| 304 Reset_Locked(); | 304 Reset_Locked(); |
| 305 return WEBRTC_VIDEO_CODEC_OK; | 305 return WEBRTC_VIDEO_CODEC_OK; |
| 306 } | 306 } |
| 307 | 307 |
| 308 void RTCVideoDecoder::ProvidePictureBuffers(uint32_t count, | 308 void RTCVideoDecoder::ProvidePictureBuffers(uint32_t buffer_count, |
| 309 media::VideoPixelFormat format, | 309 media::VideoPixelFormat format, |
| 310 uint32_t textures_per_buffer, | 310 uint32_t textures_per_buffer, |
| 311 const gfx::Size& size, | 311 const gfx::Size& size, |
| 312 uint32_t texture_target) { | 312 uint32_t texture_target) { |
| 313 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 313 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 314 DVLOG(3) << "ProvidePictureBuffers. texture_target=" << texture_target; | 314 DVLOG(3) << "ProvidePictureBuffers. texture_target=" << texture_target; |
| 315 DCHECK_EQ(1u, textures_per_buffer); | |
| 316 | 315 |
| 317 if (!vda_) | 316 if (!vda_) |
| 318 return; | 317 return; |
| 319 | 318 |
| 320 std::vector<uint32_t> texture_ids; | 319 std::vector<uint32_t> texture_ids; |
| 321 std::vector<gpu::Mailbox> texture_mailboxes; | 320 std::vector<gpu::Mailbox> texture_mailboxes; |
| 322 decoder_texture_target_ = texture_target; | 321 decoder_texture_target_ = texture_target; |
| 323 | 322 |
| 324 if (format == media::PIXEL_FORMAT_UNKNOWN) | 323 if (format == media::PIXEL_FORMAT_UNKNOWN) |
| 325 format = media::PIXEL_FORMAT_ARGB; | 324 format = media::PIXEL_FORMAT_ARGB; |
| 326 | 325 |
| 327 if ((pixel_format_ != media::PIXEL_FORMAT_UNKNOWN) && | 326 if ((pixel_format_ != media::PIXEL_FORMAT_UNKNOWN) && |
| 328 (format != pixel_format_)) { | 327 (format != pixel_format_)) { |
| 329 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 328 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); |
| 330 return; | 329 return; |
| 331 } | 330 } |
| 332 | 331 |
| 333 pixel_format_ = format; | 332 pixel_format_ = format; |
| 334 if (!factories_->CreateTextures(count, | 333 const uint32_t texture_count = buffer_count * textures_per_buffer; |
| 335 size, | 334 if (!factories_->CreateTextures(texture_count, size, &texture_ids, |
| 336 &texture_ids, | |
| 337 &texture_mailboxes, | 335 &texture_mailboxes, |
| 338 decoder_texture_target_)) { | 336 decoder_texture_target_)) { |
| 339 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 337 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); |
| 340 return; | 338 return; |
| 341 } | 339 } |
| 342 DCHECK_EQ(count, texture_ids.size()); | 340 DCHECK_EQ(texture_count, texture_ids.size()); |
| 343 DCHECK_EQ(count, texture_mailboxes.size()); | 341 DCHECK_EQ(texture_count, texture_mailboxes.size()); |
| 344 | 342 |
| 345 std::vector<media::PictureBuffer> picture_buffers; | 343 std::vector<media::PictureBuffer> picture_buffers; |
| 346 for (size_t i = 0; i < texture_ids.size(); ++i) { | 344 for (size_t buffer_index = 0; buffer_index < buffer_count; ++buffer_index) { |
| 347 media::PictureBuffer::TextureIds ids; | 345 media::PictureBuffer::TextureIds ids; |
| 348 ids.push_back(texture_ids[i]); | |
| 349 std::vector<gpu::Mailbox> mailboxes; | 346 std::vector<gpu::Mailbox> mailboxes; |
| 350 mailboxes.push_back(texture_mailboxes[i]); | 347 for (size_t texture_index = 0; texture_index < textures_per_buffer; |
| 348 ++texture_index) { |
| 349 const size_t texture_id = |
| 350 texture_index + textures_per_buffer * buffer_index; |
| 351 ids.push_back(texture_ids[texture_id]); |
| 352 mailboxes.push_back(texture_mailboxes[texture_id]); |
| 353 } |
| 351 | 354 |
| 352 picture_buffers.push_back( | 355 picture_buffers.push_back( |
| 353 media::PictureBuffer(next_picture_buffer_id_++, size, ids, mailboxes)); | 356 media::PictureBuffer(next_picture_buffer_id_++, size, ids, mailboxes)); |
| 354 bool inserted = assigned_picture_buffers_.insert(std::make_pair( | 357 const bool inserted = |
| 355 picture_buffers.back().id(), picture_buffers.back())).second; | 358 assigned_picture_buffers_ |
| 359 .insert(std::make_pair(picture_buffers.back().id(), |
| 360 picture_buffers.back())) |
| 361 .second; |
| 356 DCHECK(inserted); | 362 DCHECK(inserted); |
| 357 } | 363 } |
| 358 vda_->AssignPictureBuffers(picture_buffers); | 364 vda_->AssignPictureBuffers(picture_buffers); |
| 359 } | 365 } |
| 360 | 366 |
| 361 void RTCVideoDecoder::DismissPictureBuffer(int32_t id) { | 367 void RTCVideoDecoder::DismissPictureBuffer(int32_t id) { |
| 362 DVLOG(3) << "DismissPictureBuffer. id=" << id; | 368 DVLOG(3) << "DismissPictureBuffer. id=" << id; |
| 363 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 369 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 364 | 370 |
| 365 std::map<int32_t, media::PictureBuffer>::iterator it = | 371 std::map<int32_t, media::PictureBuffer>::iterator it = |
| 366 assigned_picture_buffers_.find(id); | 372 assigned_picture_buffers_.find(id); |
| 367 if (it == assigned_picture_buffers_.end()) { | 373 if (it == assigned_picture_buffers_.end()) { |
| 368 NOTREACHED() << "Missing picture buffer: " << id; | 374 NOTREACHED() << "Missing picture buffer: " << id; |
| 369 return; | 375 return; |
| 370 } | 376 } |
| 371 | 377 |
| 372 media::PictureBuffer buffer_to_dismiss = it->second; | 378 media::PictureBuffer buffer_to_dismiss = it->second; |
| 373 assigned_picture_buffers_.erase(it); | 379 assigned_picture_buffers_.erase(it); |
| 374 | 380 |
| 375 if (!picture_buffers_at_display_.count(id)) { | 381 if (!picture_buffers_at_display_.count(id)) { |
| 376 // We can delete the texture immediately as it's not being displayed. | 382 // We can delete the texture immediately as it's not being displayed. |
| 377 factories_->DeleteTexture(buffer_to_dismiss.client_texture_ids()[0]); | 383 for (const auto& id : buffer_to_dismiss.client_texture_ids()) |
| 384 factories_->DeleteTexture(id); |
| 378 return; | 385 return; |
| 379 } | 386 } |
| 380 // Not destroying a texture in display in |picture_buffers_at_display_|. | 387 // Not destroying a texture in display in |picture_buffers_at_display_|. |
| 381 // Postpone deletion until after it's returned to us. | 388 // Postpone deletion until after it's returned to us. |
| 382 } | 389 } |
| 383 | 390 |
| 384 void RTCVideoDecoder::PictureReady(const media::Picture& picture) { | 391 void RTCVideoDecoder::PictureReady(const media::Picture& picture) { |
| 385 DVLOG(3) << "PictureReady"; | 392 DVLOG(3) << "PictureReady"; |
| 386 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 393 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 387 | 394 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 408 } | 415 } |
| 409 | 416 |
| 410 scoped_refptr<media::VideoFrame> frame = | 417 scoped_refptr<media::VideoFrame> frame = |
| 411 CreateVideoFrame(picture, pb, timestamp, visible_rect, pixel_format_); | 418 CreateVideoFrame(picture, pb, timestamp, visible_rect, pixel_format_); |
| 412 if (!frame) { | 419 if (!frame) { |
| 413 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 420 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); |
| 414 return; | 421 return; |
| 415 } | 422 } |
| 416 bool inserted = picture_buffers_at_display_ | 423 bool inserted = picture_buffers_at_display_ |
| 417 .insert(std::make_pair(picture.picture_buffer_id(), | 424 .insert(std::make_pair(picture.picture_buffer_id(), |
| 418 pb.client_texture_ids()[0])) | 425 pb.client_texture_ids())) |
| 419 .second; | 426 .second; |
| 420 DCHECK(inserted); | 427 DCHECK(inserted); |
| 421 | 428 |
| 422 // Create a WebRTC video frame. | 429 // Create a WebRTC video frame. |
| 423 webrtc::VideoFrame decoded_image( | 430 webrtc::VideoFrame decoded_image( |
| 424 new rtc::RefCountedObject<WebRtcVideoFrameAdapter>( | 431 new rtc::RefCountedObject<WebRtcVideoFrameAdapter>( |
| 425 frame, WebRtcVideoFrameAdapter::CopyTextureFrameCallback()), | 432 frame, WebRtcVideoFrameAdapter::CopyTextureFrameCallback()), |
| 426 timestamp, 0, webrtc::kVideoRotation_0); | 433 timestamp, 0, webrtc::kVideoRotation_0); |
| 427 | 434 |
| 428 // Invoke decode callback. WebRTC expects no callback after Release. | 435 // Invoke decode callback. WebRTC expects no callback after Release. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 447 DCHECK(decoder_texture_target_); | 454 DCHECK(decoder_texture_target_); |
| 448 // Convert timestamp from 90KHz to ms. | 455 // Convert timestamp from 90KHz to ms. |
| 449 base::TimeDelta timestamp_ms = base::TimeDelta::FromInternalValue( | 456 base::TimeDelta timestamp_ms = base::TimeDelta::FromInternalValue( |
| 450 base::checked_cast<uint64_t>(timestamp) * 1000 / 90); | 457 base::checked_cast<uint64_t>(timestamp) * 1000 / 90); |
| 451 // TODO(mcasas): The incoming data may actually be in a YUV format, but may be | 458 // TODO(mcasas): The incoming data may actually be in a YUV format, but may be |
| 452 // labelled as ARGB. This may or may not be reported by VDA, depending on | 459 // labelled as ARGB. This may or may not be reported by VDA, depending on |
| 453 // whether it provides an implementation of VDA::GetOutputFormat(). | 460 // whether it provides an implementation of VDA::GetOutputFormat(). |
| 454 // This prevents the compositor from messing with it, since the underlying | 461 // This prevents the compositor from messing with it, since the underlying |
| 455 // platform can handle the former format natively. Make sure the | 462 // platform can handle the former format natively. Make sure the |
| 456 // correct format is used and everyone down the line understands it. | 463 // correct format is used and everyone down the line understands it. |
| 457 gpu::MailboxHolder holders[media::VideoFrame::kMaxPlanes] = { | 464 gpu::MailboxHolder holders[media::VideoFrame::kMaxPlanes]; |
| 458 gpu::MailboxHolder(pb.texture_mailbox(0), gpu::SyncToken(), | 465 for (size_t i = 0; i < pb.client_texture_ids().size(); ++i) { |
| 459 decoder_texture_target_)}; | 466 holders[i].mailbox = pb.texture_mailbox(i); |
| 467 holders[i].texture_target = decoder_texture_target_; |
| 468 } |
| 460 scoped_refptr<media::VideoFrame> frame = | 469 scoped_refptr<media::VideoFrame> frame = |
| 461 media::VideoFrame::WrapNativeTextures( | 470 media::VideoFrame::WrapNativeTextures( |
| 462 pixel_format, holders, | 471 pixel_format, holders, |
| 463 media::BindToCurrentLoop(base::Bind( | 472 media::BindToCurrentLoop( |
| 464 &RTCVideoDecoder::ReleaseMailbox, weak_factory_.GetWeakPtr(), | 473 base::Bind(&RTCVideoDecoder::ReleaseMailbox, |
| 465 factories_, picture.picture_buffer_id(), | 474 weak_factory_.GetWeakPtr(), factories_, |
| 466 pb.client_texture_ids()[0])), | 475 picture.picture_buffer_id(), pb.client_texture_ids())), |
| 467 pb.size(), visible_rect, visible_rect.size(), timestamp_ms); | 476 pb.size(), visible_rect, visible_rect.size(), timestamp_ms); |
| 468 if (frame && picture.allow_overlay()) { | 477 if (frame && picture.allow_overlay()) { |
| 469 frame->metadata()->SetBoolean(media::VideoFrameMetadata::ALLOW_OVERLAY, | 478 frame->metadata()->SetBoolean(media::VideoFrameMetadata::ALLOW_OVERLAY, |
| 470 true); | 479 true); |
| 471 } | 480 } |
| 472 return frame; | 481 return frame; |
| 473 } | 482 } |
| 474 | 483 |
| 475 void RTCVideoDecoder::NotifyEndOfBitstreamBuffer(int32_t id) { | 484 void RTCVideoDecoder::NotifyEndOfBitstreamBuffer(int32_t id) { |
| 476 DVLOG(3) << "NotifyEndOfBitstreamBuffer. id=" << id; | 485 DVLOG(3) << "NotifyEndOfBitstreamBuffer. id=" << id; |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 679 state_ = INITIALIZED; | 688 state_ = INITIALIZED; |
| 680 } | 689 } |
| 681 } | 690 } |
| 682 } | 691 } |
| 683 | 692 |
| 684 // static | 693 // static |
| 685 void RTCVideoDecoder::ReleaseMailbox( | 694 void RTCVideoDecoder::ReleaseMailbox( |
| 686 base::WeakPtr<RTCVideoDecoder> decoder, | 695 base::WeakPtr<RTCVideoDecoder> decoder, |
| 687 media::GpuVideoAcceleratorFactories* factories, | 696 media::GpuVideoAcceleratorFactories* factories, |
| 688 int64_t picture_buffer_id, | 697 int64_t picture_buffer_id, |
| 689 uint32_t texture_id, | 698 const media::PictureBuffer::TextureIds& texture_ids, |
| 690 const gpu::SyncToken& release_sync_token) { | 699 const gpu::SyncToken& release_sync_token) { |
| 691 DCHECK(factories->GetTaskRunner()->BelongsToCurrentThread()); | 700 DCHECK(factories->GetTaskRunner()->BelongsToCurrentThread()); |
| 692 factories->WaitSyncToken(release_sync_token); | 701 factories->WaitSyncToken(release_sync_token); |
| 693 | 702 |
| 694 if (decoder) { | 703 if (decoder) { |
| 695 decoder->ReusePictureBuffer(picture_buffer_id); | 704 decoder->ReusePictureBuffer(picture_buffer_id); |
| 696 return; | 705 return; |
| 697 } | 706 } |
| 698 // It's the last chance to delete the texture after display, | 707 // It's the last chance to delete the texture after display, |
| 699 // because RTCVideoDecoder was destructed. | 708 // because RTCVideoDecoder was destructed. |
| 700 factories->DeleteTexture(texture_id); | 709 for (const auto& id : texture_ids) |
| 710 factories->DeleteTexture(id); |
| 701 } | 711 } |
| 702 | 712 |
| 703 void RTCVideoDecoder::ReusePictureBuffer(int64_t picture_buffer_id) { | 713 void RTCVideoDecoder::ReusePictureBuffer(int64_t picture_buffer_id) { |
| 704 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 714 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 705 DVLOG(3) << "ReusePictureBuffer. id=" << picture_buffer_id; | 715 DVLOG(3) << "ReusePictureBuffer. id=" << picture_buffer_id; |
| 706 | 716 |
| 707 DCHECK(!picture_buffers_at_display_.empty()); | 717 DCHECK(!picture_buffers_at_display_.empty()); |
| 708 PictureBufferTextureMap::iterator display_iterator = | 718 PictureBufferTextureMap::iterator display_iterator = |
| 709 picture_buffers_at_display_.find(picture_buffer_id); | 719 picture_buffers_at_display_.find(picture_buffer_id); |
| 710 uint32_t texture_id = display_iterator->second; | 720 const auto texture_ids = display_iterator->second; |
| 711 DCHECK(display_iterator != picture_buffers_at_display_.end()); | 721 DCHECK(display_iterator != picture_buffers_at_display_.end()); |
| 712 picture_buffers_at_display_.erase(display_iterator); | 722 picture_buffers_at_display_.erase(display_iterator); |
| 713 | 723 |
| 714 if (!assigned_picture_buffers_.count(picture_buffer_id)) { | 724 if (!assigned_picture_buffers_.count(picture_buffer_id)) { |
| 715 // This picture was dismissed while in display, so we postponed deletion. | 725 // This picture was dismissed while in display, so we postponed deletion. |
| 716 factories_->DeleteTexture(texture_id); | 726 for (const auto& id : texture_ids) |
| 727 factories_->DeleteTexture(id); |
| 717 return; | 728 return; |
| 718 } | 729 } |
| 719 | 730 |
| 720 // DestroyVDA() might already have been called. | 731 // DestroyVDA() might already have been called. |
| 721 if (vda_) | 732 if (vda_) |
| 722 vda_->ReusePictureBuffer(picture_buffer_id); | 733 vda_->ReusePictureBuffer(picture_buffer_id); |
| 723 } | 734 } |
| 724 | 735 |
| 725 bool RTCVideoDecoder::IsProfileSupported(media::VideoCodecProfile profile) { | 736 bool RTCVideoDecoder::IsProfileSupported(media::VideoCodecProfile profile) { |
| 726 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 737 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 758 } | 769 } |
| 759 | 770 |
| 760 void RTCVideoDecoder::DestroyTextures() { | 771 void RTCVideoDecoder::DestroyTextures() { |
| 761 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 772 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 762 | 773 |
| 763 // Not destroying PictureBuffers in |picture_buffers_at_display_| yet, since | 774 // Not destroying PictureBuffers in |picture_buffers_at_display_| yet, since |
| 764 // their textures may still be in use by the user of this RTCVideoDecoder. | 775 // their textures may still be in use by the user of this RTCVideoDecoder. |
| 765 for (const auto& picture_buffer_at_display : picture_buffers_at_display_) | 776 for (const auto& picture_buffer_at_display : picture_buffers_at_display_) |
| 766 assigned_picture_buffers_.erase(picture_buffer_at_display.first); | 777 assigned_picture_buffers_.erase(picture_buffer_at_display.first); |
| 767 | 778 |
| 768 for (const auto& assigned_picture_buffer : assigned_picture_buffers_) | 779 for (const auto& assigned_picture_buffer : assigned_picture_buffers_) { |
| 769 factories_->DeleteTexture( | 780 for (const auto& id : assigned_picture_buffer.second.client_texture_ids()) |
| 770 assigned_picture_buffer.second.client_texture_ids()[0]); | 781 factories_->DeleteTexture(id); |
| 782 } |
| 771 | 783 |
| 772 assigned_picture_buffers_.clear(); | 784 assigned_picture_buffers_.clear(); |
| 773 } | 785 } |
| 774 | 786 |
| 775 void RTCVideoDecoder::DestroyVDA() { | 787 void RTCVideoDecoder::DestroyVDA() { |
| 776 DVLOG(2) << "DestroyVDA"; | 788 DVLOG(2) << "DestroyVDA"; |
| 777 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 789 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 778 if (vda_) | 790 if (vda_) |
| 779 vda_.release()->Destroy(); | 791 vda_.release()->Destroy(); |
| 780 DestroyTextures(); | 792 DestroyTextures(); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 891 } | 903 } |
| 892 | 904 |
| 893 void RTCVideoDecoder::ClearPendingBuffers() { | 905 void RTCVideoDecoder::ClearPendingBuffers() { |
| 894 // Delete WebRTC input buffers. | 906 // Delete WebRTC input buffers. |
| 895 for (const auto& pending_buffer : pending_buffers_) | 907 for (const auto& pending_buffer : pending_buffers_) |
| 896 delete[] pending_buffer.first._buffer; | 908 delete[] pending_buffer.first._buffer; |
| 897 pending_buffers_.clear(); | 909 pending_buffers_.clear(); |
| 898 } | 910 } |
| 899 | 911 |
| 900 } // namespace content | 912 } // namespace content |
| OLD | NEW |