| 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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 | 61 |
| 62 RTCVideoDecoder::BufferData::BufferData() {} | 62 RTCVideoDecoder::BufferData::BufferData() {} |
| 63 | 63 |
| 64 RTCVideoDecoder::BufferData::~BufferData() {} | 64 RTCVideoDecoder::BufferData::~BufferData() {} |
| 65 | 65 |
| 66 RTCVideoDecoder::RTCVideoDecoder(webrtc::VideoCodecType type, | 66 RTCVideoDecoder::RTCVideoDecoder(webrtc::VideoCodecType type, |
| 67 media::GpuVideoAcceleratorFactories* factories) | 67 media::GpuVideoAcceleratorFactories* factories) |
| 68 : vda_error_counter_(0), | 68 : vda_error_counter_(0), |
| 69 video_codec_type_(type), | 69 video_codec_type_(type), |
| 70 factories_(factories), | 70 factories_(factories), |
| 71 decoder_texture_target_(0), | |
| 72 pixel_format_(media::PIXEL_FORMAT_UNKNOWN), | |
| 73 next_picture_buffer_id_(0), | 71 next_picture_buffer_id_(0), |
| 74 state_(UNINITIALIZED), | 72 state_(UNINITIALIZED), |
| 75 decode_complete_callback_(nullptr), | 73 decode_complete_callback_(nullptr), |
| 76 num_shm_buffers_(0), | 74 num_shm_buffers_(0), |
| 77 next_bitstream_buffer_id_(0), | 75 next_bitstream_buffer_id_(0), |
| 78 reset_bitstream_buffer_id_(ID_INVALID), | 76 reset_bitstream_buffer_id_(ID_INVALID), |
| 79 weak_factory_(this) { | 77 weak_factory_(this) { |
| 80 DCHECK(!factories_->GetTaskRunner()->BelongsToCurrentThread()); | 78 DCHECK(!factories_->GetTaskRunner()->BelongsToCurrentThread()); |
| 81 } | 79 } |
| 82 | 80 |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 const gfx::Size& size, | 309 const gfx::Size& size, |
| 312 uint32_t texture_target) { | 310 uint32_t texture_target) { |
| 313 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 311 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 314 DVLOG(3) << "ProvidePictureBuffers. texture_target=" << texture_target; | 312 DVLOG(3) << "ProvidePictureBuffers. texture_target=" << texture_target; |
| 315 | 313 |
| 316 if (!vda_) | 314 if (!vda_) |
| 317 return; | 315 return; |
| 318 | 316 |
| 319 std::vector<uint32_t> texture_ids; | 317 std::vector<uint32_t> texture_ids; |
| 320 std::vector<gpu::Mailbox> texture_mailboxes; | 318 std::vector<gpu::Mailbox> texture_mailboxes; |
| 321 decoder_texture_target_ = texture_target; | |
| 322 | 319 |
| 323 if (format == media::PIXEL_FORMAT_UNKNOWN) | 320 if (format == media::PIXEL_FORMAT_UNKNOWN) |
| 324 format = media::PIXEL_FORMAT_ARGB; | 321 format = media::PIXEL_FORMAT_ARGB; |
| 325 | 322 |
| 326 if ((pixel_format_ != media::PIXEL_FORMAT_UNKNOWN) && | 323 const uint32_t texture_count = buffer_count * textures_per_buffer; |
| 327 (format != pixel_format_)) { | 324 if (!factories_->CreateTextures(texture_count, size, &texture_ids, |
| 325 &texture_mailboxes, texture_target)) { |
| 328 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 326 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); |
| 329 return; | 327 return; |
| 330 } | 328 } |
| 331 | |
| 332 pixel_format_ = format; | |
| 333 const uint32_t texture_count = buffer_count * textures_per_buffer; | |
| 334 if (!factories_->CreateTextures(texture_count, size, &texture_ids, | |
| 335 &texture_mailboxes, | |
| 336 decoder_texture_target_)) { | |
| 337 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | |
| 338 return; | |
| 339 } | |
| 340 DCHECK_EQ(texture_count, texture_ids.size()); | 329 DCHECK_EQ(texture_count, texture_ids.size()); |
| 341 DCHECK_EQ(texture_count, texture_mailboxes.size()); | 330 DCHECK_EQ(texture_count, texture_mailboxes.size()); |
| 342 | 331 |
| 343 std::vector<media::PictureBuffer> picture_buffers; | 332 std::vector<media::PictureBuffer> picture_buffers; |
| 344 for (size_t buffer_index = 0; buffer_index < buffer_count; ++buffer_index) { | 333 for (size_t buffer_index = 0; buffer_index < buffer_count; ++buffer_index) { |
| 345 media::PictureBuffer::TextureIds ids; | 334 media::PictureBuffer::TextureIds ids; |
| 346 std::vector<gpu::Mailbox> mailboxes; | 335 std::vector<gpu::Mailbox> mailboxes; |
| 347 for (size_t texture_index = 0; texture_index < textures_per_buffer; | 336 for (size_t texture_index = 0; texture_index < textures_per_buffer; |
| 348 ++texture_index) { | 337 ++texture_index) { |
| 349 const size_t texture_id = | 338 const size_t texture_id = |
| 350 texture_index + textures_per_buffer * buffer_index; | 339 texture_index + textures_per_buffer * buffer_index; |
| 351 ids.push_back(texture_ids[texture_id]); | 340 ids.push_back(texture_ids[texture_id]); |
| 352 mailboxes.push_back(texture_mailboxes[texture_id]); | 341 mailboxes.push_back(texture_mailboxes[texture_id]); |
| 353 } | 342 } |
| 354 | 343 |
| 355 picture_buffers.push_back( | 344 picture_buffers.push_back(media::PictureBuffer(next_picture_buffer_id_++, |
| 356 media::PictureBuffer(next_picture_buffer_id_++, size, ids, mailboxes)); | 345 size, ids, texture_target, |
| 346 format, mailboxes)); |
| 357 const bool inserted = | 347 const bool inserted = |
| 358 assigned_picture_buffers_ | 348 assigned_picture_buffers_ |
| 359 .insert(std::make_pair(picture_buffers.back().id(), | 349 .insert(std::make_pair(picture_buffers.back().id(), |
| 360 picture_buffers.back())) | 350 picture_buffers.back())) |
| 361 .second; | 351 .second; |
| 362 DCHECK(inserted); | 352 DCHECK(inserted); |
| 363 } | 353 } |
| 364 vda_->AssignPictureBuffers(picture_buffers); | 354 vda_->AssignPictureBuffers(picture_buffers); |
| 365 } | 355 } |
| 366 | 356 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 408 | 398 |
| 409 const media::PictureBuffer& pb = it->second; | 399 const media::PictureBuffer& pb = it->second; |
| 410 if (visible_rect.IsEmpty() || !gfx::Rect(pb.size()).Contains(visible_rect)) { | 400 if (visible_rect.IsEmpty() || !gfx::Rect(pb.size()).Contains(visible_rect)) { |
| 411 LOG(ERROR) << "Invalid picture size: " << visible_rect.ToString() | 401 LOG(ERROR) << "Invalid picture size: " << visible_rect.ToString() |
| 412 << " should fit in " << pb.size().ToString(); | 402 << " should fit in " << pb.size().ToString(); |
| 413 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 403 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); |
| 414 return; | 404 return; |
| 415 } | 405 } |
| 416 | 406 |
| 417 scoped_refptr<media::VideoFrame> frame = | 407 scoped_refptr<media::VideoFrame> frame = |
| 418 CreateVideoFrame(picture, pb, timestamp, visible_rect, pixel_format_); | 408 CreateVideoFrame(picture, pb, timestamp, visible_rect, pb.pixel_format()); |
| 419 if (!frame) { | 409 if (!frame) { |
| 420 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); | 410 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); |
| 421 return; | 411 return; |
| 422 } | 412 } |
| 423 bool inserted = picture_buffers_at_display_ | 413 bool inserted = picture_buffers_at_display_ |
| 424 .insert(std::make_pair(picture.picture_buffer_id(), | 414 .insert(std::make_pair(picture.picture_buffer_id(), |
| 425 pb.client_texture_ids())) | 415 pb.client_texture_ids())) |
| 426 .second; | 416 .second; |
| 427 DCHECK(inserted); | 417 DCHECK(inserted); |
| 428 | 418 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 444 vda_error_counter_ = 0; | 434 vda_error_counter_ = 0; |
| 445 } | 435 } |
| 446 } | 436 } |
| 447 | 437 |
| 448 scoped_refptr<media::VideoFrame> RTCVideoDecoder::CreateVideoFrame( | 438 scoped_refptr<media::VideoFrame> RTCVideoDecoder::CreateVideoFrame( |
| 449 const media::Picture& picture, | 439 const media::Picture& picture, |
| 450 const media::PictureBuffer& pb, | 440 const media::PictureBuffer& pb, |
| 451 uint32_t timestamp, | 441 uint32_t timestamp, |
| 452 const gfx::Rect& visible_rect, | 442 const gfx::Rect& visible_rect, |
| 453 media::VideoPixelFormat pixel_format) { | 443 media::VideoPixelFormat pixel_format) { |
| 454 DCHECK(decoder_texture_target_); | 444 DCHECK(pb.texture_target()); |
| 455 // Convert timestamp from 90KHz to ms. | 445 // Convert timestamp from 90KHz to ms. |
| 456 base::TimeDelta timestamp_ms = base::TimeDelta::FromInternalValue( | 446 base::TimeDelta timestamp_ms = base::TimeDelta::FromInternalValue( |
| 457 base::checked_cast<uint64_t>(timestamp) * 1000 / 90); | 447 base::checked_cast<uint64_t>(timestamp) * 1000 / 90); |
| 458 // TODO(mcasas): The incoming data may actually be in a YUV format, but may be | 448 // TODO(mcasas): The incoming data may actually be in a YUV format, but may be |
| 459 // labelled as ARGB. This may or may not be reported by VDA, depending on | 449 // labelled as ARGB. This may or may not be reported by VDA, depending on |
| 460 // whether it provides an implementation of VDA::GetOutputFormat(). | 450 // whether it provides an implementation of VDA::GetOutputFormat(). |
| 461 // This prevents the compositor from messing with it, since the underlying | 451 // This prevents the compositor from messing with it, since the underlying |
| 462 // platform can handle the former format natively. Make sure the | 452 // platform can handle the former format natively. Make sure the |
| 463 // correct format is used and everyone down the line understands it. | 453 // correct format is used and everyone down the line understands it. |
| 464 gpu::MailboxHolder holders[media::VideoFrame::kMaxPlanes]; | 454 gpu::MailboxHolder holders[media::VideoFrame::kMaxPlanes]; |
| 465 for (size_t i = 0; i < pb.client_texture_ids().size(); ++i) { | 455 for (size_t i = 0; i < pb.client_texture_ids().size(); ++i) { |
| 466 holders[i].mailbox = pb.texture_mailbox(i); | 456 holders[i].mailbox = pb.texture_mailbox(i); |
| 467 holders[i].texture_target = decoder_texture_target_; | 457 holders[i].texture_target = pb.texture_target(); |
| 468 } | 458 } |
| 469 scoped_refptr<media::VideoFrame> frame = | 459 scoped_refptr<media::VideoFrame> frame = |
| 470 media::VideoFrame::WrapNativeTextures( | 460 media::VideoFrame::WrapNativeTextures( |
| 471 pixel_format, holders, | 461 pixel_format, holders, |
| 472 media::BindToCurrentLoop( | 462 media::BindToCurrentLoop( |
| 473 base::Bind(&RTCVideoDecoder::ReleaseMailbox, | 463 base::Bind(&RTCVideoDecoder::ReleaseMailbox, |
| 474 weak_factory_.GetWeakPtr(), factories_, | 464 weak_factory_.GetWeakPtr(), factories_, |
| 475 picture.picture_buffer_id(), pb.client_texture_ids())), | 465 picture.picture_buffer_id(), pb.client_texture_ids())), |
| 476 pb.size(), visible_rect, visible_rect.size(), timestamp_ms); | 466 pb.size(), visible_rect, visible_rect.size(), timestamp_ms); |
| 477 if (frame && picture.allow_overlay()) { | 467 if (frame && picture.allow_overlay()) { |
| (...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 903 } | 893 } |
| 904 | 894 |
| 905 void RTCVideoDecoder::ClearPendingBuffers() { | 895 void RTCVideoDecoder::ClearPendingBuffers() { |
| 906 // Delete WebRTC input buffers. | 896 // Delete WebRTC input buffers. |
| 907 for (const auto& pending_buffer : pending_buffers_) | 897 for (const auto& pending_buffer : pending_buffers_) |
| 908 delete[] pending_buffer.first._buffer; | 898 delete[] pending_buffer.first._buffer; |
| 909 pending_buffers_.clear(); | 899 pending_buffers_.clear(); |
| 910 } | 900 } |
| 911 | 901 |
| 912 } // namespace content | 902 } // namespace content |
| OLD | NEW |