Index: media/filters/fake_video_decoder.cc |
diff --git a/media/filters/fake_video_decoder.cc b/media/filters/fake_video_decoder.cc |
index 0f171999783f161a65bf38c2662f76d15655ad6b..e2c2e5092277496429252afdb09af37d8312fd7b 100644 |
--- a/media/filters/fake_video_decoder.cc |
+++ b/media/filters/fake_video_decoder.cc |
@@ -14,11 +14,13 @@ |
namespace media { |
FakeVideoDecoder::FakeVideoDecoder(int decoding_delay, |
- bool supports_get_decode_output) |
- : task_runner_(base::MessageLoopProxy::current()), |
- decoding_delay_(decoding_delay), |
+ bool supports_get_decode_output, |
+ int max_parallel_decoding_requests) |
+ : decoding_delay_(decoding_delay), |
supports_get_decode_output_(supports_get_decode_output), |
+ max_parallel_decoding_requests_(max_parallel_decoding_requests), |
state_(UNINITIALIZED), |
+ hold_decode_(false), |
total_bytes_decoded_(0), |
weak_factory_(this) { |
DCHECK_GE(decoding_delay, 0); |
@@ -30,9 +32,10 @@ FakeVideoDecoder::~FakeVideoDecoder() { |
void FakeVideoDecoder::Initialize(const VideoDecoderConfig& config, |
const PipelineStatusCB& status_cb) { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
DCHECK(config.IsValidConfig()); |
- DCHECK(decode_cb_.IsNull()) << "No reinitialization during pending decode."; |
+ DCHECK(held_decode_callbacks_.empty()) |
+ << "No reinitialization during pending decode."; |
DCHECK(reset_cb_.IsNull()) << "No reinitialization during pending reset."; |
current_config_ = config; |
@@ -49,58 +52,58 @@ void FakeVideoDecoder::Initialize(const VideoDecoderConfig& config, |
void FakeVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
const DecodeCB& decode_cb) { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
- DCHECK(decode_cb_.IsNull()) << "Overlapping decodes are not supported."; |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
DCHECK(reset_cb_.IsNull()); |
- DCHECK_LE(decoded_frames_.size(), static_cast<size_t>(decoding_delay_)); |
+ DCHECK_LE( |
+ decoded_frames_.size(), |
+ static_cast<size_t>(decoding_delay_) + max_parallel_decoding_requests_); |
+ DCHECK_LT(static_cast<int>(held_decode_callbacks_.size()), |
+ max_parallel_decoding_requests_); |
int buffer_size = buffer->end_of_stream() ? 0 : buffer->data_size(); |
- decode_cb_.SetCallback( |
+ DecodeCB wrapped_decode_cb = |
BindToCurrentLoop(base::Bind(&FakeVideoDecoder::OnFrameDecoded, |
weak_factory_.GetWeakPtr(), |
buffer_size, |
- decode_cb))); |
+ decode_cb)); |
- if (buffer->end_of_stream() && decoded_frames_.empty()) { |
- decode_cb_.RunOrHold(kOk, VideoFrame::CreateEOSFrame()); |
+ if (state_ == ERROR) { |
+ wrapped_decode_cb.Run(kDecodeError, scoped_refptr<VideoFrame>()); |
return; |
} |
- if (!buffer->end_of_stream()) { |
+ if (buffer->end_of_stream()) { |
+ state_ = END_OF_STREAM; |
+ } else { |
DCHECK(VerifyFakeVideoBufferForTest(buffer, current_config_)); |
scoped_refptr<VideoFrame> video_frame = VideoFrame::CreateColorFrame( |
current_config_.coded_size(), 0, 0, 0, buffer->timestamp()); |
decoded_frames_.push_back(video_frame); |
- |
- if (decoded_frames_.size() <= static_cast<size_t>(decoding_delay_)) { |
- decode_cb_.RunOrHold(kNotEnoughData, scoped_refptr<VideoFrame>()); |
- return; |
- } |
} |
- scoped_refptr<VideoFrame> frame = decoded_frames_.front(); |
- decoded_frames_.pop_front(); |
- decode_cb_.RunOrHold(kOk, frame); |
+ RunOrHoldDecode(wrapped_decode_cb); |
} |
void FakeVideoDecoder::Reset(const base::Closure& closure) { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
DCHECK(reset_cb_.IsNull()); |
+ |
reset_cb_.SetCallback(BindToCurrentLoop(closure)); |
+ decoded_frames_.clear(); |
// Defer the reset if a decode is pending. |
- if (!decode_cb_.IsNull()) |
+ if (!held_decode_callbacks_.empty()) |
return; |
DoReset(); |
} |
void FakeVideoDecoder::Stop() { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
if (!init_cb_.IsNull()) |
SatisfyInit(); |
- if (!decode_cb_.IsNull()) |
+ if (!held_decode_callbacks_.empty()) |
SatisfyDecode(); |
if (!reset_cb_.IsNull()) |
SatisfyReset(); |
@@ -110,7 +113,7 @@ void FakeVideoDecoder::Stop() { |
} |
scoped_refptr<VideoFrame> FakeVideoDecoder::GetDecodeOutput() { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
if (!supports_get_decode_output_ || decoded_frames_.empty()) |
return NULL; |
scoped_refptr<VideoFrame> out = decoded_frames_.front(); |
@@ -119,49 +122,70 @@ scoped_refptr<VideoFrame> FakeVideoDecoder::GetDecodeOutput() { |
} |
void FakeVideoDecoder::HoldNextInit() { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
init_cb_.HoldCallback(); |
} |
-void FakeVideoDecoder::HoldNextDecode() { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
- decode_cb_.HoldCallback(); |
+void FakeVideoDecoder::HoldDecode() { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ hold_decode_ = true; |
} |
void FakeVideoDecoder::HoldNextReset() { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
reset_cb_.HoldCallback(); |
} |
void FakeVideoDecoder::SatisfyInit() { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
- DCHECK(decode_cb_.IsNull()); |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ DCHECK(held_decode_callbacks_.empty()); |
DCHECK(reset_cb_.IsNull()); |
init_cb_.RunHeldCallback(); |
} |
void FakeVideoDecoder::SatisfyDecode() { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
- decode_cb_.RunHeldCallback(); |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ DCHECK_NE(hold_decode_, 0); |
- if (!reset_cb_.IsNull()) |
+ hold_decode_ = 0; |
+ |
+ while (!held_decode_callbacks_.empty()) { |
+ SatisfySingleDecode(); |
+ } |
+} |
+ |
+void FakeVideoDecoder::SatisfySingleDecode() { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ DCHECK(!held_decode_callbacks_.empty()); |
+ |
+ RunDecodeCallback(held_decode_callbacks_.front()); |
+ held_decode_callbacks_.pop_front(); |
+ |
+ if (!reset_cb_.IsNull() && held_decode_callbacks_.empty()) |
DoReset(); |
} |
void FakeVideoDecoder::SatisfyReset() { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
- DCHECK(decode_cb_.IsNull()); |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ DCHECK(held_decode_callbacks_.empty()); |
reset_cb_.RunHeldCallback(); |
} |
-void FakeVideoDecoder::DoReset() { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
- DCHECK(decode_cb_.IsNull()); |
- DCHECK(!reset_cb_.IsNull()); |
+void FakeVideoDecoder::SimulateError() { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ state_ = ERROR; |
+ while (!held_decode_callbacks_.empty()) { |
+ held_decode_callbacks_.front().Run(kDecodeError, |
+ scoped_refptr<VideoFrame>()); |
+ held_decode_callbacks_.pop_front(); |
+ } |
decoded_frames_.clear(); |
- reset_cb_.RunOrHold(); |
+} |
+ |
+int FakeVideoDecoder::GetMaxDecodeRequests() const { |
+ return max_parallel_decoding_requests_; |
} |
void FakeVideoDecoder::OnFrameDecoded( |
@@ -169,9 +193,52 @@ void FakeVideoDecoder::OnFrameDecoded( |
const DecodeCB& decode_cb, |
Status status, |
const scoped_refptr<VideoFrame>& video_frame) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
if (status == kOk || status == kNotEnoughData) |
total_bytes_decoded_ += buffer_size; |
decode_cb.Run(status, video_frame); |
} |
+void FakeVideoDecoder::RunOrHoldDecode(const DecodeCB& decode_cb) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ if (hold_decode_) { |
+ held_decode_callbacks_.push_back(decode_cb); |
+ } else { |
xhwang
2014/04/25 00:36:03
DCHECK(held_decode_callbacks_.empty());
We should
Sergey Ulanov
2014/04/26 00:59:29
Done.
|
+ RunDecodeCallback(decode_cb); |
+ } |
+} |
+ |
+void FakeVideoDecoder::RunDecodeCallback(const DecodeCB& decode_cb) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ if (!reset_cb_.IsNull()) { |
xhwang
2014/04/25 00:36:03
DCHECK(decoded_frames_.empty());
Sergey Ulanov
2014/04/26 00:59:29
Done.
|
+ decode_cb.Run(kAborted, scoped_refptr<VideoFrame>()); |
+ return; |
+ } |
+ if (static_cast<int>(decoded_frames_.size()) <= decoding_delay_ && |
xhwang
2014/04/25 00:36:03
The two cases we use |decoding_delay_| both involv
Sergey Ulanov
2014/04/26 00:59:29
Done.
|
+ state_ != END_OF_STREAM) { |
+ decode_cb.Run(kNotEnoughData, scoped_refptr<VideoFrame>()); |
xhwang
2014/04/25 00:36:03
Return early here then we don't need the "else" in
Sergey Ulanov
2014/04/26 00:59:29
Done.
|
+ } else { |
+ scoped_refptr<VideoFrame> frame; |
+ if (decoded_frames_.empty()) { |
+ DCHECK_EQ(state_, END_OF_STREAM); |
+ frame = VideoFrame::CreateEOSFrame(); |
+ } else { |
+ frame = decoded_frames_.front(); |
+ decoded_frames_.pop_front(); |
+ } |
+ decode_cb.Run(kOk, frame); |
+ } |
+} |
+ |
+void FakeVideoDecoder::DoReset() { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ DCHECK(held_decode_callbacks_.empty()); |
+ DCHECK(!reset_cb_.IsNull()); |
+ |
+ reset_cb_.RunOrHold(); |
+} |
+ |
} // namespace media |