Commit 4beec40b authored by xhwang@chromium.org's avatar xhwang@chromium.org

Fold DecoderStream::Stop() into the dtor.

BUG=349211
TEST=Existing tests pass.

Review URL: https://codereview.chromium.org/393313004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@283713 0039d316-1c4b-4281-b951-d872f2087c98
parent 317b66eb
...@@ -48,9 +48,9 @@ AudioRendererImpl::AudioRendererImpl( ...@@ -48,9 +48,9 @@ AudioRendererImpl::AudioRendererImpl(
AudioHardwareConfig* hardware_config) AudioHardwareConfig* hardware_config)
: task_runner_(task_runner), : task_runner_(task_runner),
sink_(sink), sink_(sink),
audio_buffer_stream_(task_runner, audio_buffer_stream_(new AudioBufferStream(task_runner,
decoders.Pass(), decoders.Pass(),
set_decryptor_ready_cb), set_decryptor_ready_cb)),
hardware_config_(hardware_config), hardware_config_(hardware_config),
state_(kUninitialized), state_(kUninitialized),
buffering_state_(BUFFERING_HAVE_NOTHING), buffering_state_(BUFFERING_HAVE_NOTHING),
...@@ -60,9 +60,9 @@ AudioRendererImpl::AudioRendererImpl( ...@@ -60,9 +60,9 @@ AudioRendererImpl::AudioRendererImpl(
received_end_of_stream_(false), received_end_of_stream_(false),
rendered_end_of_stream_(false), rendered_end_of_stream_(false),
weak_factory_(this) { weak_factory_(this) {
audio_buffer_stream_.set_splice_observer(base::Bind( audio_buffer_stream_->set_splice_observer(base::Bind(
&AudioRendererImpl::OnNewSpliceBuffer, weak_factory_.GetWeakPtr())); &AudioRendererImpl::OnNewSpliceBuffer, weak_factory_.GetWeakPtr()));
audio_buffer_stream_.set_config_change_observer(base::Bind( audio_buffer_stream_->set_config_change_observer(base::Bind(
&AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr())); &AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr()));
} }
...@@ -155,8 +155,8 @@ void AudioRendererImpl::DoFlush_Locked() { ...@@ -155,8 +155,8 @@ void AudioRendererImpl::DoFlush_Locked() {
DCHECK(!pending_read_); DCHECK(!pending_read_);
DCHECK_EQ(state_, kFlushed); DCHECK_EQ(state_, kFlushed);
audio_buffer_stream_.Reset(base::Bind(&AudioRendererImpl::ResetDecoderDone, audio_buffer_stream_->Reset(base::Bind(&AudioRendererImpl::ResetDecoderDone,
weak_factory_.GetWeakPtr())); weak_factory_.GetWeakPtr()));
} }
void AudioRendererImpl::ResetDecoderDone() { void AudioRendererImpl::ResetDecoderDone() {
...@@ -215,7 +215,8 @@ void AudioRendererImpl::Stop(const base::Closure& callback) { ...@@ -215,7 +215,8 @@ void AudioRendererImpl::Stop(const base::Closure& callback) {
sink_ = NULL; sink_ = NULL;
} }
audio_buffer_stream_.Stop(callback); audio_buffer_stream_.reset();
task_runner_->PostTask(FROM_HERE, callback);
} }
void AudioRendererImpl::StartPlayingFrom(base::TimeDelta timestamp) { void AudioRendererImpl::StartPlayingFrom(base::TimeDelta timestamp) {
...@@ -296,7 +297,7 @@ void AudioRendererImpl::Initialize(DemuxerStream* stream, ...@@ -296,7 +297,7 @@ void AudioRendererImpl::Initialize(DemuxerStream* stream,
audio_clock_.reset(new AudioClock(audio_parameters_.sample_rate())); audio_clock_.reset(new AudioClock(audio_parameters_.sample_rate()));
audio_buffer_stream_.Initialize( audio_buffer_stream_->Initialize(
stream, stream,
false, false,
statistics_cb, statistics_cb,
...@@ -486,8 +487,8 @@ void AudioRendererImpl::AttemptRead_Locked() { ...@@ -486,8 +487,8 @@ void AudioRendererImpl::AttemptRead_Locked() {
return; return;
pending_read_ = true; pending_read_ = true;
audio_buffer_stream_.Read(base::Bind(&AudioRendererImpl::DecodedAudioReady, audio_buffer_stream_->Read(base::Bind(&AudioRendererImpl::DecodedAudioReady,
weak_factory_.GetWeakPtr())); weak_factory_.GetWeakPtr()));
} }
bool AudioRendererImpl::CanRead_Locked() { bool AudioRendererImpl::CanRead_Locked() {
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <deque> #include <deque>
#include "base/gtest_prod_util.h" #include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/synchronization/lock.h" #include "base/synchronization/lock.h"
#include "media/base/audio_decoder.h" #include "media/base/audio_decoder.h"
...@@ -197,7 +198,7 @@ class MEDIA_EXPORT AudioRendererImpl ...@@ -197,7 +198,7 @@ class MEDIA_EXPORT AudioRendererImpl
// may deadlock between |task_runner_| and the audio callback thread. // may deadlock between |task_runner_| and the audio callback thread.
scoped_refptr<media::AudioRendererSink> sink_; scoped_refptr<media::AudioRendererSink> sink_;
AudioBufferStream audio_buffer_stream_; scoped_ptr<AudioBufferStream> audio_buffer_stream_;
// Interface to the hardware audio params. // Interface to the hardware audio params.
const AudioHardwareConfig* const hardware_config_; const AudioHardwareConfig* const hardware_config_;
......
...@@ -56,7 +56,30 @@ DecoderStream<StreamType>::DecoderStream( ...@@ -56,7 +56,30 @@ DecoderStream<StreamType>::DecoderStream(
template <DemuxerStream::Type StreamType> template <DemuxerStream::Type StreamType>
DecoderStream<StreamType>::~DecoderStream() { DecoderStream<StreamType>::~DecoderStream() {
DCHECK(state_ == STATE_UNINITIALIZED || state_ == STATE_STOPPED) << state_; FUNCTION_DVLOG(2);
DCHECK(task_runner_->BelongsToCurrentThread());
// TODO(xhwang): Fold DecoderSelector::Abort() into the dtor.
if (state_ == STATE_INITIALIZING)
decoder_selector_->Abort();
if (!init_cb_.is_null()) {
task_runner_->PostTask(FROM_HERE,
base::Bind(base::ResetAndReturn(&init_cb_), false));
}
if (!read_cb_.is_null()) {
task_runner_->PostTask(FROM_HERE, base::Bind(
base::ResetAndReturn(&read_cb_), ABORTED, scoped_refptr<Output>()));
}
if (!reset_cb_.is_null())
task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&reset_cb_));
if (decrypting_demuxer_stream_)
decrypting_demuxer_stream_->Stop();
stream_ = NULL;
decoder_.reset();
decrypting_demuxer_stream_.reset();
} }
template <DemuxerStream::Type StreamType> template <DemuxerStream::Type StreamType>
...@@ -89,13 +112,12 @@ template <DemuxerStream::Type StreamType> ...@@ -89,13 +112,12 @@ template <DemuxerStream::Type StreamType>
void DecoderStream<StreamType>::Read(const ReadCB& read_cb) { void DecoderStream<StreamType>::Read(const ReadCB& read_cb) {
FUNCTION_DVLOG(2); FUNCTION_DVLOG(2);
DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_INITIALIZING && DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_INITIALIZING)
state_ != STATE_STOPPED) << state_; << state_;
// No two reads in the flight at any time. // No two reads in the flight at any time.
DCHECK(read_cb_.is_null()); DCHECK(read_cb_.is_null());
// No read during resetting or stopping process. // No read during resetting or stopping process.
DCHECK(reset_cb_.is_null()); DCHECK(reset_cb_.is_null());
DCHECK(stop_cb_.is_null());
if (state_ == STATE_ERROR) { if (state_ == STATE_ERROR) {
task_runner_->PostTask( task_runner_->PostTask(
...@@ -125,9 +147,8 @@ template <DemuxerStream::Type StreamType> ...@@ -125,9 +147,8 @@ template <DemuxerStream::Type StreamType>
void DecoderStream<StreamType>::Reset(const base::Closure& closure) { void DecoderStream<StreamType>::Reset(const base::Closure& closure) {
FUNCTION_DVLOG(2); FUNCTION_DVLOG(2);
DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_STOPPED) << state_; DCHECK(state_ != STATE_UNINITIALIZED)<< state_;
DCHECK(reset_cb_.is_null()); DCHECK(reset_cb_.is_null());
DCHECK(stop_cb_.is_null());
reset_cb_ = closure; reset_cb_ = closure;
...@@ -159,45 +180,6 @@ void DecoderStream<StreamType>::Reset(const base::Closure& closure) { ...@@ -159,45 +180,6 @@ void DecoderStream<StreamType>::Reset(const base::Closure& closure) {
ResetDecoder(); ResetDecoder();
} }
template <DemuxerStream::Type StreamType>
void DecoderStream<StreamType>::Stop(const base::Closure& closure) {
FUNCTION_DVLOG(2);
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK_NE(state_, STATE_STOPPED) << state_;
DCHECK(stop_cb_.is_null());
// TODO(xhwang): This is the only asynchronousness in DecoderStream::Stop().
// Fix this so that we can merge the stopping code into the dtor.
if (state_ == STATE_INITIALIZING) {
stop_cb_ = closure;
decoder_selector_->Abort();
return;
}
DCHECK(init_cb_.is_null());
// All pending callbacks will be dropped.
weak_factory_.InvalidateWeakPtrs();
// Post callbacks to prevent reentrance into this object.
if (!read_cb_.is_null()) {
task_runner_->PostTask(FROM_HERE, base::Bind(
base::ResetAndReturn(&read_cb_), ABORTED, scoped_refptr<Output>()));
}
if (!reset_cb_.is_null())
task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&reset_cb_));
if (decrypting_demuxer_stream_)
decrypting_demuxer_stream_->Stop();
stream_ = NULL;
decoder_.reset();
decrypting_demuxer_stream_.reset();
state_ = STATE_STOPPED;
task_runner_->PostTask(FROM_HERE, closure);
}
template <DemuxerStream::Type StreamType> template <DemuxerStream::Type StreamType>
bool DecoderStream<StreamType>::CanReadWithoutStalling() const { bool DecoderStream<StreamType>::CanReadWithoutStalling() const {
DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK(task_runner_->BelongsToCurrentThread());
...@@ -251,19 +233,14 @@ void DecoderStream<StreamType>::OnDecoderSelected( ...@@ -251,19 +233,14 @@ void DecoderStream<StreamType>::OnDecoderSelected(
state_ = STATE_UNINITIALIZED; state_ = STATE_UNINITIALIZED;
StreamTraits::FinishInitialization( StreamTraits::FinishInitialization(
base::ResetAndReturn(&init_cb_), selected_decoder.get(), stream_); base::ResetAndReturn(&init_cb_), selected_decoder.get(), stream_);
} else {
state_ = STATE_NORMAL;
decoder_ = selected_decoder.Pass();
decrypting_demuxer_stream_ = decrypting_demuxer_stream.Pass();
StreamTraits::FinishInitialization(
base::ResetAndReturn(&init_cb_), decoder_.get(), stream_);
}
// Stop() called during initialization.
if (!stop_cb_.is_null()) {
Stop(base::ResetAndReturn(&stop_cb_));
return; return;
} }
state_ = STATE_NORMAL;
decoder_ = selected_decoder.Pass();
decrypting_demuxer_stream_ = decrypting_demuxer_stream.Pass();
StreamTraits::FinishInitialization(
base::ResetAndReturn(&init_cb_), decoder_.get(), stream_);
} }
template <DemuxerStream::Type StreamType> template <DemuxerStream::Type StreamType>
...@@ -281,7 +258,6 @@ void DecoderStream<StreamType>::Decode( ...@@ -281,7 +258,6 @@ void DecoderStream<StreamType>::Decode(
DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_; DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_;
DCHECK_LT(pending_decode_requests_, GetMaxDecodeRequests()); DCHECK_LT(pending_decode_requests_, GetMaxDecodeRequests());
DCHECK(reset_cb_.is_null()); DCHECK(reset_cb_.is_null());
DCHECK(stop_cb_.is_null());
DCHECK(buffer); DCHECK(buffer);
int buffer_size = buffer->end_of_stream() ? 0 : buffer->data_size(); int buffer_size = buffer->end_of_stream() ? 0 : buffer->data_size();
...@@ -308,7 +284,6 @@ void DecoderStream<StreamType>::OnDecodeDone(int buffer_size, ...@@ -308,7 +284,6 @@ void DecoderStream<StreamType>::OnDecodeDone(int buffer_size,
DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER || DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER ||
state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR) state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR)
<< state_; << state_;
DCHECK(stop_cb_.is_null());
DCHECK_GT(pending_decode_requests_, 0); DCHECK_GT(pending_decode_requests_, 0);
--pending_decode_requests_; --pending_decode_requests_;
...@@ -403,7 +378,6 @@ void DecoderStream<StreamType>::ReadFromDemuxerStream() { ...@@ -403,7 +378,6 @@ void DecoderStream<StreamType>::ReadFromDemuxerStream() {
DCHECK_EQ(state_, STATE_NORMAL) << state_; DCHECK_EQ(state_, STATE_NORMAL) << state_;
DCHECK(CanDecodeMore()); DCHECK(CanDecodeMore());
DCHECK(reset_cb_.is_null()); DCHECK(reset_cb_.is_null());
DCHECK(stop_cb_.is_null());
state_ = STATE_PENDING_DEMUXER_READ; state_ = STATE_PENDING_DEMUXER_READ;
stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady, stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady,
...@@ -418,15 +392,13 @@ void DecoderStream<StreamType>::OnBufferReady( ...@@ -418,15 +392,13 @@ void DecoderStream<StreamType>::OnBufferReady(
<< (buffer ? buffer->AsHumanReadableString() : "NULL"); << (buffer ? buffer->AsHumanReadableString() : "NULL");
DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR || DCHECK(state_ == STATE_PENDING_DEMUXER_READ || state_ == STATE_ERROR)
state_ == STATE_STOPPED)
<< state_; << state_;
DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status; DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status;
DCHECK(stop_cb_.is_null());
// Decoding has been stopped (e.g due to an error). // Decoding has been stopped (e.g due to an error).
if (state_ != STATE_PENDING_DEMUXER_READ) { if (state_ != STATE_PENDING_DEMUXER_READ) {
DCHECK(state_ == STATE_ERROR || state_ == STATE_STOPPED); DCHECK(state_ == STATE_ERROR);
DCHECK(read_cb_.is_null()); DCHECK(read_cb_.is_null());
return; return;
} }
...@@ -507,7 +479,6 @@ void DecoderStream<StreamType>::OnDecoderReinitialized(PipelineStatus status) { ...@@ -507,7 +479,6 @@ void DecoderStream<StreamType>::OnDecoderReinitialized(PipelineStatus status) {
FUNCTION_DVLOG(2); FUNCTION_DVLOG(2);
DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK_EQ(state_, STATE_REINITIALIZING_DECODER) << state_; DCHECK_EQ(state_, STATE_REINITIALIZING_DECODER) << state_;
DCHECK(stop_cb_.is_null());
// ReinitializeDecoder() can be called in two cases: // ReinitializeDecoder() can be called in two cases:
// 1, Flushing decoder finished (see OnDecodeOutputReady()). // 1, Flushing decoder finished (see OnDecodeOutputReady()).
...@@ -555,7 +526,6 @@ void DecoderStream<StreamType>::OnDecoderReset() { ...@@ -555,7 +526,6 @@ void DecoderStream<StreamType>::OnDecoderReset() {
// before the reset callback is fired. // before the reset callback is fired.
DCHECK(read_cb_.is_null()); DCHECK(read_cb_.is_null());
DCHECK(!reset_cb_.is_null()); DCHECK(!reset_cb_.is_null());
DCHECK(stop_cb_.is_null());
if (state_ != STATE_FLUSHING_DECODER) { if (state_ != STATE_FLUSHING_DECODER) {
state_ = STATE_NORMAL; state_ = STATE_NORMAL;
......
...@@ -65,23 +65,16 @@ class MEDIA_EXPORT DecoderStream { ...@@ -65,23 +65,16 @@ class MEDIA_EXPORT DecoderStream {
// Reads a decoded Output and returns it via the |read_cb|. Note that // Reads a decoded Output and returns it via the |read_cb|. Note that
// |read_cb| is always called asynchronously. This method should only be // |read_cb| is always called asynchronously. This method should only be
// called after initialization has succeeded and must not be called during // called after initialization has succeeded and must not be called during
// any pending Reset() and/or Stop(). // pending Reset().
void Read(const ReadCB& read_cb); void Read(const ReadCB& read_cb);
// Resets the decoder, flushes all decoded outputs and/or internal buffers, // Resets the decoder, flushes all decoded outputs and/or internal buffers,
// fires any existing pending read callback and calls |closure| on completion. // fires any existing pending read callback and calls |closure| on completion.
// Note that |closure| is always called asynchronously. This method should // Note that |closure| is always called asynchronously. This method should
// only be called after initialization has succeeded and must not be called // only be called after initialization has succeeded and must not be called
// during any pending Reset() and/or Stop(). // during pending Reset().
void Reset(const base::Closure& closure); void Reset(const base::Closure& closure);
// Stops the decoder, fires any existing pending read callback or reset
// callback and calls |closure| on completion. Note that |closure| is always
// called asynchronously. The DecoderStream cannot be used anymore after
// it is stopped. This method can be called at any time but not during another
// pending Stop().
void Stop(const base::Closure& closure);
// Returns true if the decoder currently has the ability to decode and return // Returns true if the decoder currently has the ability to decode and return
// an Output. // an Output.
// TODO(rileya): Remove the need for this by refactoring Decoder queueing // TODO(rileya): Remove the need for this by refactoring Decoder queueing
...@@ -117,12 +110,11 @@ class MEDIA_EXPORT DecoderStream { ...@@ -117,12 +110,11 @@ class MEDIA_EXPORT DecoderStream {
enum State { enum State {
STATE_UNINITIALIZED, STATE_UNINITIALIZED,
STATE_INITIALIZING, STATE_INITIALIZING,
STATE_NORMAL, // Includes idle, pending decoder decode/reset/stop. STATE_NORMAL, // Includes idle, pending decoder decode/reset.
STATE_FLUSHING_DECODER, STATE_FLUSHING_DECODER,
STATE_PENDING_DEMUXER_READ, STATE_PENDING_DEMUXER_READ,
STATE_REINITIALIZING_DECODER, STATE_REINITIALIZING_DECODER,
STATE_END_OF_STREAM, // End of stream reached; returns EOS on all reads. STATE_END_OF_STREAM, // End of stream reached; returns EOS on all reads.
STATE_STOPPED,
STATE_ERROR STATE_ERROR
}; };
...@@ -174,7 +166,6 @@ class MEDIA_EXPORT DecoderStream { ...@@ -174,7 +166,6 @@ class MEDIA_EXPORT DecoderStream {
ReadCB read_cb_; ReadCB read_cb_;
base::Closure reset_cb_; base::Closure reset_cb_;
base::Closure stop_cb_;
DemuxerStream* stream_; DemuxerStream* stream_;
bool low_delay_; bool low_delay_;
......
...@@ -76,14 +76,19 @@ class VideoFrameStreamTest ...@@ -76,14 +76,19 @@ class VideoFrameStreamTest
} }
~VideoFrameStreamTest() { ~VideoFrameStreamTest() {
// Check that the pipeline statistics callback was fired correctly.
if (decoder_)
EXPECT_EQ(decoder_->total_bytes_decoded(), total_bytes_decoded_);
is_initialized_ = false;
decoder_ = NULL;
video_frame_stream_.reset();
message_loop_.RunUntilIdle();
DCHECK(!pending_initialize_); DCHECK(!pending_initialize_);
DCHECK(!pending_read_); DCHECK(!pending_read_);
DCHECK(!pending_reset_); DCHECK(!pending_reset_);
DCHECK(!pending_stop_); DCHECK(!pending_stop_);
if (is_initialized_)
Stop();
EXPECT_FALSE(is_initialized_);
} }
MOCK_METHOD1(OnNewSpliceBuffer, void(base::TimeDelta)); MOCK_METHOD1(OnNewSpliceBuffer, void(base::TimeDelta));
...@@ -157,16 +162,6 @@ class VideoFrameStreamTest ...@@ -157,16 +162,6 @@ class VideoFrameStreamTest
pending_reset_ = false; pending_reset_ = false;
} }
void OnStopped() {
DCHECK(!pending_initialize_);
DCHECK(!pending_read_);
DCHECK(!pending_reset_);
DCHECK(pending_stop_);
pending_stop_ = false;
is_initialized_ = false;
decoder_ = NULL;
}
void ReadOneFrame() { void ReadOneFrame() {
frame_read_ = NULL; frame_read_ = NULL;
pending_read_ = true; pending_read_ = true;
...@@ -270,7 +265,7 @@ class VideoFrameStreamTest ...@@ -270,7 +265,7 @@ class VideoFrameStreamTest
break; break;
// These two cases are only interesting to test during // These two cases are only interesting to test during
// VideoFrameStream::Stop(). There's no need to satisfy a callback. // VideoFrameStream destruction. There's no need to satisfy a callback.
case SET_DECRYPTOR: case SET_DECRYPTOR:
case DECRYPTOR_NO_KEY: case DECRYPTOR_NO_KEY:
NOTREACHED(); NOTREACHED();
...@@ -315,15 +310,6 @@ class VideoFrameStreamTest ...@@ -315,15 +310,6 @@ class VideoFrameStreamTest
SatisfyPendingCallback(DECODER_RESET); SatisfyPendingCallback(DECODER_RESET);
} }
void Stop() {
// Check that the pipeline statistics callback was fired correctly.
EXPECT_EQ(decoder_->total_bytes_decoded(), total_bytes_decoded_);
pending_stop_ = true;
video_frame_stream_->Stop(base::Bind(&VideoFrameStreamTest::OnStopped,
base::Unretained(this)));
message_loop_.RunUntilIdle();
}
base::MessageLoop message_loop_; base::MessageLoop message_loop_;
scoped_ptr<VideoFrameStream> video_frame_stream_; scoped_ptr<VideoFrameStream> video_frame_stream_;
...@@ -577,118 +563,98 @@ TEST_P(VideoFrameStreamTest, Reset_DuringNoKeyRead) { ...@@ -577,118 +563,98 @@ TEST_P(VideoFrameStreamTest, Reset_DuringNoKeyRead) {
Reset(); Reset();
} }
TEST_P(VideoFrameStreamTest, Stop_BeforeInitialization) { // In the following Destroy_* tests, |video_frame_stream_| is destroyed in
pending_stop_ = true; // VideoFrameStreamTest dtor.
video_frame_stream_->Stop(
base::Bind(&VideoFrameStreamTest::OnStopped, base::Unretained(this))); TEST_P(VideoFrameStreamTest, Destroy_BeforeInitialization) {
message_loop_.RunUntilIdle();
} }
TEST_P(VideoFrameStreamTest, Stop_DuringSetDecryptor) { TEST_P(VideoFrameStreamTest, Destroy_DuringSetDecryptor) {
if (!GetParam().is_encrypted) { if (!GetParam().is_encrypted) {
DVLOG(1) << "SetDecryptor test only runs when the stream is encrytped."; DVLOG(1) << "SetDecryptor test only runs when the stream is encrytped.";
return; return;
} }
EnterPendingState(SET_DECRYPTOR); EnterPendingState(SET_DECRYPTOR);
pending_stop_ = true;
video_frame_stream_->Stop(
base::Bind(&VideoFrameStreamTest::OnStopped, base::Unretained(this)));
message_loop_.RunUntilIdle();
} }
TEST_P(VideoFrameStreamTest, Stop_DuringInitialization) { TEST_P(VideoFrameStreamTest, Destroy_DuringInitialization) {
EnterPendingState(DECODER_INIT); EnterPendingState(DECODER_INIT);
Stop();
} }
TEST_P(VideoFrameStreamTest, Stop_AfterInitialization) { TEST_P(VideoFrameStreamTest, Destroy_AfterInitialization) {
Initialize(); Initialize();
Stop();
} }
TEST_P(VideoFrameStreamTest, Stop_DuringReinitialization) { TEST_P(VideoFrameStreamTest, Destroy_DuringReinitialization) {
Initialize(); Initialize();
EnterPendingState(DECODER_REINIT); EnterPendingState(DECODER_REINIT);
Stop();
} }
TEST_P(VideoFrameStreamTest, Stop_AfterReinitialization) { TEST_P(VideoFrameStreamTest, Destroy_AfterReinitialization) {
Initialize(); Initialize();
EnterPendingState(DECODER_REINIT); EnterPendingState(DECODER_REINIT);
SatisfyPendingCallback(DECODER_REINIT); SatisfyPendingCallback(DECODER_REINIT);
Stop();
} }
TEST_P(VideoFrameStreamTest, Stop_DuringDemuxerRead_Normal) { TEST_P(VideoFrameStreamTest, Destroy_DuringDemuxerRead_Normal) {
Initialize(); Initialize();
EnterPendingState(DEMUXER_READ_NORMAL); EnterPendingState(DEMUXER_READ_NORMAL);
Stop();
} }
TEST_P(VideoFrameStreamTest, Stop_DuringDemuxerRead_ConfigChange) { TEST_P(VideoFrameStreamTest, Destroy_DuringDemuxerRead_ConfigChange) {
Initialize(); Initialize();
EnterPendingState(DEMUXER_READ_CONFIG_CHANGE); EnterPendingState(DEMUXER_READ_CONFIG_CHANGE);
Stop();
} }
TEST_P(VideoFrameStreamTest, Stop_DuringNormalDecoderDecode) { TEST_P(VideoFrameStreamTest, Destroy_DuringNormalDecoderDecode) {
Initialize(); Initialize();
EnterPendingState(DECODER_DECODE); EnterPendingState(DECODER_DECODE);
Stop();
} }
TEST_P(VideoFrameStreamTest, Stop_AfterNormalRead) { TEST_P(VideoFrameStreamTest, Destroy_AfterNormalRead) {
Initialize(); Initialize();
Read(); Read();
Stop();
} }
TEST_P(VideoFrameStreamTest, Stop_AfterConfigChangeRead) { TEST_P(VideoFrameStreamTest, Destroy_AfterConfigChangeRead) {
Initialize(); Initialize();
EnterPendingState(DEMUXER_READ_CONFIG_CHANGE); EnterPendingState(DEMUXER_READ_CONFIG_CHANGE);
SatisfyPendingCallback(DEMUXER_READ_CONFIG_CHANGE); SatisfyPendingCallback(DEMUXER_READ_CONFIG_CHANGE);
Stop();
} }
TEST_P(VideoFrameStreamTest, Stop_DuringNoKeyRead) { TEST_P(VideoFrameStreamTest, Destroy_DuringNoKeyRead) {
Initialize(); Initialize();
EnterPendingState(DECRYPTOR_NO_KEY); EnterPendingState(DECRYPTOR_NO_KEY);
Stop();
} }
TEST_P(VideoFrameStreamTest, Stop_DuringReset) { TEST_P(VideoFrameStreamTest, Destroy_DuringReset) {
Initialize(); Initialize();
EnterPendingState(DECODER_RESET); EnterPendingState(DECODER_RESET);
Stop();
} }
TEST_P(VideoFrameStreamTest, Stop_AfterReset) { TEST_P(VideoFrameStreamTest, Destroy_AfterReset) {
Initialize(); Initialize();
Reset(); Reset();
Stop();
} }
TEST_P(VideoFrameStreamTest, Stop_DuringRead_DuringReset) { TEST_P(VideoFrameStreamTest, Destroy_DuringRead_DuringReset) {
Initialize(); Initialize();
EnterPendingState(DECODER_DECODE); EnterPendingState(DECODER_DECODE);
EnterPendingState(DECODER_RESET); EnterPendingState(DECODER_RESET);
Stop();
} }
TEST_P(VideoFrameStreamTest, Stop_AfterRead_DuringReset) { TEST_P(VideoFrameStreamTest, Destroy_AfterRead_DuringReset) {
Initialize(); Initialize();
EnterPendingState(DECODER_DECODE); EnterPendingState(DECODER_DECODE);
EnterPendingState(DECODER_RESET); EnterPendingState(DECODER_RESET);
SatisfyPendingCallback(DECODER_DECODE); SatisfyPendingCallback(DECODER_DECODE);
Stop();
} }
TEST_P(VideoFrameStreamTest, Stop_AfterRead_AfterReset) { TEST_P(VideoFrameStreamTest, Destroy_AfterRead_AfterReset) {
Initialize(); Initialize();
Read(); Read();
Reset(); Reset();
Stop();
} }
TEST_P(VideoFrameStreamTest, DecoderErrorWhenReading) { TEST_P(VideoFrameStreamTest, DecoderErrorWhenReading) {
......
...@@ -25,7 +25,9 @@ VideoRendererImpl::VideoRendererImpl( ...@@ -25,7 +25,9 @@ VideoRendererImpl::VideoRendererImpl(
const PaintCB& paint_cb, const PaintCB& paint_cb,
bool drop_frames) bool drop_frames)
: task_runner_(task_runner), : task_runner_(task_runner),
video_frame_stream_(task_runner, decoders.Pass(), set_decryptor_ready_cb), video_frame_stream_(new VideoFrameStream(task_runner,
decoders.Pass(),
set_decryptor_ready_cb)),
low_delay_(false), low_delay_(false),
received_end_of_stream_(false), received_end_of_stream_(false),
rendered_end_of_stream_(false), rendered_end_of_stream_(false),
...@@ -66,7 +68,7 @@ void VideoRendererImpl::Flush(const base::Closure& callback) { ...@@ -66,7 +68,7 @@ void VideoRendererImpl::Flush(const base::Closure& callback) {
received_end_of_stream_ = false; received_end_of_stream_ = false;
rendered_end_of_stream_ = false; rendered_end_of_stream_ = false;
video_frame_stream_.Reset( video_frame_stream_->Reset(
base::Bind(&VideoRendererImpl::OnVideoFrameStreamResetDone, base::Bind(&VideoRendererImpl::OnVideoFrameStreamResetDone,
weak_factory_.GetWeakPtr())); weak_factory_.GetWeakPtr()));
} }
...@@ -75,7 +77,7 @@ void VideoRendererImpl::Stop(const base::Closure& callback) { ...@@ -75,7 +77,7 @@ void VideoRendererImpl::Stop(const base::Closure& callback) {
DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK(task_runner_->BelongsToCurrentThread());
base::AutoLock auto_lock(lock_); base::AutoLock auto_lock(lock_);
if (state_ == kUninitialized || state_ == kStopped) { if (state_ == kUninitialized || state_ == kStopped) {
callback.Run(); task_runner_->PostTask(FROM_HERE, callback);
return; return;
} }
...@@ -102,7 +104,8 @@ void VideoRendererImpl::Stop(const base::Closure& callback) { ...@@ -102,7 +104,8 @@ void VideoRendererImpl::Stop(const base::Closure& callback) {
base::PlatformThread::Join(thread_to_join); base::PlatformThread::Join(thread_to_join);
} }
video_frame_stream_.Stop(callback); video_frame_stream_.reset();
task_runner_->PostTask(FROM_HERE, callback);
} }
void VideoRendererImpl::StartPlayingFrom(base::TimeDelta timestamp) { void VideoRendererImpl::StartPlayingFrom(base::TimeDelta timestamp) {
...@@ -153,7 +156,7 @@ void VideoRendererImpl::Initialize(DemuxerStream* stream, ...@@ -153,7 +156,7 @@ void VideoRendererImpl::Initialize(DemuxerStream* stream,
get_duration_cb_ = get_duration_cb; get_duration_cb_ = get_duration_cb;
state_ = kInitializing; state_ = kInitializing;
video_frame_stream_.Initialize( video_frame_stream_->Initialize(
stream, stream,
low_delay, low_delay,
statistics_cb, statistics_cb,
...@@ -360,7 +363,7 @@ void VideoRendererImpl::FrameReady(VideoFrameStream::Status status, ...@@ -360,7 +363,7 @@ void VideoRendererImpl::FrameReady(VideoFrameStream::Status status,
bool VideoRendererImpl::HaveEnoughData_Locked() { bool VideoRendererImpl::HaveEnoughData_Locked() {
DCHECK_EQ(state_, kPlaying); DCHECK_EQ(state_, kPlaying);
return received_end_of_stream_ || return received_end_of_stream_ ||
!video_frame_stream_.CanReadWithoutStalling() || !video_frame_stream_->CanReadWithoutStalling() ||
ready_frames_.size() >= static_cast<size_t>(limits::kMaxVideoFrames) || ready_frames_.size() >= static_cast<size_t>(limits::kMaxVideoFrames) ||
(low_delay_ && ready_frames_.size() > 0); (low_delay_ && ready_frames_.size() > 0);
} }
...@@ -440,8 +443,8 @@ void VideoRendererImpl::AttemptRead_Locked() { ...@@ -440,8 +443,8 @@ void VideoRendererImpl::AttemptRead_Locked() {
switch (state_) { switch (state_) {
case kPlaying: case kPlaying:
pending_read_ = true; pending_read_ = true;
video_frame_stream_.Read(base::Bind(&VideoRendererImpl::FrameReady, video_frame_stream_->Read(base::Bind(&VideoRendererImpl::FrameReady,
weak_factory_.GetWeakPtr())); weak_factory_.GetWeakPtr()));
return; return;
case kUninitialized: case kUninitialized:
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <deque> #include <deque>
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h" #include "base/memory/scoped_vector.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/synchronization/condition_variable.h" #include "base/synchronization/condition_variable.h"
...@@ -123,7 +124,7 @@ class MEDIA_EXPORT VideoRendererImpl ...@@ -123,7 +124,7 @@ class MEDIA_EXPORT VideoRendererImpl
base::Lock lock_; base::Lock lock_;
// Provides video frames to VideoRendererImpl. // Provides video frames to VideoRendererImpl.
VideoFrameStream video_frame_stream_; scoped_ptr<VideoFrameStream> video_frame_stream_;
// Flag indicating low-delay mode. // Flag indicating low-delay mode.
bool low_delay_; bool low_delay_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment