| 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 "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
| 9 #include "base/cpu.h" | 9 #include "base/cpu.h" |
| 10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
| (...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 361 const gfx::Size& size, | 361 const gfx::Size& size, |
| 362 uint32 texture_target) { | 362 uint32 texture_target) { |
| 363 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 363 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
| 364 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 364 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 365 &GpuVideoDecoder::ProvidePictureBuffers, this, count, size, | 365 &GpuVideoDecoder::ProvidePictureBuffers, this, count, size, |
| 366 texture_target)); | 366 texture_target)); |
| 367 return; | 367 return; |
| 368 } | 368 } |
| 369 | 369 |
| 370 std::vector<uint32> texture_ids; | 370 std::vector<uint32> texture_ids; |
| 371 std::vector<gpu::Mailbox> texture_mailboxes; |
| 371 decoder_texture_target_ = texture_target; | 372 decoder_texture_target_ = texture_target; |
| 372 if (!factories_->CreateTextures( | 373 if (!factories_->CreateTextures(count, |
| 373 count, size, &texture_ids, decoder_texture_target_)) { | 374 size, |
| 375 &texture_ids, |
| 376 &texture_mailboxes, |
| 377 decoder_texture_target_)) { |
| 374 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); | 378 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); |
| 375 return; | 379 return; |
| 376 } | 380 } |
| 377 | 381 |
| 378 if (!vda_.get()) | 382 if (!vda_.get()) |
| 379 return; | 383 return; |
| 380 | 384 |
| 381 CHECK_EQ(available_pictures_, -1); | 385 CHECK_EQ(available_pictures_, -1); |
| 382 available_pictures_ = count; | 386 available_pictures_ = count; |
| 383 | 387 |
| 384 std::vector<PictureBuffer> picture_buffers; | 388 std::vector<PictureBuffer> picture_buffers; |
| 385 for (size_t i = 0; i < texture_ids.size(); ++i) { | 389 for (size_t i = 0; i < texture_ids.size(); ++i) { |
| 386 picture_buffers.push_back(PictureBuffer( | 390 picture_buffers.push_back(PictureBuffer( |
| 387 next_picture_buffer_id_++, size, texture_ids[i])); | 391 next_picture_buffer_id_++, size, texture_ids[i], texture_mailboxes[i])); |
| 388 bool inserted = picture_buffers_in_decoder_.insert(std::make_pair( | 392 bool inserted = picture_buffers_in_decoder_.insert(std::make_pair( |
| 389 picture_buffers.back().id(), picture_buffers.back())).second; | 393 picture_buffers.back().id(), picture_buffers.back())).second; |
| 390 DCHECK(inserted); | 394 DCHECK(inserted); |
| 391 } | 395 } |
| 392 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 396 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 393 &VideoDecodeAccelerator::AssignPictureBuffers, weak_vda_, | 397 &VideoDecodeAccelerator::AssignPictureBuffers, weak_vda_, |
| 394 picture_buffers)); | 398 picture_buffers)); |
| 395 } | 399 } |
| 396 | 400 |
| 397 void GpuVideoDecoder::DismissPictureBuffer(int32 id) { | 401 void GpuVideoDecoder::DismissPictureBuffer(int32 id) { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 425 } | 429 } |
| 426 const PictureBuffer& pb = it->second; | 430 const PictureBuffer& pb = it->second; |
| 427 | 431 |
| 428 // Update frame's timestamp. | 432 // Update frame's timestamp. |
| 429 base::TimeDelta timestamp; | 433 base::TimeDelta timestamp; |
| 430 gfx::Rect visible_rect; | 434 gfx::Rect visible_rect; |
| 431 gfx::Size natural_size; | 435 gfx::Size natural_size; |
| 432 GetBufferData(picture.bitstream_buffer_id(), ×tamp, &visible_rect, | 436 GetBufferData(picture.bitstream_buffer_id(), ×tamp, &visible_rect, |
| 433 &natural_size); | 437 &natural_size); |
| 434 DCHECK(decoder_texture_target_); | 438 DCHECK(decoder_texture_target_); |
| 439 |
| 440 #ifdef VIDEO_FRAME_MAILBOX |
| 441 uint32 sync_point = factories_->ProduceTextureToMailbox( |
| 442 pb.texture_mailbox(), pb.texture_id()); |
| 443 #endif |
| 444 |
| 435 scoped_refptr<VideoFrame> frame( | 445 scoped_refptr<VideoFrame> frame( |
| 436 VideoFrame::WrapNativeTexture( | 446 VideoFrame::WrapNativeTexture( |
| 437 pb.texture_id(), decoder_texture_target_, pb.size(), visible_rect, | 447 #ifdef VIDEO_FRAME_MAILBOX |
| 448 pb.texture_mailbox(), sync_point, |
| 449 #else |
| 450 pb.texture_id(), |
| 451 #endif |
| 452 decoder_texture_target_, |
| 453 pb.size(), visible_rect, |
| 438 natural_size, timestamp, | 454 natural_size, timestamp, |
| 439 base::Bind(&Factories::ReadPixels, factories_, pb.texture_id(), | 455 base::Bind(&Factories::ReadPixels, factories_, pb.texture_id(), |
| 440 decoder_texture_target_, | 456 decoder_texture_target_, |
| 441 gfx::Size(visible_rect.width(), visible_rect.height())), | 457 gfx::Size(visible_rect.width(), visible_rect.height())), |
| 442 base::Bind(&GpuVideoDecoder::ReusePictureBuffer, this, | 458 base::Bind(&GpuVideoDecoder::ReusePictureBuffer, this, |
| 443 picture.picture_buffer_id()))); | 459 picture.picture_buffer_id()), |
| 460 base::Closure())); |
| 444 CHECK_GT(available_pictures_, 0); | 461 CHECK_GT(available_pictures_, 0); |
| 445 available_pictures_--; | 462 available_pictures_--; |
| 446 | 463 |
| 447 EnqueueFrameAndTriggerFrameDelivery(frame); | 464 EnqueueFrameAndTriggerFrameDelivery(frame); |
| 448 } | 465 } |
| 449 | 466 |
| 450 void GpuVideoDecoder::EnqueueFrameAndTriggerFrameDelivery( | 467 void GpuVideoDecoder::EnqueueFrameAndTriggerFrameDelivery( |
| 451 const scoped_refptr<VideoFrame>& frame) { | 468 const scoped_refptr<VideoFrame>& frame) { |
| 452 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 469 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
| 453 | 470 |
| 454 // During a pending vda->Reset(), we don't accumulate frames. Drop it on the | 471 // During a pending vda->Reset(), we don't accumulate frames. Drop it on the |
| 455 // floor and return. | 472 // floor and return. |
| 456 if (!pending_reset_cb_.is_null()) | 473 if (!pending_reset_cb_.is_null()) |
| 457 return; | 474 return; |
| 458 | 475 |
| 459 if (frame) | 476 if (frame) |
| 460 ready_video_frames_.push_back(frame); | 477 ready_video_frames_.push_back(frame); |
| 461 else | 478 else |
| 462 DCHECK(!ready_video_frames_.empty()); | 479 DCHECK(!ready_video_frames_.empty()); |
| 463 | 480 |
| 464 if (pending_read_cb_.is_null()) | 481 if (pending_read_cb_.is_null()) |
| 465 return; | 482 return; |
| 466 | 483 |
| 467 base::ResetAndReturn(&pending_read_cb_).Run(kOk, ready_video_frames_.front()); | 484 base::ResetAndReturn(&pending_read_cb_).Run(kOk, ready_video_frames_.front()); |
| 468 ready_video_frames_.pop_front(); | 485 ready_video_frames_.pop_front(); |
| 469 } | 486 } |
| 470 | 487 |
| 471 void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id) { | 488 void GpuVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id, |
| 489 uint32 sync_point) { |
| 472 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { | 490 if (!gvd_loop_proxy_->BelongsToCurrentThread()) { |
| 473 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 491 gvd_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 474 &GpuVideoDecoder::ReusePictureBuffer, this, picture_buffer_id)); | 492 &GpuVideoDecoder::ReusePictureBuffer, |
| 493 this, |
| 494 picture_buffer_id, |
| 495 sync_point)); |
| 475 return; | 496 return; |
| 476 } | 497 } |
| 477 CHECK_GE(available_pictures_, 0); | 498 CHECK_GE(available_pictures_, 0); |
| 478 available_pictures_++; | 499 available_pictures_++; |
| 479 | 500 |
| 480 if (!vda_.get()) | 501 if (!vda_.get()) |
| 481 return; | 502 return; |
| 503 |
| 504 std::map<int32, PictureBuffer>::iterator it = |
| 505 picture_buffers_in_decoder_.find(picture_buffer_id); |
| 506 if (it == picture_buffers_in_decoder_.end()) { |
| 507 NOTREACHED() << "Missing picture buffer: " << picture_buffer_id; |
| 508 NotifyError(VideoDecodeAccelerator::PLATFORM_FAILURE); |
| 509 return; |
| 510 } |
| 511 #ifdef VIDEO_FRAME_MAILBOX |
| 512 const PictureBuffer& pb = it->second; |
| 513 factories_->ConsumeMailboxToTexture(pb.texture_mailbox(), |
| 514 pb.texture_id(), |
| 515 sync_point); |
| 516 #endif |
| 517 |
| 482 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( | 518 vda_loop_proxy_->PostTask(FROM_HERE, base::Bind( |
| 483 &VideoDecodeAccelerator::ReusePictureBuffer, weak_vda_, | 519 &VideoDecodeAccelerator::ReusePictureBuffer, weak_vda_, |
| 484 picture_buffer_id)); | 520 picture_buffer_id)); |
| 485 } | 521 } |
| 486 | 522 |
| 487 GpuVideoDecoder::SHMBuffer* GpuVideoDecoder::GetSHM(size_t min_size) { | 523 GpuVideoDecoder::SHMBuffer* GpuVideoDecoder::GetSHM(size_t min_size) { |
| 488 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); | 524 DCHECK(gvd_loop_proxy_->BelongsToCurrentThread()); |
| 489 if (available_shm_segments_.empty() || | 525 if (available_shm_segments_.empty() || |
| 490 available_shm_segments_.back()->size < min_size) { | 526 available_shm_segments_.back()->size < min_size) { |
| 491 size_t size_to_allocate = std::max(min_size, kSharedMemorySegmentBytes); | 527 size_t size_to_allocate = std::max(min_size, kSharedMemorySegmentBytes); |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 613 | 649 |
| 614 error_occured_ = true; | 650 error_occured_ = true; |
| 615 | 651 |
| 616 if (!pending_read_cb_.is_null()) { | 652 if (!pending_read_cb_.is_null()) { |
| 617 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); | 653 base::ResetAndReturn(&pending_read_cb_).Run(kDecodeError, NULL); |
| 618 return; | 654 return; |
| 619 } | 655 } |
| 620 } | 656 } |
| 621 | 657 |
| 622 } // namespace media | 658 } // namespace media |
| OLD | NEW |