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

Side by Side Diff: media/filters/decoder_stream.cc

Issue 1939993002: Ignore calls to Reset() when in error state (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months 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 unified diff | Download patch
« no previous file with comments | « media/filters/decoder_stream.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/filters/decoder_stream.h" 5 #include "media/filters/decoder_stream.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/callback_helpers.h" 10 #include "base/callback_helpers.h"
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 state_(STATE_UNINITIALIZED), 52 state_(STATE_UNINITIALIZED),
53 stream_(NULL), 53 stream_(NULL),
54 decoder_selector_(new DecoderSelector<StreamType>(task_runner, 54 decoder_selector_(new DecoderSelector<StreamType>(task_runner,
55 std::move(decoders), 55 std::move(decoders),
56 media_log)), 56 media_log)),
57 decoded_frames_since_fallback_(0), 57 decoded_frames_since_fallback_(0),
58 active_splice_(false), 58 active_splice_(false),
59 decoding_eos_(false), 59 decoding_eos_(false),
60 pending_decode_requests_(0), 60 pending_decode_requests_(0),
61 duration_tracker_(8), 61 duration_tracker_(8),
62 received_config_change_during_reinit_(false),
63 pending_demuxer_read_(false),
62 weak_factory_(this), 64 weak_factory_(this),
63 fallback_weak_factory_(this) {} 65 fallback_weak_factory_(this) {}
64 66
65 template <DemuxerStream::Type StreamType> 67 template <DemuxerStream::Type StreamType>
66 DecoderStream<StreamType>::~DecoderStream() { 68 DecoderStream<StreamType>::~DecoderStream() {
67 FUNCTION_DVLOG(2); 69 FUNCTION_DVLOG(2);
68 DCHECK(task_runner_->BelongsToCurrentThread()); 70 DCHECK(task_runner_->BelongsToCurrentThread());
69 71
70 decoder_selector_.reset(); 72 decoder_selector_.reset();
71 73
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 template <DemuxerStream::Type StreamType> 152 template <DemuxerStream::Type StreamType>
151 void DecoderStream<StreamType>::Reset(const base::Closure& closure) { 153 void DecoderStream<StreamType>::Reset(const base::Closure& closure) {
152 FUNCTION_DVLOG(2); 154 FUNCTION_DVLOG(2);
153 DCHECK(task_runner_->BelongsToCurrentThread()); 155 DCHECK(task_runner_->BelongsToCurrentThread());
154 DCHECK_NE(state_, STATE_UNINITIALIZED); 156 DCHECK_NE(state_, STATE_UNINITIALIZED);
155 DCHECK(reset_cb_.is_null()); 157 DCHECK(reset_cb_.is_null());
156 158
157 reset_cb_ = closure; 159 reset_cb_ = closure;
158 160
159 if (!read_cb_.is_null()) { 161 if (!read_cb_.is_null()) {
160 task_runner_->PostTask(FROM_HERE, base::Bind( 162 task_runner_->PostTask(FROM_HERE,
161 base::ResetAndReturn(&read_cb_), ABORTED, scoped_refptr<Output>())); 163 base::Bind(base::ResetAndReturn(&read_cb_), ABORTED,
164 scoped_refptr<Output>()));
162 } 165 }
163 166
164 ready_outputs_.clear(); 167 ready_outputs_.clear();
165 168
169 // It's possible to have received a DECODE_ERROR and entered STATE_ERROR right
170 // before a Reset() is executed. If we are still waiting for a demuxer read,
171 // OnBufferReady() will handle the reset callback.
172 // See crbug.com/597605 and crbug.com/607454.
173 if (state_ == STATE_ERROR && !pending_demuxer_read_) {
174 task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&reset_cb_));
175 return;
176 }
177
166 // During decoder reinitialization, the Decoder does not need to be and 178 // During decoder reinitialization, the Decoder does not need to be and
167 // cannot be Reset(). |decrypting_demuxer_stream_| was reset before decoder 179 // cannot be Reset(). |decrypting_demuxer_stream_| was reset before decoder
168 // reinitialization. 180 // reinitialization.
169 if (state_ == STATE_REINITIALIZING_DECODER) 181 if (state_ == STATE_REINITIALIZING_DECODER)
170 return; 182 return;
171 183
172 // During pending demuxer read and when not using DecryptingDemuxerStream, 184 // |decrypting_demuxer_stream_| will fire all of its read requests when
173 // the Decoder will be reset after demuxer read is returned 185 // it resets. |reset_cb_| will be fired in OnDecoderReset(), after the
174 // (in OnBufferReady()). 186 // decrypting demuxer stream finishes its reset.
175 if (state_ == STATE_PENDING_DEMUXER_READ && !decrypting_demuxer_stream_)
176 return;
177
178 if (decrypting_demuxer_stream_) { 187 if (decrypting_demuxer_stream_) {
179 decrypting_demuxer_stream_->Reset(base::Bind( 188 decrypting_demuxer_stream_->Reset(base::Bind(
180 &DecoderStream<StreamType>::ResetDecoder, weak_factory_.GetWeakPtr())); 189 &DecoderStream<StreamType>::ResetDecoder, weak_factory_.GetWeakPtr()));
181 return; 190 return;
182 } 191 }
183 192
193 // During pending demuxer read and when not using DecryptingDemuxerStream,
194 // the Decoder will be reset after demuxer read is returned
195 // (in OnBufferReady()).
196 if (pending_demuxer_read_)
197 return;
198
184 ResetDecoder(); 199 ResetDecoder();
185 } 200 }
186 201
187 template <DemuxerStream::Type StreamType> 202 template <DemuxerStream::Type StreamType>
188 bool DecoderStream<StreamType>::CanReadWithoutStalling() const { 203 bool DecoderStream<StreamType>::CanReadWithoutStalling() const {
189 DCHECK(task_runner_->BelongsToCurrentThread()); 204 DCHECK(task_runner_->BelongsToCurrentThread());
190 return !ready_outputs_.empty() || decoder_->CanReadWithoutStalling(); 205 return !ready_outputs_.empty() || decoder_->CanReadWithoutStalling();
191 } 206 }
192 207
193 template <> 208 template <>
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 } 254 }
240 255
241 template <DemuxerStream::Type StreamType> 256 template <DemuxerStream::Type StreamType>
242 void DecoderStream<StreamType>::OnDecoderSelected( 257 void DecoderStream<StreamType>::OnDecoderSelected(
243 std::unique_ptr<Decoder> selected_decoder, 258 std::unique_ptr<Decoder> selected_decoder,
244 std::unique_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) { 259 std::unique_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) {
245 FUNCTION_DVLOG(2) << ": " 260 FUNCTION_DVLOG(2) << ": "
246 << (selected_decoder ? selected_decoder->GetDisplayName() 261 << (selected_decoder ? selected_decoder->GetDisplayName()
247 : "No decoder selected."); 262 : "No decoder selected.");
248 DCHECK(task_runner_->BelongsToCurrentThread()); 263 DCHECK(task_runner_->BelongsToCurrentThread());
249 DCHECK(state_ == STATE_INITIALIZING || 264 DCHECK(state_ == STATE_INITIALIZING || state_ == STATE_REINITIALIZING_DECODER)
250 state_ == STATE_REINITIALIZING_DECODER ||
251 state_ == STATE_CONFIG_CHANGE_RECEIVED_WHILE_REINITIALIZING_DECODER)
252 << state_; 265 << state_;
253 if (state_ == STATE_INITIALIZING) { 266 if (state_ == STATE_INITIALIZING) {
254 DCHECK(!init_cb_.is_null()); 267 DCHECK(!init_cb_.is_null());
255 DCHECK(read_cb_.is_null()); 268 DCHECK(read_cb_.is_null());
256 DCHECK(reset_cb_.is_null()); 269 DCHECK(reset_cb_.is_null());
257 } else if (state_ == STATE_REINITIALIZING_DECODER) { 270 } else if (state_ == STATE_REINITIALIZING_DECODER) {
258 DCHECK(decoder_); 271 DCHECK(decoder_);
259 } 272 }
260 273
261 previous_decoder_ = std::move(decoder_); 274 previous_decoder_ = std::move(decoder_);
262 decoded_frames_since_fallback_ = 0; 275 decoded_frames_since_fallback_ = 0;
263 decoder_ = std::move(selected_decoder); 276 decoder_ = std::move(selected_decoder);
264 if (decrypting_demuxer_stream) { 277 if (decrypting_demuxer_stream) {
265 decrypting_demuxer_stream_ = std::move(decrypting_demuxer_stream); 278 decrypting_demuxer_stream_ = std::move(decrypting_demuxer_stream);
266 stream_ = decrypting_demuxer_stream_.get(); 279 stream_ = decrypting_demuxer_stream_.get();
267 } 280 }
268 281
269 // TODO(tguilbert): crbug.com/603713 support config changes on decoder reinit. 282 // TODO(tguilbert): crbug.com/603713 support config changes on decoder reinit.
270 if (state_ == STATE_CONFIG_CHANGE_RECEIVED_WHILE_REINITIALIZING_DECODER) { 283 if (received_config_change_during_reinit_) {
271 CompleteDecoderReinitialization(false); 284 CompleteDecoderReinitialization(false);
272 return; 285 return;
273 } 286 }
274 287
275 // Attempt to decode buffers from previous decoders (when those decoders have 288 // Attempt to decode buffers from previous decoders (when those decoders have
276 // never successfully outputed a frame). 289 // never successfully outputed a frame).
277 fallback_buffers_ = pending_buffers_; 290 fallback_buffers_ = pending_buffers_;
278 291
279 if (!decoder_) { 292 if (!decoder_) {
280 if (state_ == STATE_INITIALIZING) { 293 if (state_ == STATE_INITIALIZING) {
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 512
500 if (!fallback_buffers_.empty()) { 513 if (!fallback_buffers_.empty()) {
501 scoped_refptr<DecoderBuffer> buffer = fallback_buffers_.front(); 514 scoped_refptr<DecoderBuffer> buffer = fallback_buffers_.front();
502 fallback_buffers_.pop_front(); 515 fallback_buffers_.pop_front();
503 516
504 // Decode the buffer without re-appending it to |pending_buffers_|. 517 // Decode the buffer without re-appending it to |pending_buffers_|.
505 DecodeInternal(buffer); 518 DecodeInternal(buffer);
506 return; 519 return;
507 } 520 }
508 521
522 // Set a flag in addition to the state, because the state can be overwritten
523 // when encountering an error. See crbug.com/597605.
524 DCHECK(!pending_demuxer_read_);
525 pending_demuxer_read_ = true;
526
509 state_ = STATE_PENDING_DEMUXER_READ; 527 state_ = STATE_PENDING_DEMUXER_READ;
510 stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady, 528 stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady,
511 weak_factory_.GetWeakPtr())); 529 weak_factory_.GetWeakPtr()));
512 } 530 }
513 531
514 template <DemuxerStream::Type StreamType> 532 template <DemuxerStream::Type StreamType>
515 void DecoderStream<StreamType>::OnBufferReady( 533 void DecoderStream<StreamType>::OnBufferReady(
516 DemuxerStream::Status status, 534 DemuxerStream::Status status,
517 const scoped_refptr<DecoderBuffer>& buffer) { 535 const scoped_refptr<DecoderBuffer>& buffer) {
518 FUNCTION_DVLOG(2) << ": " << status << ", " 536 FUNCTION_DVLOG(2) << ": " << status << ", "
519 << (buffer.get() ? buffer->AsHumanReadableString() 537 << (buffer.get() ? buffer->AsHumanReadableString()
520 : "NULL"); 538 : "NULL");
521 539
522 DCHECK(task_runner_->BelongsToCurrentThread()); 540 DCHECK(task_runner_->BelongsToCurrentThread());
523 if (decoded_frames_since_fallback_) { 541 if (decoded_frames_since_fallback_) {
524 DCHECK(state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR) 542 DCHECK(state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR)
525 << state_; 543 << state_;
526 } else { 544 } else {
527 DCHECK(state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR || 545 DCHECK(state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR ||
528 STATE_REINITIALIZING_DECODER) 546 STATE_REINITIALIZING_DECODER)
529 << state_; 547 << state_;
530 } 548 }
531 DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status; 549 DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status;
532 550
551 // Unset the flag. STATE_PENDING_DEMUXER_READ might have been overwritten.
552 // See crbug.com/597605.
553 pending_demuxer_read_ = false;
554
533 // If parallel decode requests are supported, multiple read requests might 555 // If parallel decode requests are supported, multiple read requests might
534 // have been sent to the demuxer. The buffers might arrive while the decoder 556 // have been sent to the demuxer. The buffers might arrive while the decoder
535 // is reinitializing after falling back on first decode error. 557 // is reinitializing after falling back on first decode error.
536 if (state_ == STATE_REINITIALIZING_DECODER && 558 if (state_ == STATE_REINITIALIZING_DECODER &&
537 !decoded_frames_since_fallback_) { 559 !decoded_frames_since_fallback_) {
538 switch (status) { 560 switch (status) {
539 case DemuxerStream::kOk: 561 case DemuxerStream::kOk:
540 // Save valid buffers to be consumed by the new decoder. 562 // Save valid buffers to be consumed by the new decoder.
541 // |pending_buffers_| is copied to |fallback_buffers| in 563 // |pending_buffers_| is copied to |fallback_buffers| in
542 // OnDecoderSelected(). 564 // OnDecoderSelected().
543 pending_buffers_.push_back(buffer); 565 pending_buffers_.push_back(buffer);
544 break; 566 break;
545 case DemuxerStream::kConfigChanged: 567 case DemuxerStream::kConfigChanged:
546 // TODO(tguilbert): crbug.com/603713 568 // TODO(tguilbert): crbug.com/603713
547 // |decoder_| might have a stale config by the time it is reinitialized. 569 // |decoder_| might have a stale config by the time it is reinitialized.
548 // Ideally, we would save the config from |stream_| and reinitialize the 570 // Ideally, we would save the config from |stream_| and reinitialize the
549 // decoder by playing back the sequence of buffers and config changes. 571 // decoder by playing back the sequence of buffers and config changes.
550 state_ = STATE_CONFIG_CHANGE_RECEIVED_WHILE_REINITIALIZING_DECODER; 572 received_config_change_during_reinit_ = true;
551 pending_buffers_.clear(); 573 pending_buffers_.clear();
552 break; 574 break;
553 case DemuxerStream::kAborted: 575 case DemuxerStream::kAborted:
554 // |this| will read from the demuxer stream again in OnDecoderSelected() 576 // |this| will read from the demuxer stream again in OnDecoderSelected()
555 // and receive a kAborted then. 577 // and receive a kAborted then.
556 pending_buffers_.clear(); 578 pending_buffers_.clear();
557 break; 579 break;
558 } 580 }
559 return; 581 return;
560 } 582 }
561 583
562 // Decoding has been stopped (e.g due to an error). 584 // Decoding has been stopped (e.g due to an error).
563 if (state_ != STATE_PENDING_DEMUXER_READ) { 585 if (state_ != STATE_PENDING_DEMUXER_READ) {
564 DCHECK(state_ == STATE_ERROR); 586 DCHECK(state_ == STATE_ERROR);
565 DCHECK(read_cb_.is_null()); 587 DCHECK(read_cb_.is_null());
588
589 if (!reset_cb_.is_null()) {
590 // If we are using DecryptingDemuxerStream, we already called DDS::Reset()
591 // which will continue the resetting process in its callback.
592 if (!decrypting_demuxer_stream_)
593 Reset(base::ResetAndReturn(&reset_cb_));
594 }
566 return; 595 return;
567 } 596 }
568 597
569 state_ = STATE_NORMAL; 598 state_ = STATE_NORMAL;
570 599
571 if (status == DemuxerStream::kConfigChanged) { 600 if (status == DemuxerStream::kConfigChanged) {
572 FUNCTION_DVLOG(2) << ": " << "ConfigChanged"; 601 FUNCTION_DVLOG(2) << ": " << "ConfigChanged";
573 DCHECK(stream_->SupportsConfigChanges()); 602 DCHECK(stream_->SupportsConfigChanges());
574 603
575 // Pending buffers might not match the reinitialized decoder's new config. 604 // Pending buffers might not match the reinitialized decoder's new config.
(...skipping 15 matching lines...) Expand all
591 // happened, and read straight from the demuxer, which could lead to some 620 // happened, and read straight from the demuxer, which could lead to some
592 // lost frames if we were to fallback then). 621 // lost frames if we were to fallback then).
593 pending_buffers_.clear(); 622 pending_buffers_.clear();
594 623
595 if (!config_change_observer_cb_.is_null()) 624 if (!config_change_observer_cb_.is_null())
596 config_change_observer_cb_.Run(); 625 config_change_observer_cb_.Run();
597 626
598 state_ = STATE_FLUSHING_DECODER; 627 state_ = STATE_FLUSHING_DECODER;
599 if (!reset_cb_.is_null()) { 628 if (!reset_cb_.is_null()) {
600 // If we are using DecryptingDemuxerStream, we already called DDS::Reset() 629 // If we are using DecryptingDemuxerStream, we already called DDS::Reset()
601 // which will continue the resetting process in it's callback. 630 // which will continue the resetting process in its callback.
602 if (!decrypting_demuxer_stream_) 631 if (!decrypting_demuxer_stream_)
603 Reset(base::ResetAndReturn(&reset_cb_)); 632 Reset(base::ResetAndReturn(&reset_cb_));
604 // Reinitialization will continue after Reset() is done. 633 // Reinitialization will continue after Reset() is done.
605 } else { 634 } else {
606 FlushDecoder(); 635 FlushDecoder();
607 } 636 }
608 return; 637 return;
609 } 638 }
610 639
611 if (!reset_cb_.is_null()) { 640 if (!reset_cb_.is_null()) {
612 // If we are using DecryptingDemuxerStream, we already called DDS::Reset() 641 // If we are using DecryptingDemuxerStream, we already called DDS::Reset()
613 // which will continue the resetting process in it's callback. 642 // which will continue the resetting process in its callback.
614 if (!decrypting_demuxer_stream_) 643 if (!decrypting_demuxer_stream_)
615 Reset(base::ResetAndReturn(&reset_cb_)); 644 Reset(base::ResetAndReturn(&reset_cb_));
616 return; 645 return;
617 } 646 }
618 647
619 if (status == DemuxerStream::kAborted) { 648 if (status == DemuxerStream::kAborted) {
620 if (!read_cb_.is_null()) 649 if (!read_cb_.is_null())
621 SatisfyRead(DEMUXER_READ_ABORTED, NULL); 650 SatisfyRead(DEMUXER_READ_ABORTED, NULL);
622 return; 651 return;
623 } 652 }
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
740 } 769 }
741 770
742 // The resetting process will be continued in OnDecoderReinitialized(). 771 // The resetting process will be continued in OnDecoderReinitialized().
743 ReinitializeDecoder(); 772 ReinitializeDecoder();
744 } 773 }
745 774
746 template class DecoderStream<DemuxerStream::VIDEO>; 775 template class DecoderStream<DemuxerStream::VIDEO>;
747 template class DecoderStream<DemuxerStream::AUDIO>; 776 template class DecoderStream<DemuxerStream::AUDIO>;
748 777
749 } // namespace media 778 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/decoder_stream.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698