Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(807)

Unified Diff: media/gpu/vaapi_video_decode_accelerator.cc

Issue 2642623002: Fix Vaapi VDA flush handling during resolution change (Closed)
Patch Set: fix compile due to style check Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/gpu/vaapi_video_decode_accelerator.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/gpu/vaapi_video_decode_accelerator.cc
diff --git a/media/gpu/vaapi_video_decode_accelerator.cc b/media/gpu/vaapi_video_decode_accelerator.cc
index a119f0fd16b039ddefc831c5be2fef71e14837de..21b5d3ebc6c7bf661bace376176e547619c3ec27 100644
--- a/media/gpu/vaapi_video_decode_accelerator.cc
+++ b/media/gpu/vaapi_video_decode_accelerator.cc
@@ -268,9 +268,8 @@ class VaapiVideoDecodeAccelerator::VaapiVP9Accelerator
DISALLOW_COPY_AND_ASSIGN(VaapiVP9Accelerator);
};
-VaapiVideoDecodeAccelerator::InputBuffer::InputBuffer() : id(0) {}
-
-VaapiVideoDecodeAccelerator::InputBuffer::~InputBuffer() {}
+VaapiVideoDecodeAccelerator::InputBuffer::InputBuffer() = default;
+VaapiVideoDecodeAccelerator::InputBuffer::~InputBuffer() = default;
void VaapiVideoDecodeAccelerator::NotifyError(Error error) {
if (!task_runner_->BelongsToCurrentThread()) {
@@ -461,41 +460,62 @@ void VaapiVideoDecodeAccelerator::TryOutputSurface() {
FinishFlush();
}
-void VaapiVideoDecodeAccelerator::MapAndQueueNewInputBuffer(
+void VaapiVideoDecodeAccelerator::QueueInputBuffer(
const BitstreamBuffer& bitstream_buffer) {
DCHECK(task_runner_->BelongsToCurrentThread());
- TRACE_EVENT1("Video Decoder", "MapAndQueueNewInputBuffer", "input_id",
+ TRACE_EVENT1("Video Decoder", "QueueInputBuffer", "input_id",
bitstream_buffer.id());
- DVLOG(4) << "Mapping new input buffer id: " << bitstream_buffer.id()
+ DVLOG(4) << "Queueing new input buffer id: " << bitstream_buffer.id()
<< " size: " << (int)bitstream_buffer.size();
- std::unique_ptr<SharedMemoryRegion> shm(
- new SharedMemoryRegion(bitstream_buffer, true));
-
- // Skip empty buffers.
+ base::AutoLock auto_lock(lock_);
if (bitstream_buffer.size() == 0) {
- if (client_)
- client_->NotifyEndOfBitstreamBuffer(bitstream_buffer.id());
- return;
+ // Dummy buffer for flush.
+ DCHECK(!base::SharedMemory::IsHandleValid(bitstream_buffer.handle()));
+ input_buffers_.push(make_linked_ptr(new InputBuffer()));
+ } else {
+ std::unique_ptr<SharedMemoryRegion> shm(
+ new SharedMemoryRegion(bitstream_buffer, true));
+
+ RETURN_AND_NOTIFY_ON_FAILURE(shm->Map(), "Failed to map input buffer",
+ UNREADABLE_INPUT, );
+
+ linked_ptr<InputBuffer> input_buffer(new InputBuffer());
+ input_buffer->shm = std::move(shm);
+ input_buffer->id = bitstream_buffer.id();
+ input_buffers_.push(input_buffer);
+ ++num_stream_bufs_at_decoder_;
+ TRACE_COUNTER1("Video Decoder", "Stream buffers at decoder",
+ num_stream_bufs_at_decoder_);
}
- RETURN_AND_NOTIFY_ON_FAILURE(shm->Map(), "Failed to map input buffer",
- UNREADABLE_INPUT, );
+ input_ready_.Signal();
- base::AutoLock auto_lock(lock_);
+ switch (state_) {
+ case kIdle:
+ state_ = kDecoding;
+ decoder_thread_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::DecodeTask,
+ base::Unretained(this)));
+ break;
- // Set up a new input buffer and queue it for later.
- linked_ptr<InputBuffer> input_buffer(new InputBuffer());
- input_buffer->shm = std::move(shm);
- input_buffer->id = bitstream_buffer.id();
+ case kDecoding:
+ // Decoder already running.
+ break;
- ++num_stream_bufs_at_decoder_;
- TRACE_COUNTER1("Video Decoder", "Stream buffers at decoder",
- num_stream_bufs_at_decoder_);
+ case kResetting:
+ // When resetting, allow accumulating bitstream buffers, so that
+ // the client can queue after-seek-buffers while we are finishing with
+ // the before-seek one.
+ break;
- input_buffers_.push(input_buffer);
- input_ready_.Signal();
+ default:
+ LOG(ERROR) << "Decode/Flush request from client in invalid state: "
+ << state_;
+ NotifyError(PLATFORM_FAILURE);
+ break;
+ }
}
bool VaapiVideoDecodeAccelerator::GetInputBuffer_Locked() {
@@ -514,12 +534,6 @@ bool VaapiVideoDecodeAccelerator::GetInputBuffer_Locked() {
// We could have got woken up in a different state or never got to sleep
// due to current state; check for that.
switch (state_) {
- case kFlushing:
- // Here we are only interested in finishing up decoding buffers that are
- // already queued up. Otherwise will stop decoding.
- if (input_buffers_.empty())
- return false;
- // else fallthrough
case kDecoding:
case kIdle:
DCHECK(!input_buffers_.empty());
@@ -527,12 +541,17 @@ bool VaapiVideoDecodeAccelerator::GetInputBuffer_Locked() {
curr_input_buffer_ = input_buffers_.front();
input_buffers_.pop();
- DVLOG(4) << "New current bitstream buffer, id: " << curr_input_buffer_->id
- << " size: " << curr_input_buffer_->shm->size();
+ if (curr_input_buffer_->is_flush()) {
+ DVLOG(4) << "New flush buffer";
+ } else {
+ DVLOG(4) << "New current bitstream buffer, id: "
+ << curr_input_buffer_->id
+ << " size: " << curr_input_buffer_->shm->size();
- decoder_->SetStream(
- static_cast<uint8_t*>(curr_input_buffer_->shm->memory()),
- curr_input_buffer_->shm->size());
+ decoder_->SetStream(
+ static_cast<uint8_t*>(curr_input_buffer_->shm->memory()),
+ curr_input_buffer_->shm->size());
+ }
return true;
default:
@@ -565,11 +584,11 @@ bool VaapiVideoDecodeAccelerator::WaitForSurfaces_Locked() {
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
while (available_va_surfaces_.empty() &&
- (state_ == kDecoding || state_ == kFlushing || state_ == kIdle)) {
+ (state_ == kDecoding || state_ == kIdle)) {
surfaces_available_.Wait();
}
- if (state_ != kDecoding && state_ != kFlushing && state_ != kIdle)
+ if (state_ != kDecoding && state_ != kIdle)
return false;
return true;
@@ -591,6 +610,11 @@ void VaapiVideoDecodeAccelerator::DecodeTask() {
while (GetInputBuffer_Locked()) {
DCHECK(curr_input_buffer_.get());
+ if (curr_input_buffer_->is_flush()) {
+ FlushTask();
+ break;
+ }
+
AcceleratedVideoDecoder::DecodeResult res;
{
// We are OK releasing the lock here, as decoder never calls our methods
@@ -735,32 +759,17 @@ void VaapiVideoDecodeAccelerator::Decode(
return;
}
- // We got a new input buffer from the client, map it and queue for later use.
- MapAndQueueNewInputBuffer(bitstream_buffer);
-
- base::AutoLock auto_lock(lock_);
- switch (state_) {
- case kIdle:
- state_ = kDecoding;
- decoder_thread_task_runner_->PostTask(
- FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::DecodeTask,
- base::Unretained(this)));
- break;
-
- case kDecoding:
- // Decoder already running, fallthrough.
- case kResetting:
- // When resetting, allow accumulating bitstream buffers, so that
- // the client can queue after-seek-buffers while we are finishing with
- // the before-seek one.
- break;
-
- default:
- RETURN_AND_NOTIFY_ON_FAILURE(
- false, "Decode request from client in invalid state: " << state_,
- PLATFORM_FAILURE, );
- break;
+ // Skip empty buffers. VaapiVDA uses empty buffer as dummy buffer for flush
+ // internally.
+ if (bitstream_buffer.size() == 0) {
+ if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle()))
+ base::SharedMemory::CloseHandle(bitstream_buffer.handle());
+ if (client_)
+ client_->NotifyEndOfBitstreamBuffer(bitstream_buffer.id());
+ return;
}
+
+ QueueInputBuffer(bitstream_buffer);
}
void VaapiVideoDecodeAccelerator::RecycleVASurfaceID(
@@ -824,10 +833,8 @@ void VaapiVideoDecodeAccelerator::AssignPictureBuffers(
surfaces_available_.Signal();
}
- // The resolution changing may happen while resetting or flushing. In this
- // case we do not change state and post DecodeTask().
- if (state_ != kResetting && state_ != kFlushing) {
- state_ = kDecoding;
+ // Resume DecodeTask if it is still in decoding state.
+ if (state_ == kDecoding) {
decoder_thread_task_runner_->PostTask(
FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::DecodeTask,
base::Unretained(this)));
@@ -908,8 +915,12 @@ void VaapiVideoDecodeAccelerator::ReusePictureBuffer(
void VaapiVideoDecodeAccelerator::FlushTask() {
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
+ DCHECK(curr_input_buffer_.get() && curr_input_buffer_->is_flush());
+
DVLOG(1) << "Flush task";
+ curr_input_buffer_.reset();
+
// First flush all the pictures that haven't been outputted, notifying the
// client to output them.
bool res = decoder_->Flush();
@@ -928,15 +939,8 @@ void VaapiVideoDecodeAccelerator::Flush() {
DCHECK(task_runner_->BelongsToCurrentThread());
DVLOG(1) << "Got flush request";
- base::AutoLock auto_lock(lock_);
- state_ = kFlushing;
- // Queue a flush task after all existing decoding tasks to clean up.
- decoder_thread_task_runner_->PostTask(
- FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::FlushTask,
- base::Unretained(this)));
-
- input_ready_.Signal();
- surfaces_available_.Signal();
+ // Queue a dummy buffer, which means flush.
+ QueueInputBuffer(media::BitstreamBuffer());
}
void VaapiVideoDecodeAccelerator::FinishFlush() {
@@ -945,7 +949,7 @@ void VaapiVideoDecodeAccelerator::FinishFlush() {
finish_flush_pending_ = false;
base::AutoLock auto_lock(lock_);
- if (state_ != kFlushing) {
+ if (state_ != kDecoding) {
DCHECK_EQ(state_, kDestroying);
return; // We could've gotten destroyed already.
}
@@ -957,7 +961,14 @@ void VaapiVideoDecodeAccelerator::FinishFlush() {
return;
}
- state_ = kIdle;
+ // Resume decoding if necessary.
+ if (input_buffers_.empty()) {
+ state_ = kIdle;
+ } else {
+ decoder_thread_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::DecodeTask,
+ base::Unretained(this)));
+ }
task_runner_->PostTask(FROM_HERE,
base::Bind(&Client::NotifyFlushDone, client_));
@@ -997,9 +1008,11 @@ void VaapiVideoDecodeAccelerator::Reset() {
// Drop all remaining input buffers, if present.
while (!input_buffers_.empty()) {
- task_runner_->PostTask(
- FROM_HERE, base::Bind(&Client::NotifyEndOfBitstreamBuffer, client_,
- input_buffers_.front()->id));
+ const auto& input_buffer = input_buffers_.front();
+ if (!input_buffer->is_flush())
+ task_runner_->PostTask(
+ FROM_HERE, base::Bind(&Client::NotifyEndOfBitstreamBuffer, client_,
+ input_buffer->id));
input_buffers_.pop();
}
« no previous file with comments | « media/gpu/vaapi_video_decode_accelerator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698