Chromium Code Reviews| 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..4640c83cc10de48cbabab07c8242167225ff1da4 100644 |
| --- a/media/gpu/vaapi_video_decode_accelerator.cc |
| +++ b/media/gpu/vaapi_video_decode_accelerator.cc |
| @@ -268,7 +268,7 @@ class VaapiVideoDecodeAccelerator::VaapiVP9Accelerator |
| DISALLOW_COPY_AND_ASSIGN(VaapiVP9Accelerator); |
| }; |
| -VaapiVideoDecodeAccelerator::InputBuffer::InputBuffer() : id(0) {} |
| +VaapiVideoDecodeAccelerator::InputBuffer::InputBuffer() {} |
| VaapiVideoDecodeAccelerator::InputBuffer::~InputBuffer() {} |
| @@ -461,7 +461,7 @@ void VaapiVideoDecodeAccelerator::TryOutputSurface() { |
| FinishFlush(); |
| } |
| -void VaapiVideoDecodeAccelerator::MapAndQueueNewInputBuffer( |
| +bool VaapiVideoDecodeAccelerator::MapAndQueueNewInputBuffer( |
| const BitstreamBuffer& bitstream_buffer) { |
| DCHECK(task_runner_->BelongsToCurrentThread()); |
| TRACE_EVENT1("Video Decoder", "MapAndQueueNewInputBuffer", "input_id", |
| @@ -477,14 +477,22 @@ void VaapiVideoDecodeAccelerator::MapAndQueueNewInputBuffer( |
| if (bitstream_buffer.size() == 0) { |
| if (client_) |
| client_->NotifyEndOfBitstreamBuffer(bitstream_buffer.id()); |
| - return; |
| + return true; |
| } |
| RETURN_AND_NOTIFY_ON_FAILURE(shm->Map(), "Failed to map input buffer", |
| - UNREADABLE_INPUT, ); |
| + UNREADABLE_INPUT, false); |
| base::AutoLock auto_lock(lock_); |
| + if (IsFlushPending_Locked()) { |
| + LOG(ERROR) << "Shouldn't enqueue more input before FlushDone"; |
| + if (client_) |
| + client_->NotifyEndOfBitstreamBuffer(bitstream_buffer.id()); |
| + NotifyError(PLATFORM_FAILURE); |
| + return false; |
| + } |
| + |
| // Set up a new input buffer and queue it for later. |
| linked_ptr<InputBuffer> input_buffer(new InputBuffer()); |
| input_buffer->shm = std::move(shm); |
| @@ -496,6 +504,7 @@ void VaapiVideoDecodeAccelerator::MapAndQueueNewInputBuffer( |
| input_buffers_.push(input_buffer); |
| input_ready_.Signal(); |
| + return true; |
| } |
| bool VaapiVideoDecodeAccelerator::GetInputBuffer_Locked() { |
| @@ -514,12 +523,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 +530,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_->dummy_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,16 +573,30 @@ 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; |
| } |
| +bool VaapiVideoDecodeAccelerator::IsFlushPending_Locked() { |
|
Owen Lin
2017/01/19 07:39:16
I am thinking maybe we can get rid of this functio
kcwu
2017/01/19 08:26:10
It's intentional to reject them since this is inva
Owen Lin
2017/01/20 02:20:06
Yes, I see your point and it makes totally sense.
|
| + DCHECK(task_runner_->BelongsToCurrentThread()); |
| + |
| + if (finish_flush_pending_) |
| + return true; |
| + |
| + if (curr_input_buffer_.get() && curr_input_buffer_->dummy_flush) |
| + return true; |
| + |
| + // Checking last element of |input_buffers_| is enough because no more |
| + // buffers will be queued after flush. |
| + return !input_buffers_.empty() && input_buffers_.back()->dummy_flush; |
| +} |
| + |
| void VaapiVideoDecodeAccelerator::DecodeTask() { |
| DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| TRACE_EVENT0("Video Decoder", "VAVDA::DecodeTask"); |
| @@ -591,6 +613,11 @@ void VaapiVideoDecodeAccelerator::DecodeTask() { |
| while (GetInputBuffer_Locked()) { |
| DCHECK(curr_input_buffer_.get()); |
| + if (curr_input_buffer_->dummy_flush) { |
| + FlushTask(); |
| + break; |
| + } |
| + |
| AcceleratedVideoDecoder::DecodeResult res; |
| { |
| // We are OK releasing the lock here, as decoder never calls our methods |
| @@ -736,7 +763,8 @@ void VaapiVideoDecodeAccelerator::Decode( |
| } |
| // We got a new input buffer from the client, map it and queue for later use. |
| - MapAndQueueNewInputBuffer(bitstream_buffer); |
| + if (!MapAndQueueNewInputBuffer(bitstream_buffer)) |
| + return; |
| base::AutoLock auto_lock(lock_); |
| switch (state_) { |
| @@ -824,10 +852,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 +934,15 @@ void VaapiVideoDecodeAccelerator::ReusePictureBuffer( |
| void VaapiVideoDecodeAccelerator::FlushTask() { |
| DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
| + DCHECK(input_buffers_.empty()) << "Input buffers should be empty because" |
|
Owen Lin
2017/01/19 07:39:16
It looks like a comment instead of what we should
kcwu
2017/01/20 07:49:03
Code removed.
|
| + << " the client cannot queue buffers before" |
| + << " FlushDone"; |
| + DCHECK(curr_input_buffer_.get() && curr_input_buffer_->dummy_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(); |
| @@ -929,11 +962,40 @@ void VaapiVideoDecodeAccelerator::Flush() { |
| 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))); |
| + if (IsFlushPending_Locked()) { |
| + LOG(ERROR) << "Shouldn't Flush again before FlushDone"; |
| + NotifyError(PLATFORM_FAILURE); |
| + return; |
| + } |
| + |
| + switch (state_) { |
| + case kIdle: |
| + state_ = kDecoding; |
| + decoder_thread_task_runner_->PostTask( |
| + FROM_HERE, base::Bind(&VaapiVideoDecodeAccelerator::DecodeTask, |
|
Owen Lin
2017/01/19 07:39:16
Can we extract the common part of this function an
kcwu
2017/01/19 08:26:10
Regarding to Flush() to use empty buffer, I don't
Owen Lin
2017/01/20 02:20:06
First, empty buffer is not invalid, we do accept e
kcwu
2017/01/20 07:49:03
Done.
|
| + base::Unretained(this))); |
| + break; |
| + |
| + case kDecoding: |
| + // Decoder already running. |
| + break; |
| + |
| + 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; |
| + } |
| + |
| + linked_ptr<InputBuffer> input_buffer(new InputBuffer()); |
| + input_buffer->dummy_flush = true; |
| + input_buffers_.push(input_buffer); |
| input_ready_.Signal(); |
| surfaces_available_.Signal(); |
| @@ -945,7 +1007,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. |
| } |
| @@ -997,9 +1059,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->dummy_flush) |
| + task_runner_->PostTask( |
| + FROM_HERE, base::Bind(&Client::NotifyEndOfBitstreamBuffer, client_, |
| + input_buffer->id)); |
| input_buffers_.pop(); |
| } |