Index: media/filters/gpu_video_decoder.cc |
diff --git a/media/filters/gpu_video_decoder.cc b/media/filters/gpu_video_decoder.cc |
index 392448d6a45ff26ed3aa845e36fde15670396515..2c74a77bb9ef7ce98ddf3bc83a6fbb28ce2a3de4 100644 |
--- a/media/filters/gpu_video_decoder.cc |
+++ b/media/filters/gpu_video_decoder.cc |
@@ -80,23 +80,17 @@ void GpuVideoDecoder::Reset(const base::Closure& closure) { |
FROM_HERE, |
base::Bind( |
&GpuVideoDecoder::Reset, weak_factory_.GetWeakPtr(), closure)); |
- // NOTE: if we're deferring Reset() until a Flush() completes, return |
- // queued pictures to the VDA so they can be used to finish that Flush(). |
- if (pending_decode_cb_.is_null()) |
- ready_video_frames_.clear(); |
return; |
} |
- // Throw away any already-decoded, not-yet-delivered frames. |
- ready_video_frames_.clear(); |
- |
if (!vda_) { |
base::MessageLoop::current()->PostTask(FROM_HERE, closure); |
return; |
} |
- if (!pending_decode_cb_.is_null()) |
- EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEOSFrame()); |
+ while (!pending_decode_callbacks_.empty()) { |
+ DeliverFrame(VideoFrame::CreateEOSFrame()); |
+ } |
DCHECK(pending_reset_cb_.is_null()); |
pending_reset_cb_ = BindToCurrentLoop(closure); |
@@ -108,8 +102,9 @@ void GpuVideoDecoder::Stop() { |
DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
if (vda_) |
DestroyVDA(); |
- if (!pending_decode_cb_.is_null()) |
- EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEOSFrame()); |
+ while (!pending_decode_callbacks_.empty()) { |
+ DeliverFrame(VideoFrame::CreateEOSFrame()); |
+ } |
if (!pending_reset_cb_.is_null()) |
base::ResetAndReturn(&pending_reset_cb_).Run(); |
} |
@@ -222,21 +217,14 @@ void GpuVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
const DecodeCB& decode_cb) { |
DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
DCHECK(pending_reset_cb_.is_null()); |
- DCHECK(pending_decode_cb_.is_null()); |
- |
- pending_decode_cb_ = BindToCurrentLoop(decode_cb); |
if (state_ == kError || !vda_) { |
- base::ResetAndReturn(&pending_decode_cb_).Run(kDecodeError, NULL); |
+ decode_cb.Run(kDecodeError, NULL); |
return; |
} |
switch (state_) { |
case kDecoderDrained: |
- if (!ready_video_frames_.empty()) { |
- EnqueueFrameAndTriggerFrameDelivery(NULL); |
- return; |
- } |
state_ = kNormal; |
// Fall-through. |
case kNormal: |
@@ -254,12 +242,10 @@ void GpuVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
if (buffer->end_of_stream()) { |
if (state_ == kNormal) { |
state_ = kDrainingDecoder; |
+ pending_decode_callbacks_.push_back(BindToCurrentLoop(decode_cb)); |
+ DCHECK_LE(static_cast<int>(pending_decode_callbacks_.size()), |
+ kMaxInFlightDecodes); |
vda_->Flush(); |
- // If we have ready frames, go ahead and process them to ensure that the |
- // Flush operation does not block in the VDA due to lack of picture |
- // buffers. |
- if (!ready_video_frames_.empty()) |
- EnqueueFrameAndTriggerFrameDelivery(NULL); |
} |
return; |
} |
@@ -267,10 +253,14 @@ void GpuVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
size_t size = buffer->data_size(); |
SHMBuffer* shm_buffer = GetSHM(size); |
if (!shm_buffer) { |
- base::ResetAndReturn(&pending_decode_cb_).Run(kDecodeError, NULL); |
+ decode_cb.Run(kDecodeError, NULL); |
return; |
} |
+ pending_decode_callbacks_.push_back(BindToCurrentLoop(decode_cb)); |
+ DCHECK_LE(static_cast<int>(pending_decode_callbacks_.size()), |
+ kMaxInFlightDecodes); |
+ |
memcpy(shm_buffer->shm->memory(), buffer->data(), size); |
BitstreamBuffer bitstream_buffer( |
next_bitstream_buffer_id_, shm_buffer->shm->handle(), size); |
@@ -282,18 +272,6 @@ void GpuVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
RecordBufferData(bitstream_buffer, *buffer.get()); |
vda_->Decode(bitstream_buffer); |
- |
- if (!ready_video_frames_.empty()) { |
- EnqueueFrameAndTriggerFrameDelivery(NULL); |
- return; |
- } |
- |
- if (CanMoreDecodeWorkBeDone()) |
- base::ResetAndReturn(&pending_decode_cb_).Run(kNotEnoughData, NULL); |
-} |
- |
-bool GpuVideoDecoder::CanMoreDecodeWorkBeDone() { |
- return bitstream_buffers_in_decoder_.size() < kMaxInFlightDecodes; |
} |
void GpuVideoDecoder::RecordBufferData(const BitstreamBuffer& bitstream_buffer, |
@@ -337,7 +315,11 @@ bool GpuVideoDecoder::CanReadWithoutStalling() const { |
DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
return |
next_picture_buffer_id_ == 0 || // Decode() will ProvidePictureBuffers(). |
- available_pictures_ > 0 || !ready_video_frames_.empty(); |
+ available_pictures_ > 0; |
+} |
+ |
+int GpuVideoDecoder::GetMaxDecodeRequests() const { |
+ return kMaxInFlightDecodes; |
} |
void GpuVideoDecoder::ProvidePictureBuffers(uint32 count, |
@@ -470,10 +452,10 @@ void GpuVideoDecoder::PictureReady(const media::Picture& picture) { |
pb.texture_id())).second; |
DCHECK(inserted); |
- EnqueueFrameAndTriggerFrameDelivery(frame); |
+ DeliverFrame(frame); |
} |
-void GpuVideoDecoder::EnqueueFrameAndTriggerFrameDelivery( |
+void GpuVideoDecoder::DeliverFrame( |
const scoped_refptr<VideoFrame>& frame) { |
DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
@@ -482,17 +464,12 @@ void GpuVideoDecoder::EnqueueFrameAndTriggerFrameDelivery( |
if (!pending_reset_cb_.is_null()) |
return; |
- if (frame.get()) |
- ready_video_frames_.push_back(frame); |
- else |
- DCHECK(!ready_video_frames_.empty()); |
+ DCHECK(!pending_decode_callbacks_.empty()); |
- if (pending_decode_cb_.is_null()) |
- return; |
+ DecodeCB decode_cb = pending_decode_callbacks_.front(); |
+ pending_decode_callbacks_.pop_front(); |
- base::ResetAndReturn(&pending_decode_cb_) |
- .Run(kOk, ready_video_frames_.front()); |
- ready_video_frames_.pop_front(); |
+ decode_cb.Run(kOk, frame); |
} |
// static |
@@ -573,18 +550,13 @@ void GpuVideoDecoder::NotifyEndOfBitstreamBuffer(int32 id) { |
PutSHM(it->second.shm_buffer); |
bitstream_buffers_in_decoder_.erase(it); |
- |
- if (pending_reset_cb_.is_null() && state_ != kDrainingDecoder && |
- CanMoreDecodeWorkBeDone() && !pending_decode_cb_.is_null()) { |
- base::ResetAndReturn(&pending_decode_cb_).Run(kNotEnoughData, NULL); |
- } |
} |
GpuVideoDecoder::~GpuVideoDecoder() { |
DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
// Stop should have been already called. |
DCHECK(!vda_.get() && assigned_picture_buffers_.empty()); |
- DCHECK(pending_decode_cb_.is_null()); |
+ DCHECK(pending_decode_callbacks_.empty()); |
for (size_t i = 0; i < available_shm_segments_.size(); ++i) { |
available_shm_segments_[i]->shm->Close(); |
delete available_shm_segments_[i]; |
@@ -602,14 +574,15 @@ void GpuVideoDecoder::NotifyFlushDone() { |
DVLOG(3) << "NotifyFlushDone()"; |
DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
DCHECK_EQ(state_, kDrainingDecoder); |
+ DCHECK_EQ(pending_decode_callbacks_.size(), 1U); |
state_ = kDecoderDrained; |
- EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEOSFrame()); |
+ DeliverFrame(VideoFrame::CreateEOSFrame()); |
} |
void GpuVideoDecoder::NotifyResetDone() { |
DVLOG(3) << "NotifyResetDone()"; |
DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
- DCHECK(ready_video_frames_.empty()); |
+ DCHECK(pending_decode_callbacks_.empty()); |
// This needs to happen after the Reset() on vda_ is done to ensure pictures |
// delivered during the reset can find their time data. |
@@ -617,9 +590,6 @@ void GpuVideoDecoder::NotifyResetDone() { |
if (!pending_reset_cb_.is_null()) |
base::ResetAndReturn(&pending_reset_cb_).Run(); |
- |
- if (!pending_decode_cb_.is_null()) |
- EnqueueFrameAndTriggerFrameDelivery(VideoFrame::CreateEOSFrame()); |
} |
void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { |
@@ -632,9 +602,9 @@ void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { |
state_ = kError; |
- if (!pending_decode_cb_.is_null()) { |
- base::ResetAndReturn(&pending_decode_cb_).Run(kDecodeError, NULL); |
- return; |
+ while (!pending_decode_callbacks_.empty()) { |
+ pending_decode_callbacks_.front().Run(kDecodeError, NULL); |
+ pending_decode_callbacks_.pop_front(); |
} |
} |