Chromium Code Reviews| 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/gpu/vaapi_video_decode_accelerator.h" | 5 #include "media/gpu/vaapi_video_decode_accelerator.h" |
| 6 | 6 |
| 7 #include <string.h> | 7 #include <string.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 | 10 |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 261 private: | 261 private: |
| 262 scoped_refptr<VaapiDecodeSurface> VP9PictureToVaapiDecodeSurface( | 262 scoped_refptr<VaapiDecodeSurface> VP9PictureToVaapiDecodeSurface( |
| 263 const scoped_refptr<VP9Picture>& pic); | 263 const scoped_refptr<VP9Picture>& pic); |
| 264 | 264 |
| 265 VaapiWrapper* vaapi_wrapper_; | 265 VaapiWrapper* vaapi_wrapper_; |
| 266 VaapiVideoDecodeAccelerator* vaapi_dec_; | 266 VaapiVideoDecodeAccelerator* vaapi_dec_; |
| 267 | 267 |
| 268 DISALLOW_COPY_AND_ASSIGN(VaapiVP9Accelerator); | 268 DISALLOW_COPY_AND_ASSIGN(VaapiVP9Accelerator); |
| 269 }; | 269 }; |
| 270 | 270 |
| 271 VaapiVideoDecodeAccelerator::InputBuffer::InputBuffer() : id(0) {} | |
| 272 | |
| 273 VaapiVideoDecodeAccelerator::InputBuffer::~InputBuffer() {} | |
| 274 | |
| 275 void VaapiVideoDecodeAccelerator::NotifyError(Error error) { | 271 void VaapiVideoDecodeAccelerator::NotifyError(Error error) { |
| 276 if (!task_runner_->BelongsToCurrentThread()) { | 272 if (!task_runner_->BelongsToCurrentThread()) { |
| 277 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 273 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 278 task_runner_->PostTask(FROM_HERE, | 274 task_runner_->PostTask(FROM_HERE, |
| 279 base::Bind(&VaapiVideoDecodeAccelerator::NotifyError, | 275 base::Bind(&VaapiVideoDecodeAccelerator::NotifyError, |
| 280 weak_this_, error)); | 276 weak_this_, error)); |
| 281 return; | 277 return; |
| 282 } | 278 } |
| 283 | 279 |
| 284 // Post Cleanup() as a task so we don't recursively acquire lock_. | 280 // Post Cleanup() as a task so we don't recursively acquire lock_. |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 454 VaapiPicture* picture = PictureById(output_buffers_.front()); | 450 VaapiPicture* picture = PictureById(output_buffers_.front()); |
| 455 DCHECK(picture); | 451 DCHECK(picture); |
| 456 output_buffers_.pop(); | 452 output_buffers_.pop(); |
| 457 | 453 |
| 458 output_cb.Run(picture); | 454 output_cb.Run(picture); |
| 459 | 455 |
| 460 if (finish_flush_pending_ && pending_output_cbs_.empty()) | 456 if (finish_flush_pending_ && pending_output_cbs_.empty()) |
| 461 FinishFlush(); | 457 FinishFlush(); |
| 462 } | 458 } |
| 463 | 459 |
| 464 void VaapiVideoDecodeAccelerator::MapAndQueueNewInputBuffer( | 460 void VaapiVideoDecodeAccelerator::QueueInputBuffer( |
| 465 const BitstreamBuffer& bitstream_buffer) { | 461 const BitstreamBuffer& bitstream_buffer) { |
| 466 DCHECK(task_runner_->BelongsToCurrentThread()); | 462 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 467 TRACE_EVENT1("Video Decoder", "MapAndQueueNewInputBuffer", "input_id", | 463 TRACE_EVENT1("Video Decoder", "QueueInputBuffer", "input_id", |
| 468 bitstream_buffer.id()); | 464 bitstream_buffer.id()); |
| 469 | 465 |
| 470 DVLOG(4) << "Mapping new input buffer id: " << bitstream_buffer.id() | 466 DVLOG(4) << "Queueing new input buffer id: " << bitstream_buffer.id() |
| 471 << " size: " << (int)bitstream_buffer.size(); | 467 << " size: " << (int)bitstream_buffer.size(); |
| 472 | 468 |
| 473 std::unique_ptr<SharedMemoryRegion> shm( | 469 base::AutoLock auto_lock(lock_); |
| 474 new SharedMemoryRegion(bitstream_buffer, true)); | 470 if (bitstream_buffer.size() == 0) { |
| 471 // Dummy buffer for flush. | |
| 472 DCHECK(!base::SharedMemory::IsHandleValid(bitstream_buffer.handle())); | |
| 473 input_buffers_.push(make_linked_ptr(new InputBuffer())); | |
| 474 } else { | |
| 475 std::unique_ptr<SharedMemoryRegion> shm( | |
| 476 new SharedMemoryRegion(bitstream_buffer, true)); | |
| 475 | 477 |
| 476 // Skip empty buffers. | 478 RETURN_AND_NOTIFY_ON_FAILURE(shm->Map(), "Failed to map input buffer", |
| 477 if (bitstream_buffer.size() == 0) { | 479 UNREADABLE_INPUT, ); |
| 478 if (client_) | 480 |
| 479 client_->NotifyEndOfBitstreamBuffer(bitstream_buffer.id()); | 481 linked_ptr<InputBuffer> input_buffer(new InputBuffer()); |
| 480 return; | 482 input_buffer->shm = std::move(shm); |
| 483 input_buffer->id = bitstream_buffer.id(); | |
| 484 input_buffers_.push(input_buffer); | |
| 481 } | 485 } |
| 482 | 486 |
| 483 RETURN_AND_NOTIFY_ON_FAILURE(shm->Map(), "Failed to map input buffer", | |
| 484 UNREADABLE_INPUT, ); | |
| 485 | |
| 486 base::AutoLock auto_lock(lock_); | |
| 487 | |
| 488 // Set up a new input buffer and queue it for later. | |
| 489 linked_ptr<InputBuffer> input_buffer(new InputBuffer()); | |
| 490 input_buffer->shm = std::move(shm); | |
| 491 input_buffer->id = bitstream_buffer.id(); | |
| 492 | |
| 493 ++num_stream_bufs_at_decoder_; | 487 ++num_stream_bufs_at_decoder_; |
|
Pawel Osciak
2017/01/24 07:10:33
I think we should only increment for non-flush buf
kcwu
2017/01/24 07:54:23
Done.
| |
| 494 TRACE_COUNTER1("Video Decoder", "Stream buffers at decoder", | 488 TRACE_COUNTER1("Video Decoder", "Stream buffers at decoder", |
| 495 num_stream_bufs_at_decoder_); | 489 num_stream_bufs_at_decoder_); |
| 496 | 490 |
| 497 input_buffers_.push(input_buffer); | |
| 498 input_ready_.Signal(); | 491 input_ready_.Signal(); |
| 492 | |
| 493 switch (state_) { | |
| 494 case kIdle: | |
| 495 state_ = kDecoding; | |
| 496 decoder_thread_task_runner_->PostTask( | |
| 497 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::DecodeTask, | |
| 498 base::Unretained(this))); | |
| 499 break; | |
| 500 | |
| 501 case kDecoding: | |
| 502 // Decoder already running. | |
| 503 break; | |
| 504 | |
| 505 case kResetting: | |
| 506 // When resetting, allow accumulating bitstream buffers, so that | |
| 507 // the client can queue after-seek-buffers while we are finishing with | |
| 508 // the before-seek one. | |
| 509 break; | |
| 510 | |
| 511 default: | |
| 512 LOG(ERROR) << "Decode/Flush request from client in invalid state: " | |
| 513 << state_; | |
| 514 NotifyError(PLATFORM_FAILURE); | |
| 515 break; | |
| 516 } | |
| 499 } | 517 } |
| 500 | 518 |
| 501 bool VaapiVideoDecodeAccelerator::GetInputBuffer_Locked() { | 519 bool VaapiVideoDecodeAccelerator::GetInputBuffer_Locked() { |
| 502 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 520 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 503 lock_.AssertAcquired(); | 521 lock_.AssertAcquired(); |
| 504 | 522 |
| 505 if (curr_input_buffer_.get()) | 523 if (curr_input_buffer_.get()) |
| 506 return true; | 524 return true; |
| 507 | 525 |
| 508 // Will only wait if it is expected that in current state new buffers will | 526 // Will only wait if it is expected that in current state new buffers will |
| 509 // be queued from the client via Decode(). The state can change during wait. | 527 // be queued from the client via Decode(). The state can change during wait. |
| 510 while (input_buffers_.empty() && (state_ == kDecoding || state_ == kIdle)) { | 528 while (input_buffers_.empty() && (state_ == kDecoding || state_ == kIdle)) { |
| 511 input_ready_.Wait(); | 529 input_ready_.Wait(); |
| 512 } | 530 } |
| 513 | 531 |
| 514 // We could have got woken up in a different state or never got to sleep | 532 // We could have got woken up in a different state or never got to sleep |
| 515 // due to current state; check for that. | 533 // due to current state; check for that. |
| 516 switch (state_) { | 534 switch (state_) { |
| 517 case kFlushing: | |
| 518 // Here we are only interested in finishing up decoding buffers that are | |
| 519 // already queued up. Otherwise will stop decoding. | |
| 520 if (input_buffers_.empty()) | |
| 521 return false; | |
| 522 // else fallthrough | |
| 523 case kDecoding: | 535 case kDecoding: |
| 524 case kIdle: | 536 case kIdle: |
| 525 DCHECK(!input_buffers_.empty()); | 537 DCHECK(!input_buffers_.empty()); |
| 526 | 538 |
| 527 curr_input_buffer_ = input_buffers_.front(); | 539 curr_input_buffer_ = input_buffers_.front(); |
| 528 input_buffers_.pop(); | 540 input_buffers_.pop(); |
| 529 | 541 |
| 530 DVLOG(4) << "New current bitstream buffer, id: " << curr_input_buffer_->id | 542 if (curr_input_buffer_->is_flush()) { |
| 531 << " size: " << curr_input_buffer_->shm->size(); | 543 DVLOG(4) << "New flush buffer"; |
| 544 } else { | |
| 545 DVLOG(4) << "New current bitstream buffer, id: " | |
| 546 << curr_input_buffer_->id | |
| 547 << " size: " << curr_input_buffer_->shm->size(); | |
| 532 | 548 |
| 533 decoder_->SetStream( | 549 decoder_->SetStream( |
| 534 static_cast<uint8_t*>(curr_input_buffer_->shm->memory()), | 550 static_cast<uint8_t*>(curr_input_buffer_->shm->memory()), |
| 535 curr_input_buffer_->shm->size()); | 551 curr_input_buffer_->shm->size()); |
| 552 } | |
| 536 return true; | 553 return true; |
| 537 | 554 |
| 538 default: | 555 default: |
| 539 // We got woken up due to being destroyed/reset, ignore any already | 556 // We got woken up due to being destroyed/reset, ignore any already |
| 540 // queued inputs. | 557 // queued inputs. |
| 541 return false; | 558 return false; |
| 542 } | 559 } |
| 543 } | 560 } |
| 544 | 561 |
| 545 void VaapiVideoDecodeAccelerator::ReturnCurrInputBuffer_Locked() { | 562 void VaapiVideoDecodeAccelerator::ReturnCurrInputBuffer_Locked() { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 558 num_stream_bufs_at_decoder_); | 575 num_stream_bufs_at_decoder_); |
| 559 } | 576 } |
| 560 | 577 |
| 561 // TODO(posciak): refactor the whole class to remove sleeping in wait for | 578 // TODO(posciak): refactor the whole class to remove sleeping in wait for |
| 562 // surfaces, and reschedule DecodeTask instead. | 579 // surfaces, and reschedule DecodeTask instead. |
| 563 bool VaapiVideoDecodeAccelerator::WaitForSurfaces_Locked() { | 580 bool VaapiVideoDecodeAccelerator::WaitForSurfaces_Locked() { |
| 564 lock_.AssertAcquired(); | 581 lock_.AssertAcquired(); |
| 565 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 582 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 566 | 583 |
| 567 while (available_va_surfaces_.empty() && | 584 while (available_va_surfaces_.empty() && |
| 568 (state_ == kDecoding || state_ == kFlushing || state_ == kIdle)) { | 585 (state_ == kDecoding || state_ == kIdle)) { |
| 569 surfaces_available_.Wait(); | 586 surfaces_available_.Wait(); |
| 570 } | 587 } |
| 571 | 588 |
| 572 if (state_ != kDecoding && state_ != kFlushing && state_ != kIdle) | 589 if (state_ != kDecoding && state_ != kIdle) |
| 573 return false; | 590 return false; |
| 574 | 591 |
| 575 return true; | 592 return true; |
| 576 } | 593 } |
| 577 | 594 |
| 578 void VaapiVideoDecodeAccelerator::DecodeTask() { | 595 void VaapiVideoDecodeAccelerator::DecodeTask() { |
| 579 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 596 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 580 TRACE_EVENT0("Video Decoder", "VAVDA::DecodeTask"); | 597 TRACE_EVENT0("Video Decoder", "VAVDA::DecodeTask"); |
| 581 base::AutoLock auto_lock(lock_); | 598 base::AutoLock auto_lock(lock_); |
| 582 | 599 |
| 583 if (state_ != kDecoding) | 600 if (state_ != kDecoding) |
| 584 return; | 601 return; |
| 585 | 602 |
| 586 // Main decode task. | 603 // Main decode task. |
| 587 DVLOG(4) << "Decode task"; | 604 DVLOG(4) << "Decode task"; |
| 588 | 605 |
| 589 // Try to decode what stream data is (still) in the decoder until we run out | 606 // Try to decode what stream data is (still) in the decoder until we run out |
| 590 // of it. | 607 // of it. |
| 591 while (GetInputBuffer_Locked()) { | 608 while (GetInputBuffer_Locked()) { |
| 592 DCHECK(curr_input_buffer_.get()); | 609 DCHECK(curr_input_buffer_.get()); |
| 593 | 610 |
| 611 if (curr_input_buffer_->is_flush()) { | |
| 612 FlushTask(); | |
| 613 break; | |
| 614 } | |
| 615 | |
| 594 AcceleratedVideoDecoder::DecodeResult res; | 616 AcceleratedVideoDecoder::DecodeResult res; |
| 595 { | 617 { |
| 596 // We are OK releasing the lock here, as decoder never calls our methods | 618 // We are OK releasing the lock here, as decoder never calls our methods |
| 597 // directly and we will reacquire the lock before looking at state again. | 619 // directly and we will reacquire the lock before looking at state again. |
| 598 // This is the main decode function of the decoder and while keeping | 620 // This is the main decode function of the decoder and while keeping |
| 599 // the lock for its duration would be fine, it would defeat the purpose | 621 // the lock for its duration would be fine, it would defeat the purpose |
| 600 // of having a separate decoder thread. | 622 // of having a separate decoder thread. |
| 601 base::AutoUnlock auto_unlock(lock_); | 623 base::AutoUnlock auto_unlock(lock_); |
| 602 res = decoder_->Decode(); | 624 res = decoder_->Decode(); |
| 603 } | 625 } |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 728 bitstream_buffer.id()); | 750 bitstream_buffer.id()); |
| 729 | 751 |
| 730 if (bitstream_buffer.id() < 0) { | 752 if (bitstream_buffer.id() < 0) { |
| 731 if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle())) | 753 if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle())) |
| 732 base::SharedMemory::CloseHandle(bitstream_buffer.handle()); | 754 base::SharedMemory::CloseHandle(bitstream_buffer.handle()); |
| 733 LOG(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id(); | 755 LOG(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id(); |
| 734 NotifyError(INVALID_ARGUMENT); | 756 NotifyError(INVALID_ARGUMENT); |
| 735 return; | 757 return; |
| 736 } | 758 } |
| 737 | 759 |
| 738 // We got a new input buffer from the client, map it and queue for later use. | 760 // Skip empty buffers. VaapiVDA uses empty buffer as dummy buffer for flush |
| 739 MapAndQueueNewInputBuffer(bitstream_buffer); | 761 // internally. |
| 762 if (bitstream_buffer.size() == 0) { | |
| 763 if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle())) | |
| 764 base::SharedMemory::CloseHandle(bitstream_buffer.handle()); | |
| 765 if (client_) | |
| 766 client_->NotifyEndOfBitstreamBuffer(bitstream_buffer.id()); | |
| 767 return; | |
| 768 } | |
| 740 | 769 |
| 741 base::AutoLock auto_lock(lock_); | 770 QueueInputBuffer(bitstream_buffer); |
| 742 switch (state_) { | |
| 743 case kIdle: | |
| 744 state_ = kDecoding; | |
| 745 decoder_thread_task_runner_->PostTask( | |
| 746 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::DecodeTask, | |
| 747 base::Unretained(this))); | |
| 748 break; | |
| 749 | |
| 750 case kDecoding: | |
| 751 // Decoder already running, fallthrough. | |
| 752 case kResetting: | |
| 753 // When resetting, allow accumulating bitstream buffers, so that | |
| 754 // the client can queue after-seek-buffers while we are finishing with | |
| 755 // the before-seek one. | |
| 756 break; | |
| 757 | |
| 758 default: | |
| 759 RETURN_AND_NOTIFY_ON_FAILURE( | |
| 760 false, "Decode request from client in invalid state: " << state_, | |
| 761 PLATFORM_FAILURE, ); | |
| 762 break; | |
| 763 } | |
| 764 } | 771 } |
| 765 | 772 |
| 766 void VaapiVideoDecodeAccelerator::RecycleVASurfaceID( | 773 void VaapiVideoDecodeAccelerator::RecycleVASurfaceID( |
| 767 VASurfaceID va_surface_id) { | 774 VASurfaceID va_surface_id) { |
| 768 DCHECK(task_runner_->BelongsToCurrentThread()); | 775 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 769 base::AutoLock auto_lock(lock_); | 776 base::AutoLock auto_lock(lock_); |
| 770 | 777 |
| 771 available_va_surfaces_.push_back(va_surface_id); | 778 available_va_surfaces_.push_back(va_surface_id); |
| 772 surfaces_available_.Signal(); | 779 surfaces_available_.Signal(); |
| 773 } | 780 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 817 RETURN_AND_NOTIFY_ON_FAILURE( | 824 RETURN_AND_NOTIFY_ON_FAILURE( |
| 818 picture->Allocate(output_format_), | 825 picture->Allocate(output_format_), |
| 819 "Failed to allocate memory for a VaapiPicture", PLATFORM_FAILURE, ); | 826 "Failed to allocate memory for a VaapiPicture", PLATFORM_FAILURE, ); |
| 820 output_buffers_.push(buffers[i].id()); | 827 output_buffers_.push(buffers[i].id()); |
| 821 } | 828 } |
| 822 | 829 |
| 823 available_va_surfaces_.push_back(va_surface_ids[i]); | 830 available_va_surfaces_.push_back(va_surface_ids[i]); |
| 824 surfaces_available_.Signal(); | 831 surfaces_available_.Signal(); |
| 825 } | 832 } |
| 826 | 833 |
| 827 // The resolution changing may happen while resetting or flushing. In this | 834 // Resume DecodeTask if it is still in decoding state. |
| 828 // case we do not change state and post DecodeTask(). | 835 if (state_ == kDecoding) { |
| 829 if (state_ != kResetting && state_ != kFlushing) { | |
| 830 state_ = kDecoding; | |
| 831 decoder_thread_task_runner_->PostTask( | 836 decoder_thread_task_runner_->PostTask( |
| 832 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::DecodeTask, | 837 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::DecodeTask, |
| 833 base::Unretained(this))); | 838 base::Unretained(this))); |
| 834 } | 839 } |
| 835 } | 840 } |
| 836 | 841 |
| 837 #if defined(USE_OZONE) | 842 #if defined(USE_OZONE) |
| 838 static void CloseGpuMemoryBufferHandle( | 843 static void CloseGpuMemoryBufferHandle( |
| 839 const gfx::GpuMemoryBufferHandle& handle) { | 844 const gfx::GpuMemoryBufferHandle& handle) { |
| 840 for (const auto& fd : handle.native_pixmap_handle.fds) { | 845 for (const auto& fd : handle.native_pixmap_handle.fds) { |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 901 | 906 |
| 902 --num_frames_at_client_; | 907 --num_frames_at_client_; |
| 903 TRACE_COUNTER1("Video Decoder", "Textures at client", num_frames_at_client_); | 908 TRACE_COUNTER1("Video Decoder", "Textures at client", num_frames_at_client_); |
| 904 | 909 |
| 905 output_buffers_.push(picture_buffer_id); | 910 output_buffers_.push(picture_buffer_id); |
| 906 TryOutputSurface(); | 911 TryOutputSurface(); |
| 907 } | 912 } |
| 908 | 913 |
| 909 void VaapiVideoDecodeAccelerator::FlushTask() { | 914 void VaapiVideoDecodeAccelerator::FlushTask() { |
| 910 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 915 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 916 DCHECK(curr_input_buffer_.get() && curr_input_buffer_->is_flush()); | |
| 917 | |
| 911 DVLOG(1) << "Flush task"; | 918 DVLOG(1) << "Flush task"; |
| 912 | 919 |
| 920 curr_input_buffer_.reset(); | |
| 921 --num_stream_bufs_at_decoder_; | |
| 922 TRACE_COUNTER1("Video Decoder", "Stream buffers at decoder", | |
| 923 num_stream_bufs_at_decoder_); | |
| 924 | |
| 913 // First flush all the pictures that haven't been outputted, notifying the | 925 // First flush all the pictures that haven't been outputted, notifying the |
| 914 // client to output them. | 926 // client to output them. |
| 915 bool res = decoder_->Flush(); | 927 bool res = decoder_->Flush(); |
| 916 RETURN_AND_NOTIFY_ON_FAILURE(res, "Failed flushing the decoder.", | 928 RETURN_AND_NOTIFY_ON_FAILURE(res, "Failed flushing the decoder.", |
| 917 PLATFORM_FAILURE, ); | 929 PLATFORM_FAILURE, ); |
| 918 | 930 |
| 919 // Put the decoder in idle state, ready to resume. | 931 // Put the decoder in idle state, ready to resume. |
| 920 decoder_->Reset(); | 932 decoder_->Reset(); |
| 921 | 933 |
| 922 task_runner_->PostTask( | 934 task_runner_->PostTask( |
| 923 FROM_HERE, | 935 FROM_HERE, |
| 924 base::Bind(&VaapiVideoDecodeAccelerator::FinishFlush, weak_this_)); | 936 base::Bind(&VaapiVideoDecodeAccelerator::FinishFlush, weak_this_)); |
| 925 } | 937 } |
| 926 | 938 |
| 927 void VaapiVideoDecodeAccelerator::Flush() { | 939 void VaapiVideoDecodeAccelerator::Flush() { |
| 928 DCHECK(task_runner_->BelongsToCurrentThread()); | 940 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 929 DVLOG(1) << "Got flush request"; | 941 DVLOG(1) << "Got flush request"; |
| 930 | 942 |
| 931 base::AutoLock auto_lock(lock_); | 943 // Queue a dummy buffer, which means flush. |
| 932 state_ = kFlushing; | 944 QueueInputBuffer(media::BitstreamBuffer()); |
| 933 // Queue a flush task after all existing decoding tasks to clean up. | |
| 934 decoder_thread_task_runner_->PostTask( | |
| 935 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::FlushTask, | |
| 936 base::Unretained(this))); | |
| 937 | |
| 938 input_ready_.Signal(); | |
| 939 surfaces_available_.Signal(); | |
| 940 } | 945 } |
| 941 | 946 |
| 942 void VaapiVideoDecodeAccelerator::FinishFlush() { | 947 void VaapiVideoDecodeAccelerator::FinishFlush() { |
| 943 DCHECK(task_runner_->BelongsToCurrentThread()); | 948 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 944 | 949 |
| 945 finish_flush_pending_ = false; | 950 finish_flush_pending_ = false; |
| 946 | 951 |
| 947 base::AutoLock auto_lock(lock_); | 952 base::AutoLock auto_lock(lock_); |
| 948 if (state_ != kFlushing) { | 953 if (state_ != kDecoding) { |
| 949 DCHECK_EQ(state_, kDestroying); | 954 DCHECK_EQ(state_, kDestroying); |
| 950 return; // We could've gotten destroyed already. | 955 return; // We could've gotten destroyed already. |
| 951 } | 956 } |
| 952 | 957 |
| 953 // Still waiting for textures from client to finish outputting all pending | 958 // Still waiting for textures from client to finish outputting all pending |
| 954 // frames. Try again later. | 959 // frames. Try again later. |
| 955 if (!pending_output_cbs_.empty()) { | 960 if (!pending_output_cbs_.empty()) { |
| 956 finish_flush_pending_ = true; | 961 finish_flush_pending_ = true; |
| 957 return; | 962 return; |
| 958 } | 963 } |
| 959 | 964 |
| 960 state_ = kIdle; | 965 // Resume decoding if necessary. |
| 966 if (input_buffers_.empty()) { | |
| 967 state_ = kIdle; | |
| 968 } else { | |
| 969 decoder_thread_task_runner_->PostTask( | |
| 970 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::DecodeTask, | |
| 971 base::Unretained(this))); | |
| 972 } | |
| 961 | 973 |
| 962 task_runner_->PostTask(FROM_HERE, | 974 task_runner_->PostTask(FROM_HERE, |
| 963 base::Bind(&Client::NotifyFlushDone, client_)); | 975 base::Bind(&Client::NotifyFlushDone, client_)); |
| 964 | 976 |
| 965 DVLOG(1) << "Flush finished"; | 977 DVLOG(1) << "Flush finished"; |
| 966 } | 978 } |
| 967 | 979 |
| 968 void VaapiVideoDecodeAccelerator::ResetTask() { | 980 void VaapiVideoDecodeAccelerator::ResetTask() { |
| 969 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); | 981 DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| 970 DVLOG(1) << "ResetTask"; | 982 DVLOG(1) << "ResetTask"; |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 990 DCHECK(task_runner_->BelongsToCurrentThread()); | 1002 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 991 DVLOG(1) << "Got reset request"; | 1003 DVLOG(1) << "Got reset request"; |
| 992 | 1004 |
| 993 // This will make any new decode tasks exit early. | 1005 // This will make any new decode tasks exit early. |
| 994 base::AutoLock auto_lock(lock_); | 1006 base::AutoLock auto_lock(lock_); |
| 995 state_ = kResetting; | 1007 state_ = kResetting; |
| 996 finish_flush_pending_ = false; | 1008 finish_flush_pending_ = false; |
| 997 | 1009 |
| 998 // Drop all remaining input buffers, if present. | 1010 // Drop all remaining input buffers, if present. |
| 999 while (!input_buffers_.empty()) { | 1011 while (!input_buffers_.empty()) { |
| 1000 task_runner_->PostTask( | 1012 const auto& input_buffer = input_buffers_.front(); |
| 1001 FROM_HERE, base::Bind(&Client::NotifyEndOfBitstreamBuffer, client_, | 1013 if (!input_buffer->is_flush()) |
|
Pawel Osciak
2017/01/24 07:10:33
Perhaps we could have this in destructor of InputB
kcwu
2017/01/24 07:54:23
If doing so, InputBuffer would need to keep refere
Pawel Osciak
2017/01/24 09:19:16
Acknowledged.
| |
| 1002 input_buffers_.front()->id)); | 1014 task_runner_->PostTask( |
| 1015 FROM_HERE, base::Bind(&Client::NotifyEndOfBitstreamBuffer, client_, | |
| 1016 input_buffer->id)); | |
| 1003 input_buffers_.pop(); | 1017 input_buffers_.pop(); |
| 1004 } | 1018 } |
| 1005 | 1019 |
| 1006 decoder_thread_task_runner_->PostTask( | 1020 decoder_thread_task_runner_->PostTask( |
| 1007 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::ResetTask, | 1021 FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::ResetTask, |
| 1008 base::Unretained(this))); | 1022 base::Unretained(this))); |
| 1009 | 1023 |
| 1010 input_ready_.Signal(); | 1024 input_ready_.Signal(); |
| 1011 surfaces_available_.Signal(); | 1025 surfaces_available_.Signal(); |
| 1012 } | 1026 } |
| (...skipping 867 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1880 return vaapi_pic->dec_surface(); | 1894 return vaapi_pic->dec_surface(); |
| 1881 } | 1895 } |
| 1882 | 1896 |
| 1883 // static | 1897 // static |
| 1884 VideoDecodeAccelerator::SupportedProfiles | 1898 VideoDecodeAccelerator::SupportedProfiles |
| 1885 VaapiVideoDecodeAccelerator::GetSupportedProfiles() { | 1899 VaapiVideoDecodeAccelerator::GetSupportedProfiles() { |
| 1886 return VaapiWrapper::GetSupportedDecodeProfiles(); | 1900 return VaapiWrapper::GetSupportedDecodeProfiles(); |
| 1887 } | 1901 } |
| 1888 | 1902 |
| 1889 } // namespace media | 1903 } // namespace media |
| OLD | NEW |