1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/filters/fake_video_decoder.h"
7 #include "base/location.h"
8 #include "media/base/bind_to_current_loop.h"
9 #include "media/base/test_helpers.h"
13 FakeVideoDecoder::FakeVideoDecoder(int decoder_id,
15 int max_parallel_decoding_requests,
16 const BytesDecodedCB& bytes_decoded_cb)
17 : decoder_id_(decoder_id),
18 decoding_delay_(decoding_delay),
19 max_parallel_decoding_requests_(max_parallel_decoding_requests),
20 bytes_decoded_cb_(bytes_decoded_cb),
21 state_(STATE_UNINITIALIZED),
23 total_bytes_decoded_(0),
24 fail_to_initialize_(false) {
25 DETACH_FROM_SEQUENCE(sequence_checker_);
26 DVLOG(1) << decoder_id_ << ": " << __func__;
27 DCHECK_GE(decoding_delay, 0);
30 FakeVideoDecoder::~FakeVideoDecoder() {
31 DVLOG(1) << decoder_id_ << ": " << __func__;
32 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
34 if (state_ == STATE_UNINITIALIZED)
37 if (!init_cb_.IsNull())
39 if (!held_decode_callbacks_.empty())
41 if (!reset_cb_.IsNull())
44 decoded_frames_.clear();
47 void FakeVideoDecoder::EnableEncryptedConfigSupport() {
48 supports_encrypted_config_ = true;
51 void FakeVideoDecoder::SetIsPlatformDecoder(bool value) {
52 is_platform_decoder_ = value;
55 base::WeakPtr<FakeVideoDecoder> FakeVideoDecoder::GetWeakPtr() {
56 return weak_factory_.GetWeakPtr();
59 bool FakeVideoDecoder::SupportsDecryption() const {
60 return supports_encrypted_config_;
63 bool FakeVideoDecoder::IsPlatformDecoder() const {
64 return is_platform_decoder_;
67 VideoDecoderType FakeVideoDecoder::GetDecoderType() const {
68 return VideoDecoderType::kTesting;
71 void FakeVideoDecoder::Initialize(const VideoDecoderConfig& config,
73 CdmContext* cdm_context,
75 const OutputCB& output_cb,
76 const WaitingCB& waiting_cb) {
77 DVLOG(1) << decoder_id_ << ": " << __func__;
78 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
79 DCHECK(config.IsValidConfig());
80 DCHECK(held_decode_callbacks_.empty())
81 << "No reinitialization during pending decode.";
82 DCHECK(reset_cb_.IsNull()) << "No reinitialization during pending reset.";
84 current_config_ = config;
85 init_cb_.SetCallback(BindToCurrentLoop(std::move(init_cb)));
87 // Don't need BindToCurrentLoop() because |output_cb_| is only called from
88 // RunDecodeCallback() which is posted from Decode().
89 output_cb_ = output_cb;
91 if (!decoded_frames_.empty()) {
92 DVLOG(1) << "Decoded frames dropped during reinitialization.";
93 decoded_frames_.clear();
96 if (config.is_encrypted() && (!supports_encrypted_config_ || !cdm_context)) {
97 DVLOG(1) << "Encrypted config not supported.";
98 state_ = STATE_NORMAL;
99 init_cb_.RunOrHold(DecoderStatus::Codes::kUnsupportedEncryptionMode);
103 if (fail_to_initialize_) {
104 DVLOG(1) << decoder_id_ << ": Initialization failed.";
105 state_ = STATE_ERROR;
106 init_cb_.RunOrHold(DecoderStatus::Codes::kFailed);
108 DVLOG(1) << decoder_id_ << ": Initialization succeeded.";
109 state_ = STATE_NORMAL;
110 init_cb_.RunOrHold(DecoderStatus::Codes::kOk);
114 void FakeVideoDecoder::Decode(scoped_refptr<DecoderBuffer> buffer,
115 DecodeCB decode_cb) {
116 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
117 DCHECK(reset_cb_.IsNull());
118 DCHECK_LE(decoded_frames_.size(),
119 decoding_delay_ + held_decode_callbacks_.size());
120 DCHECK_LT(static_cast<int>(held_decode_callbacks_.size()),
121 max_parallel_decoding_requests_);
122 DCHECK_NE(state_, STATE_END_OF_STREAM);
124 int buffer_size = buffer->end_of_stream() ? 0 : buffer->data_size();
125 DecodeCB wrapped_decode_cb = base::BindOnce(
126 &FakeVideoDecoder::OnFrameDecoded, weak_factory_.GetWeakPtr(),
127 buffer_size, BindToCurrentLoop(std::move(decode_cb)));
129 if (state_ == STATE_ERROR) {
130 std::move(wrapped_decode_cb).Run(DecoderStatus::Codes::kFailed);
134 if (buffer->end_of_stream()) {
135 state_ = STATE_END_OF_STREAM;
137 DCHECK(VerifyFakeVideoBufferForTest(*buffer, current_config_));
138 decoded_frames_.push_back(MakeVideoFrame(*buffer));
141 RunOrHoldDecode(std::move(wrapped_decode_cb));
144 scoped_refptr<VideoFrame> FakeVideoDecoder::MakeVideoFrame(
145 const DecoderBuffer& buffer) {
146 return VideoFrame::CreateColorFrame(current_config_.coded_size(), 0, 0, 0,
150 void FakeVideoDecoder::Reset(base::OnceClosure closure) {
151 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
152 DCHECK(reset_cb_.IsNull());
154 reset_cb_.SetCallback(BindToCurrentLoop(std::move(closure)));
155 decoded_frames_.clear();
157 // Defer the reset if a decode is pending.
158 if (!held_decode_callbacks_.empty())
164 void FakeVideoDecoder::HoldNextInit() {
165 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
166 init_cb_.HoldCallback();
169 void FakeVideoDecoder::HoldDecode() {
170 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
174 void FakeVideoDecoder::HoldNextReset() {
175 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
176 reset_cb_.HoldCallback();
179 void FakeVideoDecoder::SatisfyInit() {
180 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
181 DCHECK(held_decode_callbacks_.empty());
182 DCHECK(reset_cb_.IsNull());
184 init_cb_.RunHeldCallback();
187 void FakeVideoDecoder::SatisfyDecode() {
188 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
189 DCHECK(hold_decode_);
191 hold_decode_ = false;
193 while (!held_decode_callbacks_.empty()) {
194 SatisfySingleDecode();
198 void FakeVideoDecoder::SatisfySingleDecode() {
199 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
200 DCHECK(!held_decode_callbacks_.empty());
202 DecodeCB decode_cb = std::move(held_decode_callbacks_.front());
203 held_decode_callbacks_.pop_front();
204 RunDecodeCallback(std::move(decode_cb));
206 if (!reset_cb_.IsNull() && held_decode_callbacks_.empty())
210 void FakeVideoDecoder::SatisfyReset() {
211 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
212 DCHECK(held_decode_callbacks_.empty());
213 reset_cb_.RunHeldCallback();
216 void FakeVideoDecoder::SimulateError() {
217 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
219 state_ = STATE_ERROR;
220 while (!held_decode_callbacks_.empty()) {
221 std::move(held_decode_callbacks_.front())
222 .Run(DecoderStatus::Codes::kFailed);
223 held_decode_callbacks_.pop_front();
225 decoded_frames_.clear();
228 void FakeVideoDecoder::SimulateFailureToInit() {
229 fail_to_initialize_ = true;
232 int FakeVideoDecoder::GetMaxDecodeRequests() const {
233 return max_parallel_decoding_requests_;
236 void FakeVideoDecoder::OnFrameDecoded(int buffer_size,
238 DecoderStatus status) {
239 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
241 if (status.is_ok()) {
242 total_bytes_decoded_ += buffer_size;
243 if (bytes_decoded_cb_)
244 bytes_decoded_cb_.Run(buffer_size);
246 std::move(decode_cb).Run(std::move(status));
249 void FakeVideoDecoder::RunOrHoldDecode(DecodeCB decode_cb) {
250 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
253 held_decode_callbacks_.push_back(std::move(decode_cb));
255 DCHECK(held_decode_callbacks_.empty());
256 RunDecodeCallback(std::move(decode_cb));
260 void FakeVideoDecoder::RunDecodeCallback(DecodeCB decode_cb) {
261 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
263 if (!reset_cb_.IsNull()) {
264 DCHECK(decoded_frames_.empty());
265 std::move(decode_cb).Run(DecoderStatus::Codes::kAborted);
269 // Make sure we leave decoding_delay_ frames in the queue and also frames for
270 // all pending decode callbacks, except the current one.
271 if (decoded_frames_.size() >
272 decoding_delay_ + held_decode_callbacks_.size()) {
273 output_cb_.Run(decoded_frames_.front());
274 decoded_frames_.pop_front();
275 } else if (state_ == STATE_END_OF_STREAM) {
276 // Drain the queue if this was the last request in the stream, otherwise
277 // just pop the last frame from the queue.
278 if (held_decode_callbacks_.empty()) {
279 while (!decoded_frames_.empty()) {
280 output_cb_.Run(decoded_frames_.front());
281 decoded_frames_.pop_front();
283 state_ = STATE_NORMAL;
284 } else if (!decoded_frames_.empty()) {
285 output_cb_.Run(decoded_frames_.front());
286 decoded_frames_.pop_front();
290 std::move(decode_cb).Run(DecoderStatus::Codes::kOk);
293 void FakeVideoDecoder::DoReset() {
294 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
295 DCHECK(held_decode_callbacks_.empty());
296 DCHECK(!reset_cb_.IsNull());
298 reset_cb_.RunOrHold();