Index: media/filters/ffmpeg_audio_decoder.cc |
diff --git a/media/filters/ffmpeg_audio_decoder.cc b/media/filters/ffmpeg_audio_decoder.cc |
index a0e5889eff11aca7e6c84c6bdbf26080ca2fd8c0..546edf5c1de7288498728d59049f3deb4f43b215 100644 |
--- a/media/filters/ffmpeg_audio_decoder.cc |
+++ b/media/filters/ffmpeg_audio_decoder.cc |
@@ -115,6 +115,7 @@ void FFmpegAudioDecoder::Read(const ReadCB& read_cb) { |
DCHECK(task_runner_->BelongsToCurrentThread()); |
DCHECK(!read_cb.is_null()); |
CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; |
+ DCHECK(stop_cb_.is_null()); |
xhwang
2014/01/10 18:58:51
nit: check reset_cb as well?
|
read_cb_ = BindToCurrentLoop(read_cb); |
@@ -147,20 +148,24 @@ int FFmpegAudioDecoder::samples_per_second() { |
void FFmpegAudioDecoder::Reset(const base::Closure& closure) { |
DCHECK(task_runner_->BelongsToCurrentThread()); |
- base::Closure reset_cb = BindToCurrentLoop(closure); |
+ reset_cb_ = BindToCurrentLoop(closure); |
- avcodec_flush_buffers(codec_context_.get()); |
- ResetTimestampState(); |
- queued_audio_.clear(); |
- reset_cb.Run(); |
+ if (read_cb_.is_null()) |
+ DoReset(); |
+ // Otherwise a demuxer read is pending, we'll wait until it finishes. |
} |
-FFmpegAudioDecoder::~FFmpegAudioDecoder() { |
- // TODO(scherkus): should we require Stop() to be called? this might end up |
- // getting called on a random thread due to refcounting. |
- ReleaseFFmpegResources(); |
+void FFmpegAudioDecoder::Stop(const base::Closure& closure) { |
+ DCHECK(task_runner_->BelongsToCurrentThread()); |
+ stop_cb_ = BindToCurrentLoop(closure); |
+ |
+ if (read_cb_.is_null()) |
+ DoStop(); |
xhwang
2014/01/10 18:58:51
What if we are calling Stop() during a pending res
|
+ // Otherwise a demuxer read is pending, we'll wait until it finishes. |
} |
+FFmpegAudioDecoder::~FFmpegAudioDecoder() {} |
+ |
int FFmpegAudioDecoder::GetAudioBuffer(AVCodecContext* codec, |
AVFrame* frame, |
int flags) { |
@@ -226,6 +231,26 @@ int FFmpegAudioDecoder::GetAudioBuffer(AVCodecContext* codec, |
return 0; |
} |
+void FFmpegAudioDecoder::DoStop() { |
+ DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK(!stop_cb_.is_null()); |
+ |
xhwang
2014/01/10 18:58:51
check that no read and no reset is pending when we
|
+ ResetTimestampState(); |
+ queued_audio_.clear(); |
+ ReleaseFFmpegResources(); |
+ base::ResetAndReturn(&stop_cb_).Run(); |
+} |
+ |
+void FFmpegAudioDecoder::DoReset() { |
+ DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK(!reset_cb_.is_null()); |
xhwang
2014/01/10 18:58:51
check that no read is pending when we DoReset.
|
+ |
+ avcodec_flush_buffers(codec_context_.get()); |
+ ResetTimestampState(); |
+ queued_audio_.clear(); |
+ base::ResetAndReturn(&reset_cb_).Run(); |
+} |
+ |
void FFmpegAudioDecoder::ReadFromDemuxerStream() { |
DCHECK(!read_cb_.is_null()); |
demuxer_stream_->Read(base::Bind( |
@@ -240,6 +265,22 @@ void FFmpegAudioDecoder::BufferReady( |
DCHECK(queued_audio_.empty()); |
DCHECK_EQ(status != DemuxerStream::kOk, !input.get()) << status; |
+ // Stop() is pending, we'll ignore the buffer we just got, fire read_cb_, and |
+ // complete the Stop. |
+ if (!stop_cb_.is_null()) { |
+ base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
+ DoStop(); |
+ return; |
+ } |
+ |
+ // Reset() is pending, we'll ignore the buffer we just got, fire read_cb_, and |
+ // complete the Reset. |
+ if (!reset_cb_.is_null()) { |
+ base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
+ DoReset(); |
+ return; |
+ } |
+ |
xhwang
2014/01/10 18:58:51
If Stop() is called during pending reset, we shoul
|
if (status == DemuxerStream::kAborted) { |
DCHECK(!input.get()); |
base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |