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

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: 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(stop_cb_.is_null());
119 DCHECK(reset_cb_.is_null());
xhwang 2014/01/10 22:14:15 nit: change the order of these two lines
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 if (read_cb_.is_null())
153 ResetTimestampState(); 155 DoReset();
154 queued_audio_.clear(); 156 // Otherwise a demuxer read is pending, we'll wait until it finishes.
155 reset_cb.Run();
156 } 157 }
157 158
158 FFmpegAudioDecoder::~FFmpegAudioDecoder() { 159 void FFmpegAudioDecoder::Stop(const base::Closure& closure) {
159 // TODO(scherkus): should we require Stop() to be called? this might end up 160 DCHECK(task_runner_->BelongsToCurrentThread());
160 // getting called on a random thread due to refcounting. 161 stop_cb_ = BindToCurrentLoop(closure);
161 ReleaseFFmpegResources(); 162
163 if (read_cb_.is_null()) {
xhwang 2014/01/10 22:14:15 We like to check abnormal cases and return early.
164 if (!reset_cb_.is_null())
165 DoReset();
rileya (GONE FROM CHROMIUM) 2014/01/10 21:35:06 As-is I don't think(?) this will ever happen (Rese
xhwang 2014/01/10 22:14:15 That's correct. Feel free to DCHECK here :)
166 else
167 DoStop();
168 }
169 // Otherwise a demuxer read is pending, we'll wait until it finishes.
162 } 170 }
163 171
172 FFmpegAudioDecoder::~FFmpegAudioDecoder() {}
173
164 int FFmpegAudioDecoder::GetAudioBuffer(AVCodecContext* codec, 174 int FFmpegAudioDecoder::GetAudioBuffer(AVCodecContext* codec,
165 AVFrame* frame, 175 AVFrame* frame,
166 int flags) { 176 int flags) {
167 // Since this routine is called by FFmpeg when a buffer is required for audio 177 // 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). 178 // data, use the values supplied by FFmpeg (ignoring the current settings).
169 // RunDecodeLoop() gets to determine if the buffer is useable or not. 179 // RunDecodeLoop() gets to determine if the buffer is useable or not.
170 AVSampleFormat format = static_cast<AVSampleFormat>(frame->format); 180 AVSampleFormat format = static_cast<AVSampleFormat>(frame->format);
171 SampleFormat sample_format = AVSampleFormatToSampleFormat(format); 181 SampleFormat sample_format = AVSampleFormatToSampleFormat(format);
172 int channels = DetermineChannels(frame); 182 int channels = DetermineChannels(frame);
173 if ((channels <= 0) || (channels >= limits::kMaxChannels)) { 183 if ((channels <= 0) || (channels >= limits::kMaxChannels)) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 229
220 // Now create an AVBufferRef for the data just allocated. It will own the 230 // Now create an AVBufferRef for the data just allocated. It will own the
221 // reference to the AudioBuffer object. 231 // reference to the AudioBuffer object.
222 void* opaque = NULL; 232 void* opaque = NULL;
223 buffer.swap(reinterpret_cast<AudioBuffer**>(&opaque)); 233 buffer.swap(reinterpret_cast<AudioBuffer**>(&opaque));
224 frame->buf[0] = av_buffer_create( 234 frame->buf[0] = av_buffer_create(
225 frame->data[0], buffer_size_in_bytes, ReleaseAudioBufferImpl, opaque, 0); 235 frame->data[0], buffer_size_in_bytes, ReleaseAudioBufferImpl, opaque, 0);
226 return 0; 236 return 0;
227 } 237 }
228 238
239 void FFmpegAudioDecoder::DoStop() {
240 DCHECK(task_runner_->BelongsToCurrentThread());
241 DCHECK(!stop_cb_.is_null());
242 DCHECK(read_cb_.is_null());
243 DCHECK(reset_cb_.is_null());
244
245 ResetTimestampState();
246 queued_audio_.clear();
247 ReleaseFFmpegResources();
248 base::ResetAndReturn(&stop_cb_).Run();
249 }
250
251 void FFmpegAudioDecoder::DoReset() {
252 DCHECK(task_runner_->BelongsToCurrentThread());
253 DCHECK(!reset_cb_.is_null());
254 DCHECK(read_cb_.is_null());
255
256 avcodec_flush_buffers(codec_context_.get());
257 ResetTimestampState();
258 queued_audio_.clear();
259 base::ResetAndReturn(&reset_cb_).Run();
260
261 if (!stop_cb_.is_null())
262 DoStop();
263 }
264
229 void FFmpegAudioDecoder::ReadFromDemuxerStream() { 265 void FFmpegAudioDecoder::ReadFromDemuxerStream() {
230 DCHECK(!read_cb_.is_null()); 266 DCHECK(!read_cb_.is_null());
231 demuxer_stream_->Read(base::Bind( 267 demuxer_stream_->Read(base::Bind(
232 &FFmpegAudioDecoder::BufferReady, weak_this_)); 268 &FFmpegAudioDecoder::BufferReady, weak_this_));
233 } 269 }
234 270
235 void FFmpegAudioDecoder::BufferReady( 271 void FFmpegAudioDecoder::BufferReady(
236 DemuxerStream::Status status, 272 DemuxerStream::Status status,
237 const scoped_refptr<DecoderBuffer>& input) { 273 const scoped_refptr<DecoderBuffer>& input) {
238 DCHECK(task_runner_->BelongsToCurrentThread()); 274 DCHECK(task_runner_->BelongsToCurrentThread());
239 DCHECK(!read_cb_.is_null()); 275 DCHECK(!read_cb_.is_null());
240 DCHECK(queued_audio_.empty()); 276 DCHECK(queued_audio_.empty());
241 DCHECK_EQ(status != DemuxerStream::kOk, !input.get()) << status; 277 DCHECK_EQ(status != DemuxerStream::kOk, !input.get()) << status;
242 278
279 // Pending Reset: ignore the buffer we just got, send kAborted to |read_cb_|
280 // and carry out the Reset().
281 // If there happens to also be a pending Stop(), that will be handled at
282 // the end of DoReset().
283 if (!reset_cb_.is_null()) {
284 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
285 DoReset();
286 return;
287 }
288
289 // Pending Stop: ignore the buffer we just got, send kAborted to |read_cb_|
290 // and carry out the Stop().
291 if (!stop_cb_.is_null()) {
292 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
293 DoStop();
294 return;
295 }
296
243 if (status == DemuxerStream::kAborted) { 297 if (status == DemuxerStream::kAborted) {
244 DCHECK(!input.get()); 298 DCHECK(!input.get());
245 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); 299 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
246 return; 300 return;
247 } 301 }
248 302
249 if (status == DemuxerStream::kConfigChanged) { 303 if (status == DemuxerStream::kConfigChanged) {
250 DCHECK(!input.get()); 304 DCHECK(!input.get());
251 305
252 // Send a "end of stream" buffer to the decode loop 306 // 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. 586 // Decoding finished successfully, update statistics.
533 if (result > 0) { 587 if (result > 0) {
534 PipelineStatistics statistics; 588 PipelineStatistics statistics;
535 statistics.audio_bytes_decoded = result; 589 statistics.audio_bytes_decoded = result;
536 statistics_cb_.Run(statistics); 590 statistics_cb_.Run(statistics);
537 } 591 }
538 } while (packet.size > 0); 592 } while (packet.size > 0);
539 } 593 }
540 594
541 } // namespace media 595 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698