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

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

Issue 126793002: Add Stop() to AudioDecoder. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Some opus audio decoder cleanup Created 6 years, 11 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/ffmpeg_audio_decoder.h" 5 #include "media/filters/ffmpeg_audio_decoder.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/callback_helpers.h" 8 #include "base/callback_helpers.h"
9 #include "base/location.h" 9 #include "base/location.h"
10 #include "base/single_thread_task_runner.h" 10 #include "base/single_thread_task_runner.h"
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 } 108 }
109 109
110 statistics_cb_ = statistics_cb; 110 statistics_cb_ = statistics_cb;
111 initialize_cb.Run(PIPELINE_OK); 111 initialize_cb.Run(PIPELINE_OK);
112 } 112 }
113 113
114 void FFmpegAudioDecoder::Read(const ReadCB& read_cb) { 114 void FFmpegAudioDecoder::Read(const ReadCB& read_cb) {
115 DCHECK(task_runner_->BelongsToCurrentThread()); 115 DCHECK(task_runner_->BelongsToCurrentThread());
116 DCHECK(!read_cb.is_null()); 116 DCHECK(!read_cb.is_null());
117 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; 117 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported.";
118 DCHECK(reset_cb_.is_null());
119 DCHECK(stop_cb_.is_null());
118 120
119 read_cb_ = BindToCurrentLoop(read_cb); 121 read_cb_ = BindToCurrentLoop(read_cb);
120 122
121 // If we don't have any queued audio from the last packet we decoded, ask for 123 // If we don't have any queued audio from the last packet we decoded, ask for
122 // more data from the demuxer to satisfy this read. 124 // more data from the demuxer to satisfy this read.
123 if (queued_audio_.empty()) { 125 if (queued_audio_.empty()) {
124 ReadFromDemuxerStream(); 126 ReadFromDemuxerStream();
125 return; 127 return;
126 } 128 }
127 129
(...skipping 12 matching lines...) Expand all
140 return channel_layout_; 142 return channel_layout_;
141 } 143 }
142 144
143 int FFmpegAudioDecoder::samples_per_second() { 145 int FFmpegAudioDecoder::samples_per_second() {
144 DCHECK(task_runner_->BelongsToCurrentThread()); 146 DCHECK(task_runner_->BelongsToCurrentThread());
145 return samples_per_second_; 147 return samples_per_second_;
146 } 148 }
147 149
148 void FFmpegAudioDecoder::Reset(const base::Closure& closure) { 150 void FFmpegAudioDecoder::Reset(const base::Closure& closure) {
149 DCHECK(task_runner_->BelongsToCurrentThread()); 151 DCHECK(task_runner_->BelongsToCurrentThread());
150 base::Closure reset_cb = BindToCurrentLoop(closure); 152 reset_cb_ = BindToCurrentLoop(closure);
151 153
152 avcodec_flush_buffers(codec_context_.get()); 154 // A demuxer read is pending, we'll wait until it finishes.
153 ResetTimestampState(); 155 if (!read_cb_.is_null())
154 queued_audio_.clear(); 156 return;
155 reset_cb.Run(); 157
158 DoReset();
156 } 159 }
157 160
158 FFmpegAudioDecoder::~FFmpegAudioDecoder() { 161 void FFmpegAudioDecoder::Stop(const base::Closure& closure) {
159 // TODO(scherkus): should we require Stop() to be called? this might end up 162 DCHECK(task_runner_->BelongsToCurrentThread());
160 // getting called on a random thread due to refcounting. 163 stop_cb_ = BindToCurrentLoop(closure);
161 ReleaseFFmpegResources(); 164
165 // A demuxer read is pending, we'll wait until it finishes.
166 if (!read_cb_.is_null())
167 return;
168
169 if (!reset_cb_.is_null())
170 DoReset();
xhwang 2014/01/14 22:25:02 nit: ... DoReset(); return; } DoSt
rileya (GONE FROM CHROMIUM) 2014/01/14 23:02:40 Fixed.
171 else
172 DoStop();
162 } 173 }
163 174
175 FFmpegAudioDecoder::~FFmpegAudioDecoder() {}
176
164 int FFmpegAudioDecoder::GetAudioBuffer(AVCodecContext* codec, 177 int FFmpegAudioDecoder::GetAudioBuffer(AVCodecContext* codec,
165 AVFrame* frame, 178 AVFrame* frame,
166 int flags) { 179 int flags) {
167 // Since this routine is called by FFmpeg when a buffer is required for audio 180 // Since this routine is called by FFmpeg when a buffer is required for audio
168 // data, use the values supplied by FFmpeg (ignoring the current settings). 181 // data, use the values supplied by FFmpeg (ignoring the current settings).
169 // RunDecodeLoop() gets to determine if the buffer is useable or not. 182 // RunDecodeLoop() gets to determine if the buffer is useable or not.
170 AVSampleFormat format = static_cast<AVSampleFormat>(frame->format); 183 AVSampleFormat format = static_cast<AVSampleFormat>(frame->format);
171 SampleFormat sample_format = AVSampleFormatToSampleFormat(format); 184 SampleFormat sample_format = AVSampleFormatToSampleFormat(format);
172 int channels = DetermineChannels(frame); 185 int channels = DetermineChannels(frame);
173 if ((channels <= 0) || (channels >= limits::kMaxChannels)) { 186 if ((channels <= 0) || (channels >= limits::kMaxChannels)) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 232
220 // Now create an AVBufferRef for the data just allocated. It will own the 233 // Now create an AVBufferRef for the data just allocated. It will own the
221 // reference to the AudioBuffer object. 234 // reference to the AudioBuffer object.
222 void* opaque = NULL; 235 void* opaque = NULL;
223 buffer.swap(reinterpret_cast<AudioBuffer**>(&opaque)); 236 buffer.swap(reinterpret_cast<AudioBuffer**>(&opaque));
224 frame->buf[0] = av_buffer_create( 237 frame->buf[0] = av_buffer_create(
225 frame->data[0], buffer_size_in_bytes, ReleaseAudioBufferImpl, opaque, 0); 238 frame->data[0], buffer_size_in_bytes, ReleaseAudioBufferImpl, opaque, 0);
226 return 0; 239 return 0;
227 } 240 }
228 241
242 void FFmpegAudioDecoder::DoStop() {
243 DCHECK(task_runner_->BelongsToCurrentThread());
244 DCHECK(!stop_cb_.is_null());
245 DCHECK(read_cb_.is_null());
246 DCHECK(reset_cb_.is_null());
247
248 ResetTimestampState();
249 queued_audio_.clear();
250 ReleaseFFmpegResources();
251 base::ResetAndReturn(&stop_cb_).Run();
252 }
253
254 void FFmpegAudioDecoder::DoReset() {
255 DCHECK(task_runner_->BelongsToCurrentThread());
256 DCHECK(!reset_cb_.is_null());
257 DCHECK(read_cb_.is_null());
258
259 avcodec_flush_buffers(codec_context_.get());
260 ResetTimestampState();
261 queued_audio_.clear();
262 base::ResetAndReturn(&reset_cb_).Run();
263
264 if (!stop_cb_.is_null())
265 DoStop();
266 }
267
229 void FFmpegAudioDecoder::ReadFromDemuxerStream() { 268 void FFmpegAudioDecoder::ReadFromDemuxerStream() {
230 DCHECK(!read_cb_.is_null()); 269 DCHECK(!read_cb_.is_null());
231 demuxer_stream_->Read(base::Bind( 270 demuxer_stream_->Read(base::Bind(
232 &FFmpegAudioDecoder::BufferReady, weak_this_)); 271 &FFmpegAudioDecoder::BufferReady, weak_this_));
233 } 272 }
234 273
235 void FFmpegAudioDecoder::BufferReady( 274 void FFmpegAudioDecoder::BufferReady(
236 DemuxerStream::Status status, 275 DemuxerStream::Status status,
237 const scoped_refptr<DecoderBuffer>& input) { 276 const scoped_refptr<DecoderBuffer>& input) {
238 DCHECK(task_runner_->BelongsToCurrentThread()); 277 DCHECK(task_runner_->BelongsToCurrentThread());
239 DCHECK(!read_cb_.is_null()); 278 DCHECK(!read_cb_.is_null());
240 DCHECK(queued_audio_.empty()); 279 DCHECK(queued_audio_.empty());
241 DCHECK_EQ(status != DemuxerStream::kOk, !input.get()) << status; 280 DCHECK_EQ(status != DemuxerStream::kOk, !input.get()) << status;
242 281
282 // Pending Reset: ignore the buffer we just got, send kAborted to |read_cb_|
283 // and carry out the Reset().
284 // If there happens to also be a pending Stop(), that will be handled at
285 // the end of DoReset().
286 if (!reset_cb_.is_null()) {
287 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
288 DoReset();
289 return;
290 }
291
292 // Pending Stop: ignore the buffer we just got, send kAborted to |read_cb_|
293 // and carry out the Stop().
294 if (!stop_cb_.is_null()) {
295 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
296 DoStop();
297 return;
298 }
299
243 if (status == DemuxerStream::kAborted) { 300 if (status == DemuxerStream::kAborted) {
244 DCHECK(!input.get()); 301 DCHECK(!input.get());
245 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); 302 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
246 return; 303 return;
247 } 304 }
248 305
249 if (status == DemuxerStream::kConfigChanged) { 306 if (status == DemuxerStream::kConfigChanged) {
250 DCHECK(!input.get()); 307 DCHECK(!input.get());
251 308
252 // Send a "end of stream" buffer to the decode loop 309 // Send a "end of stream" buffer to the decode loop
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
532 // Decoding finished successfully, update statistics. 589 // Decoding finished successfully, update statistics.
533 if (result > 0) { 590 if (result > 0) {
534 PipelineStatistics statistics; 591 PipelineStatistics statistics;
535 statistics.audio_bytes_decoded = result; 592 statistics.audio_bytes_decoded = result;
536 statistics_cb_.Run(statistics); 593 statistics_cb_.Run(statistics);
537 } 594 }
538 } while (packet.size > 0); 595 } while (packet.size > 0);
539 } 596 }
540 597
541 } // namespace media 598 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698