Index: media/gpu/dxva_video_decode_accelerator_win.cc |
diff --git a/media/gpu/dxva_video_decode_accelerator_win.cc b/media/gpu/dxva_video_decode_accelerator_win.cc |
index cf841fa5342748c5adc1beba4a9b9738bc7b6d99..0e0e9d25c06da967cf7a61157557785462b49b6f 100644 |
--- a/media/gpu/dxva_video_decode_accelerator_win.cc |
+++ b/media/gpu/dxva_video_decode_accelerator_win.cc |
@@ -592,6 +592,7 @@ DXVAVideoDecodeAccelerator::DXVAVideoDecodeAccelerator( |
using_angle_device_(false), |
enable_accelerated_vpx_decode_( |
gpu_preferences.enable_accelerated_vpx_decode), |
+ processing_config_changed_(false), |
weak_this_factory_(this) { |
weak_ptr_ = weak_this_factory_.GetWeakPtr(); |
memset(&input_stream_info_, 0, sizeof(input_stream_info_)); |
@@ -927,7 +928,7 @@ void DXVAVideoDecodeAccelerator::AssignPictureBuffers( |
} |
ProcessPendingSamples(); |
- if (pending_flush_) { |
+ if (pending_flush_ || processing_config_changed_) { |
decoder_thread_task_runner_->PostTask( |
FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal, |
base::Unretained(this))); |
@@ -1020,7 +1021,7 @@ void DXVAVideoDecodeAccelerator::WaitForOutputBuffer(int32_t picture_buffer_id, |
PLATFORM_FAILURE, ); |
ProcessPendingSamples(); |
- if (pending_flush_) { |
+ if (pending_flush_ || processing_config_changed_) { |
decoder_thread_task_runner_->PostTask( |
FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal, |
base::Unretained(this))); |
@@ -1041,6 +1042,19 @@ void DXVAVideoDecodeAccelerator::Flush() { |
pending_flush_ = true; |
+ // If we receive a flush while processing a video stream config change, then |
+ // we treat this as a regular flush, i.e we process queued decode packets, |
+ // etc. |
+ // We are resetting the processing_config_changed_ flag here which means that |
+ // we won't be tearing down the decoder instance and recreating it to handle |
+ // the changed configuration. The expectation here is that after the decoder |
+ // is drained it should be able to handle a changed configuration. |
+ // TODO(ananta) |
+ // If a flush is sufficient to get the decoder to process video stream config |
+ // changes correctly, then we don't need to tear down the decoder instance |
+ // and recreate it. Check if this is indeed the case. |
+ processing_config_changed_ = false; |
+ |
decoder_thread_task_runner_->PostTask( |
FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal, |
base::Unretained(this))); |
@@ -1848,7 +1862,7 @@ void DXVAVideoDecodeAccelerator::Invalidate() { |
query_.Release(); |
} |
} |
- |
+ sent_drain_message_ = false; |
SetState(kUninitialized); |
} |
@@ -1925,6 +1939,8 @@ void DXVAVideoDecodeAccelerator::DecodePendingInputBuffers() { |
TRACE_EVENT0("media", |
"DXVAVideoDecodeAccelerator::DecodePendingInputBuffers"); |
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); |
+ DCHECK(!processing_config_changed_); |
+ |
State state = GetState(); |
RETURN_AND_NOTIFY_ON_FAILURE((state != kUninitialized), |
"Invalid state: " << state, ILLEGAL_STATE, ); |
@@ -1952,7 +1968,9 @@ void DXVAVideoDecodeAccelerator::FlushInternal() { |
// First drain the pending input because once the drain message is sent below, |
// the decoder will ignore further input until it's drained. |
- if (!pending_input_buffers_.empty()) { |
+ // If we are processing a video configuration change, then we should just |
+ // the drain the decoder. |
+ if (!processing_config_changed_ && !pending_input_buffers_.empty()) { |
decoder_thread_task_runner_->PostTask( |
FROM_HERE, |
base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers, |
@@ -1980,11 +1998,18 @@ void DXVAVideoDecodeAccelerator::FlushInternal() { |
if (OutputSamplesPresent()) |
return; |
- SetState(kFlushing); |
+ if (!processing_config_changed_) { |
+ SetState(kFlushing); |
- main_thread_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::NotifyFlushDone, |
- weak_this_factory_.GetWeakPtr())); |
+ main_thread_task_runner_->PostTask( |
+ FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::NotifyFlushDone, |
+ weak_this_factory_.GetWeakPtr())); |
+ } else { |
+ processing_config_changed_ = false; |
+ main_thread_task_runner_->PostTask( |
+ FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::ConfigChanged, |
+ weak_this_factory_.GetWeakPtr(), config_)); |
+ } |
SetState(kNormal); |
} |
@@ -2010,11 +2035,11 @@ void DXVAVideoDecodeAccelerator::DecodeInternal( |
RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to check video stream config", |
PLATFORM_FAILURE, ); |
+ processing_config_changed_ = config_changed; |
+ |
if (config_changed) { |
pending_input_buffers_.push_back(sample); |
- main_thread_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::ConfigChanged, |
- weak_this_factory_.GetWeakPtr(), config_)); |
+ FlushInternal(); |
return; |
} |
@@ -2256,7 +2281,7 @@ void DXVAVideoDecodeAccelerator::CopySurfaceComplete( |
pending_output_samples_.pop_front(); |
} |
- if (pending_flush_) { |
+ if (pending_flush_ || processing_config_changed_) { |
decoder_thread_task_runner_->PostTask( |
FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal, |
base::Unretained(this))); |
@@ -2308,7 +2333,7 @@ void DXVAVideoDecodeAccelerator::BindPictureBufferToSample( |
pending_output_samples_.pop_front(); |
} |
- if (pending_flush_) { |
+ if (pending_flush_ || processing_config_changed_) { |
decoder_thread_task_runner_->PostTask( |
FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal, |
base::Unretained(this))); |