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

Unified Diff: content/common/gpu/media/dxva_video_decode_accelerator.cc

Issue 765533005: Move the DXVA decoder off the GPU thread. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Code review comments Created 6 years 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 | « content/common/gpu/media/dxva_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: content/common/gpu/media/dxva_video_decode_accelerator.cc
diff --git a/content/common/gpu/media/dxva_video_decode_accelerator.cc b/content/common/gpu/media/dxva_video_decode_accelerator.cc
index 2fc53e7188acfd223d8cb847dd96e2b866adc4c9..9485c598b2042864b3035044d5b5d1140d24c118 100644
--- a/content/common/gpu/media/dxva_video_decode_accelerator.cc
+++ b/content/common/gpu/media/dxva_video_decode_accelerator.cc
@@ -487,8 +487,10 @@ DXVAVideoDecodeAccelerator::DXVAVideoDecodeAccelerator(
pictures_requested_(false),
inputs_before_decode_(0),
make_context_current_(make_context_current),
+ codec_(media::kUnknownVideoCodec),
+ decoder_thread_("DXVAVideoDecoderThread"),
weak_this_factory_(this),
- codec_(media::kUnknownVideoCodec) {
+ weak_ptr_(weak_this_factory_.GetWeakPtr()) {
memset(&input_stream_info_, 0, sizeof(input_stream_info_));
memset(&output_stream_info_, 0, sizeof(output_stream_info_));
}
@@ -498,11 +500,11 @@ DXVAVideoDecodeAccelerator::~DXVAVideoDecodeAccelerator() {
}
bool DXVAVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile,
- Client* client) {
- DCHECK(CalledOnValidThread());
-
+ Client* client) {
client_ = client;
+ main_thread_task_runner_ = base::MessageLoop::current()->task_runner();
+
// Not all versions of Windows 7 and later include Media Foundation DLLs.
// Instead of crashing while delay loading the DLL when calling MFStartup()
// below, probe whether we can successfully load the DLL now.
@@ -511,8 +513,8 @@ bool DXVAVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile,
HMODULE mfplat_dll = ::LoadLibrary(L"MFPlat.dll");
RETURN_ON_FAILURE(mfplat_dll, "MFPlat.dll is required for decoding", false);
- // TODO(ananta)
- // H264PROFILE_HIGH video decoding is janky at times. Needs more
+ // TODO(ananta)
+ // H264PROFILE_HIGH video decoding is janky at times. Needs more
// investigation. http://crbug.com/426707
if (profile != media::H264PROFILE_BASELINE &&
profile != media::H264PROFILE_MAIN &&
@@ -528,8 +530,9 @@ bool DXVAVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile,
PLATFORM_FAILURE,
false);
- RETURN_AND_NOTIFY_ON_FAILURE((state_ == kUninitialized),
- "Initialize: invalid state: " << state_, ILLEGAL_STATE, false);
+ State state = GetState();
+ RETURN_AND_NOTIFY_ON_FAILURE((state == kUninitialized),
+ "Initialize: invalid state: " << state, ILLEGAL_STATE, false);
HRESULT hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "MFStartup failed.", PLATFORM_FAILURE,
@@ -556,17 +559,20 @@ bool DXVAVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile,
"Send MFT_MESSAGE_NOTIFY_START_OF_STREAM notification failed",
PLATFORM_FAILURE, false);
- state_ = kNormal;
+ SetState(kNormal);
+
+ StartDecoderThread();
return true;
}
void DXVAVideoDecodeAccelerator::Decode(
const media::BitstreamBuffer& bitstream_buffer) {
- DCHECK(CalledOnValidThread());
+ DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
- RETURN_AND_NOTIFY_ON_FAILURE((state_ == kNormal || state_ == kStopped ||
- state_ == kFlushing),
- "Invalid state: " << state_, ILLEGAL_STATE,);
+ State state = GetState();
+ RETURN_AND_NOTIFY_ON_FAILURE((state == kNormal || state == kStopped ||
+ state == kFlushing),
+ "Invalid state: " << state, ILLEGAL_STATE,);
base::win::ScopedComPtr<IMFSample> sample;
sample.Attach(CreateSampleFromInputBuffer(bitstream_buffer,
@@ -578,15 +584,19 @@ void DXVAVideoDecodeAccelerator::Decode(
RETURN_AND_NOTIFY_ON_HR_FAILURE(sample->SetSampleTime(bitstream_buffer.id()),
"Failed to associate input buffer id with sample", PLATFORM_FAILURE,);
- DecodeInternal(sample);
+ decoder_thread_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&DXVAVideoDecodeAccelerator::DecodeInternal,
+ base::Unretained(this), sample));
}
void DXVAVideoDecodeAccelerator::AssignPictureBuffers(
const std::vector<media::PictureBuffer>& buffers) {
- DCHECK(CalledOnValidThread());
+ DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
- RETURN_AND_NOTIFY_ON_FAILURE((state_ != kUninitialized),
- "Invalid state: " << state_, ILLEGAL_STATE,);
+ State state = GetState();
+ RETURN_AND_NOTIFY_ON_FAILURE((state != kUninitialized),
+ "Invalid state: " << state, ILLEGAL_STATE,);
RETURN_AND_NOTIFY_ON_FAILURE((kNumPictureBuffers == buffers.size()),
"Failed to provide requested picture buffers. (Got " << buffers.size() <<
", requested " << kNumPictureBuffers << ")", INVALID_ARGUMENT,);
@@ -605,16 +615,22 @@ void DXVAVideoDecodeAccelerator::AssignPictureBuffers(
DCHECK(inserted);
}
ProcessPendingSamples();
- if (state_ == kFlushing && pending_output_samples_.empty())
- FlushInternal();
+
+ if (state == kFlushing) {
+ decoder_thread_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal,
+ base::Unretained(this)));
+ }
}
void DXVAVideoDecodeAccelerator::ReusePictureBuffer(
int32 picture_buffer_id) {
- DCHECK(CalledOnValidThread());
+ DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
- RETURN_AND_NOTIFY_ON_FAILURE((state_ != kUninitialized),
- "Invalid state: " << state_, ILLEGAL_STATE,);
+ State state = GetState();
+ RETURN_AND_NOTIFY_ON_FAILURE((state != kUninitialized),
+ "Invalid state: " << state, ILLEGAL_STATE,);
if (output_picture_buffers_.empty() && stale_output_picture_buffers_.empty())
return;
@@ -630,65 +646,75 @@ void DXVAVideoDecodeAccelerator::ReusePictureBuffer(
it = stale_output_picture_buffers_.find(picture_buffer_id);
RETURN_AND_NOTIFY_ON_FAILURE(it != stale_output_picture_buffers_.end(),
"Invalid picture id: " << picture_buffer_id, INVALID_ARGUMENT,);
- base::MessageLoop::current()->PostTask(FROM_HERE,
+ main_thread_task_runner_->PostTask(
+ FROM_HERE,
base::Bind(&DXVAVideoDecodeAccelerator::DeferredDismissStaleBuffer,
- weak_this_factory_.GetWeakPtr(), picture_buffer_id));
+ weak_this_factory_.GetWeakPtr(), picture_buffer_id));
return;
}
it->second->ReusePictureBuffer();
ProcessPendingSamples();
- if (state_ == kFlushing && pending_output_samples_.empty())
- FlushInternal();
+ if (state == kFlushing) {
+ decoder_thread_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal,
+ base::Unretained(this)));
+ }
}
void DXVAVideoDecodeAccelerator::Flush() {
- DCHECK(CalledOnValidThread());
+ DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
DVLOG(1) << "DXVAVideoDecodeAccelerator::Flush";
- RETURN_AND_NOTIFY_ON_FAILURE((state_ == kNormal || state_ == kStopped),
- "Unexpected decoder state: " << state_, ILLEGAL_STATE,);
+ State state = GetState();
+ RETURN_AND_NOTIFY_ON_FAILURE((state == kNormal || state == kStopped),
+ "Unexpected decoder state: " << state, ILLEGAL_STATE,);
- state_ = kFlushing;
+ SetState(kFlushing);
RETURN_AND_NOTIFY_ON_FAILURE(SendMFTMessage(MFT_MESSAGE_COMMAND_DRAIN, 0),
"Failed to send drain message", PLATFORM_FAILURE,);
- if (!pending_output_samples_.empty())
- return;
-
- FlushInternal();
+ decoder_thread_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal,
+ base::Unretained(this)));
}
void DXVAVideoDecodeAccelerator::Reset() {
- DCHECK(CalledOnValidThread());
+ DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
DVLOG(1) << "DXVAVideoDecodeAccelerator::Reset";
- RETURN_AND_NOTIFY_ON_FAILURE((state_ == kNormal || state_ == kStopped),
- "Reset: invalid state: " << state_, ILLEGAL_STATE,);
-
- state_ = kResetting;
-
- pending_output_samples_.clear();
-
- NotifyInputBuffersDropped();
-
- RETURN_AND_NOTIFY_ON_FAILURE(SendMFTMessage(MFT_MESSAGE_COMMAND_FLUSH, 0),
- "Reset: Failed to send message.", PLATFORM_FAILURE,);
-
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&DXVAVideoDecodeAccelerator::NotifyResetDone,
- weak_this_factory_.GetWeakPtr()));
-
- state_ = DXVAVideoDecodeAccelerator::kNormal;
+ State state = GetState();
+ RETURN_AND_NOTIFY_ON_FAILURE((state == kNormal || state == kStopped),
+ "Reset: invalid state: " << state, ILLEGAL_STATE,);
+
+ decoder_thread_.Stop();
+
+ SetState(kResetting);
+
+ pending_output_samples_.clear();
+
+ NotifyInputBuffersDropped();
+
+ RETURN_AND_NOTIFY_ON_FAILURE(SendMFTMessage(MFT_MESSAGE_COMMAND_FLUSH, 0),
+ "Reset: Failed to send message.", PLATFORM_FAILURE,);
+
+ main_thread_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&DXVAVideoDecodeAccelerator::NotifyResetDone,
+ weak_this_factory_.GetWeakPtr()));
+
+ StartDecoderThread();
+ SetState(kNormal);
}
void DXVAVideoDecodeAccelerator::Destroy() {
- DCHECK(CalledOnValidThread());
+ DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
Invalidate();
delete this;
}
@@ -929,11 +955,13 @@ bool DXVAVideoDecodeAccelerator::GetStreamsInfoAndBufferReqs() {
}
void DXVAVideoDecodeAccelerator::DoDecode() {
+ DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
// This function is also called from FlushInternal in a loop which could
// result in the state transitioning to kStopped due to no decoded output.
+ State state = GetState();
RETURN_AND_NOTIFY_ON_FAILURE(
- (state_ == kNormal || state_ == kFlushing ||
- state_ == kStopped || state_ == kFlushingPendingInputBuffers),
+ (state == kNormal || state == kFlushing ||
+ state == kStopped || state == kFlushingPendingInputBuffers),
"DoDecode: not in normal/flushing/stopped state", ILLEGAL_STATE,);
MFT_OUTPUT_DATA_BUFFER output_data_buffer = {0};
@@ -956,7 +984,7 @@ void DXVAVideoDecodeAccelerator::DoDecode() {
// Decoder didn't let us set NV12 output format. Not sure as to why
// this can happen. Give up in disgust.
NOTREACHED() << "Failed to set decoder output media type to NV12";
- state_ = kStopped;
+ SetState(kStopped);
} else {
DVLOG(1) << "Received output format change from the decoder."
" Recursively invoking DoDecode";
@@ -965,8 +993,10 @@ void DXVAVideoDecodeAccelerator::DoDecode() {
return;
} else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
// No more output from the decoder. Stop playback.
- if (state_ != kFlushingPendingInputBuffers)
- state_ = kStopped;
+ if (state != kFlushingPendingInputBuffers ||
+ pending_input_buffers_.empty()) {
+ SetState(kStopped);
+ }
return;
} else {
NOTREACHED() << "Unhandled error in DoDecode()";
@@ -1002,17 +1032,18 @@ bool DXVAVideoDecodeAccelerator::ProcessOutputSample(IMFSample* sample) {
"Failed to get input buffer id associated with sample",
false);
- pending_output_samples_.push_back(
- PendingSampleInfo(input_buffer_id, sample));
-
- // If we have available picture buffers to copy the output data then use the
- // first one and then flag it as not being available for use.
- if (output_picture_buffers_.size()) {
- ProcessPendingSamples();
- return true;
+ {
+ base::AutoLock lock(decoder_lock_);
+ pending_output_samples_.push_back(
+ PendingSampleInfo(input_buffer_id, sample));
}
+
if (pictures_requested_) {
DVLOG(1) << "Waiting for picture slots from the client.";
+ main_thread_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&DXVAVideoDecodeAccelerator::ProcessPendingSamples,
+ weak_this_factory_.GetWeakPtr()));
return true;
}
@@ -1024,7 +1055,7 @@ bool DXVAVideoDecodeAccelerator::ProcessOutputSample(IMFSample* sample) {
RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false);
// Go ahead and request picture buffers.
- base::MessageLoop::current()->PostTask(
+ main_thread_task_runner_->PostTask(
FROM_HERE,
base::Bind(&DXVAVideoDecodeAccelerator::RequestPictureBuffers,
weak_this_factory_.GetWeakPtr(),
@@ -1036,6 +1067,11 @@ bool DXVAVideoDecodeAccelerator::ProcessOutputSample(IMFSample* sample) {
}
void DXVAVideoDecodeAccelerator::ProcessPendingSamples() {
+ DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
+
+ if (!output_picture_buffers_.size())
+ return;
+
RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_.Run(),
"Failed to make context current", PLATFORM_FAILURE,);
@@ -1043,7 +1079,7 @@ void DXVAVideoDecodeAccelerator::ProcessPendingSamples() {
for (index = output_picture_buffers_.begin();
index != output_picture_buffers_.end() &&
- !pending_output_samples_.empty();
+ OutputSamplesPresent();
++index) {
if (index->second->available()) {
PendingSampleInfo sample_info = pending_output_samples_.front();
@@ -1082,41 +1118,57 @@ void DXVAVideoDecodeAccelerator::ProcessPendingSamples() {
media::Picture output_picture(index->second->id(),
sample_info.input_buffer_id,
gfx::Rect(index->second->size()));
- base::MessageLoop::current()->PostTask(
+ main_thread_task_runner_->PostTask(
FROM_HERE,
base::Bind(&DXVAVideoDecodeAccelerator::NotifyPictureReady,
weak_this_factory_.GetWeakPtr(),
output_picture));
index->second->set_available(false);
- pending_output_samples_.pop_front();
+ {
+ base::AutoLock lock(decoder_lock_);
+ pending_output_samples_.pop_front();
+ }
}
}
- if (!pending_input_buffers_.empty() && pending_output_samples_.empty()) {
- base::MessageLoop::current()->PostTask(
+ State state = GetState();
+ if (state == kFlushing) {
+ decoder_thread_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers,
- weak_this_factory_.GetWeakPtr()));
+ base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal,
+ base::Unretained(this)));
}
+ decoder_thread_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers,
+ base::Unretained(this)));
}
void DXVAVideoDecodeAccelerator::StopOnError(
media::VideoDecodeAccelerator::Error error) {
- DCHECK(CalledOnValidThread());
+ if (!main_thread_task_runner_->BelongsToCurrentThread()) {
+ main_thread_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&DXVAVideoDecodeAccelerator::StopOnError,
+ weak_this_factory_.GetWeakPtr(),
+ error));
+ return;
+ }
if (client_)
client_->NotifyError(error);
client_ = NULL;
- if (state_ != kUninitialized) {
+ if (GetState() != kUninitialized) {
Invalidate();
}
}
void DXVAVideoDecodeAccelerator::Invalidate() {
- if (state_ == kUninitialized)
+ if (GetState() == kUninitialized)
return;
+ decoder_thread_.Stop();
weak_this_factory_.InvalidateWeakPtrs();
output_picture_buffers_.clear();
stale_output_picture_buffers_.clear();
@@ -1124,27 +1176,31 @@ void DXVAVideoDecodeAccelerator::Invalidate() {
pending_input_buffers_.clear();
decoder_.Release();
MFShutdown();
- state_ = kUninitialized;
+ SetState(kUninitialized);
}
void DXVAVideoDecodeAccelerator::NotifyInputBufferRead(int input_buffer_id) {
+ DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
if (client_)
client_->NotifyEndOfBitstreamBuffer(input_buffer_id);
}
void DXVAVideoDecodeAccelerator::NotifyFlushDone() {
- if (client_)
+ DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
+ if (client_ && GetState() == kStopped)
client_->NotifyFlushDone();
}
void DXVAVideoDecodeAccelerator::NotifyResetDone() {
+ DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
if (client_)
client_->NotifyResetDone();
}
void DXVAVideoDecodeAccelerator::RequestPictureBuffers(int width, int height) {
+ DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
// This task could execute after the decoder has been torn down.
- if (state_ != kUninitialized && client_) {
+ if (GetState() != kUninitialized && client_) {
client_->ProvidePictureBuffers(
kNumPictureBuffers,
gfx::Size(width, height),
@@ -1154,30 +1210,34 @@ void DXVAVideoDecodeAccelerator::RequestPictureBuffers(int width, int height) {
void DXVAVideoDecodeAccelerator::NotifyPictureReady(
const media::Picture& picture) {
+ DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
// This task could execute after the decoder has been torn down.
- if (state_ != kUninitialized && client_)
+ if (GetState() != kUninitialized && client_)
client_->PictureReady(picture);
}
void DXVAVideoDecodeAccelerator::NotifyInputBuffersDropped() {
- if (!client_ || !pending_output_samples_.empty())
- return;
-
- for (PendingInputs::iterator it = pending_input_buffers_.begin();
- it != pending_input_buffers_.end(); ++it) {
- LONGLONG input_buffer_id = 0;
- RETURN_ON_HR_FAILURE((*it)->GetSampleTime(&input_buffer_id),
- "Failed to get buffer id associated with sample",);
- client_->NotifyEndOfBitstreamBuffer(input_buffer_id);
- }
+ DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
+ if (!client_)
+ return;
+
+ for (PendingInputs::iterator it = pending_input_buffers_.begin();
+ it != pending_input_buffers_.end(); ++it) {
+ LONGLONG input_buffer_id = 0;
+ RETURN_ON_HR_FAILURE((*it)->GetSampleTime(&input_buffer_id),
+ "Failed to get buffer id associated with sample",);
+ client_->NotifyEndOfBitstreamBuffer(input_buffer_id);
+ }
pending_input_buffers_.clear();
}
void DXVAVideoDecodeAccelerator::DecodePendingInputBuffers() {
- RETURN_AND_NOTIFY_ON_FAILURE((state_ != kUninitialized),
- "Invalid state: " << state_, ILLEGAL_STATE,);
+ DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
+ State state = GetState();
+ RETURN_AND_NOTIFY_ON_FAILURE((state != kUninitialized),
+ "Invalid state: " << state, ILLEGAL_STATE,);
- if (pending_input_buffers_.empty() || !pending_output_samples_.empty())
+ if (pending_input_buffers_.empty() || OutputSamplesPresent())
return;
PendingInputs pending_input_buffers_copy;
@@ -1187,66 +1247,56 @@ void DXVAVideoDecodeAccelerator::DecodePendingInputBuffers() {
it != pending_input_buffers_copy.end(); ++it) {
DecodeInternal(*it);
}
-
- if (state_ != kFlushingPendingInputBuffers)
- return;
-
- // If we are scheduled during a flush operation then mark the flush as
- // complete if we have no pending input and pending output frames.
- // If we don't have available output slots then this function will be
- // scheduled again by the ProcessPendingSamples function once slots become
- // available.
- if (pending_input_buffers_.empty() && pending_output_samples_.empty()) {
- state_ = kNormal;
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&DXVAVideoDecodeAccelerator::NotifyFlushDone,
- weak_this_factory_.GetWeakPtr()));
- }
}
void DXVAVideoDecodeAccelerator::FlushInternal() {
+ DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
+
+ // We allow only one output frame to be present at any given time. If we have
+ // an output frame, then we cannot complete the flush at this time.
+ if (OutputSamplesPresent())
+ return;
+
// The DoDecode function sets the state to kStopped when the decoder returns
// MF_E_TRANSFORM_NEED_MORE_INPUT.
// The MFT decoder can buffer upto 30 frames worth of input before returning
// an output frame. This loop here attempts to retrieve as many output frames
// as possible from the buffered set.
- while (state_ != kStopped) {
+ while (GetState() != kStopped) {
DoDecode();
- if (!pending_output_samples_.empty())
+ if (OutputSamplesPresent())
return;
}
-
// TODO(ananta)
// Look into whether we can simplify this function by combining the while
// above and the code below into a single block which achieves both. The Flush
// transitions in the decoder are a touch intertwined with other portions of
// the code like AssignPictureBuffers, ReusePictureBuffers etc.
if (!pending_input_buffers_.empty()) {
- state_ = kFlushingPendingInputBuffers;
- base::MessageLoop::current()->PostTask(
+ SetState(kFlushingPendingInputBuffers);
+ decoder_thread_task_runner_->PostTask(
FROM_HERE,
base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers,
- weak_this_factory_.GetWeakPtr()));
+ base::Unretained(this)));
return;
}
- base::MessageLoop::current()->PostTask(
+ main_thread_task_runner_->PostTask(
FROM_HERE,
base::Bind(&DXVAVideoDecodeAccelerator::NotifyFlushDone,
weak_this_factory_.GetWeakPtr()));
- state_ = kNormal;
+ SetState(kNormal);
}
void DXVAVideoDecodeAccelerator::DecodeInternal(
const base::win::ScopedComPtr<IMFSample>& sample) {
- DCHECK(CalledOnValidThread());
+ DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
- if (state_ == kUninitialized)
+ if (GetState() == kUninitialized)
return;
- if (!pending_output_samples_.empty() || !pending_input_buffers_.empty()) {
+ if (OutputSamplesPresent() || !pending_input_buffers_.empty()) {
pending_input_buffers_.push_back(sample);
return;
}
@@ -1268,8 +1318,10 @@ void DXVAVideoDecodeAccelerator::DecodeInternal(
// decoder failure.
if (hr == MF_E_NOTACCEPTING) {
DoDecode();
- RETURN_AND_NOTIFY_ON_FAILURE((state_ == kStopped || state_ == kNormal),
- "Failed to process output. Unexpected decoder state: " << state_,
+ State state = GetState();
+ RETURN_AND_NOTIFY_ON_FAILURE((state == kStopped || state == kNormal ||
+ state == kFlushing),
+ "Failed to process output. Unexpected decoder state: " << state,
PLATFORM_FAILURE,);
hr = decoder_->ProcessInput(0, sample.get(), 0);
// If we continue to get the MF_E_NOTACCEPTING error we do the following:-
@@ -1283,12 +1335,10 @@ void DXVAVideoDecodeAccelerator::DecodeInternal(
// decoder where it recycles the output Decoder surfaces.
if (hr == MF_E_NOTACCEPTING) {
pending_input_buffers_.push_back(sample);
- if (pending_output_samples_.empty()) {
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers,
- weak_this_factory_.GetWeakPtr()));
- }
+ decoder_thread_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers,
+ base::Unretained(this)));
return;
}
}
@@ -1297,9 +1347,11 @@ void DXVAVideoDecodeAccelerator::DecodeInternal(
DoDecode();
- RETURN_AND_NOTIFY_ON_FAILURE((state_ == kStopped || state_ == kNormal ||
- state_ == kFlushingPendingInputBuffers),
- "Failed to process output. Unexpected decoder state: " << state_,
+ State state = GetState();
+ RETURN_AND_NOTIFY_ON_FAILURE((state == kStopped || state == kNormal ||
+ state == kFlushingPendingInputBuffers ||
+ state == kFlushing),
+ "Failed to process output. Unexpected decoder state: " << state,
ILLEGAL_STATE,);
LONGLONG input_buffer_id = 0;
@@ -1315,7 +1367,7 @@ void DXVAVideoDecodeAccelerator::DecodeInternal(
// decoder to emit an output packet for every input packet.
// http://code.google.com/p/chromium/issues/detail?id=108121
// http://code.google.com/p/chromium/issues/detail?id=150925
- base::MessageLoop::current()->PostTask(
+ main_thread_task_runner_->PostTask(
FROM_HERE,
base::Bind(&DXVAVideoDecodeAccelerator::NotifyInputBufferRead,
weak_this_factory_.GetWeakPtr(),
@@ -1324,12 +1376,12 @@ void DXVAVideoDecodeAccelerator::DecodeInternal(
void DXVAVideoDecodeAccelerator::HandleResolutionChanged(int width,
int height) {
- base::MessageLoop::current()->PostTask(
+ main_thread_task_runner_->PostTask(
FROM_HERE,
base::Bind(&DXVAVideoDecodeAccelerator::DismissStaleBuffers,
weak_this_factory_.GetWeakPtr()));
- base::MessageLoop::current()->PostTask(
+ main_thread_task_runner_->PostTask(
FROM_HERE,
base::Bind(&DXVAVideoDecodeAccelerator::RequestPictureBuffers,
weak_this_factory_.GetWeakPtr(),
@@ -1366,4 +1418,38 @@ void DXVAVideoDecodeAccelerator::DeferredDismissStaleBuffer(
stale_output_picture_buffers_.erase(it);
}
+DXVAVideoDecodeAccelerator::State
+DXVAVideoDecodeAccelerator::GetState() const {
+ State state = kUninitialized;
+ ::InterlockedExchange(reinterpret_cast<long*>(&state),
+ state_);
+ return state;
+}
+
+void DXVAVideoDecodeAccelerator::SetState(State new_state) {
+ if (!main_thread_task_runner_->BelongsToCurrentThread()) {
+ main_thread_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&DXVAVideoDecodeAccelerator::SetState,
+ weak_this_factory_.GetWeakPtr(),
+ new_state));
+ return;
+ }
+ ::InterlockedCompareExchange(reinterpret_cast<long*>(&state_),
+ new_state,
+ state_);
+ DCHECK_EQ(state_, new_state);
+}
+
+void DXVAVideoDecodeAccelerator::StartDecoderThread() {
+ decoder_thread_.init_com_with_mta(false);
+ decoder_thread_.Start();
+ decoder_thread_task_runner_ = decoder_thread_.task_runner();
+}
+
+bool DXVAVideoDecodeAccelerator::OutputSamplesPresent() {
+ base::AutoLock lock(decoder_lock_);
+ return !pending_output_samples_.empty();
+}
+
} // namespace content
« no previous file with comments | « content/common/gpu/media/dxva_video_decode_accelerator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698