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