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

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

Issue 331863004: Revert 276344 "Add callback in VideoDecoder and AudioDecoder to ..." (Closed) Base URL: svn://svn.chromium.org/chrome/branches/2049/src/
Patch Set: Created 6 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « media/filters/ffmpeg_audio_decoder.h ('k') | media/filters/ffmpeg_audio_decoder_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/callback_helpers.h" 7 #include "base/callback_helpers.h"
8 #include "base/single_thread_task_runner.h" 8 #include "base/single_thread_task_runner.h"
9 #include "media/base/audio_buffer.h" 9 #include "media/base/audio_buffer.h"
10 #include "media/base/audio_bus.h" 10 #include "media/base/audio_bus.h"
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 log_cb_(log_cb) { 134 log_cb_(log_cb) {
135 } 135 }
136 136
137 FFmpegAudioDecoder::~FFmpegAudioDecoder() { 137 FFmpegAudioDecoder::~FFmpegAudioDecoder() {
138 DCHECK_EQ(state_, kUninitialized); 138 DCHECK_EQ(state_, kUninitialized);
139 DCHECK(!codec_context_); 139 DCHECK(!codec_context_);
140 DCHECK(!av_frame_); 140 DCHECK(!av_frame_);
141 } 141 }
142 142
143 void FFmpegAudioDecoder::Initialize(const AudioDecoderConfig& config, 143 void FFmpegAudioDecoder::Initialize(const AudioDecoderConfig& config,
144 const PipelineStatusCB& status_cb, 144 const PipelineStatusCB& status_cb) {
145 const OutputCB& output_cb) {
146 DCHECK(task_runner_->BelongsToCurrentThread()); 145 DCHECK(task_runner_->BelongsToCurrentThread());
147 DCHECK(!config.is_encrypted()); 146 DCHECK(!config.is_encrypted());
148 147
149 FFmpegGlue::InitializeFFmpeg(); 148 FFmpegGlue::InitializeFFmpeg();
150 149
151 config_ = config; 150 config_ = config;
152 PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb); 151 PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb);
153 152
154 if (!config.IsValidConfig() || !ConfigureDecoder()) { 153 if (!config.IsValidConfig() || !ConfigureDecoder()) {
155 initialize_cb.Run(DECODER_ERROR_NOT_SUPPORTED); 154 initialize_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
156 return; 155 return;
157 } 156 }
158 157
159 // Success! 158 // Success!
160 output_cb_ = BindToCurrentLoop(output_cb);
161 state_ = kNormal; 159 state_ = kNormal;
162 initialize_cb.Run(PIPELINE_OK); 160 initialize_cb.Run(PIPELINE_OK);
163 } 161 }
164 162
165 void FFmpegAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, 163 void FFmpegAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
166 const DecodeCB& decode_cb) { 164 const DecodeCB& decode_cb) {
167 DCHECK(task_runner_->BelongsToCurrentThread()); 165 DCHECK(task_runner_->BelongsToCurrentThread());
168 DCHECK(!decode_cb.is_null()); 166 DCHECK(!decode_cb.is_null());
169 CHECK_NE(state_, kUninitialized); 167 CHECK_NE(state_, kUninitialized);
170 DecodeCB decode_cb_bound = BindToCurrentLoop(decode_cb); 168 DecodeCB decode_cb_bound = BindToCurrentLoop(decode_cb);
171 169
172 if (state_ == kError) { 170 if (state_ == kError) {
173 decode_cb_bound.Run(kDecodeError); 171 decode_cb_bound.Run(kDecodeError, NULL);
174 return; 172 return;
175 } 173 }
176 174
177 // Do nothing if decoding has finished. 175 // Return empty frames if decoding has finished.
178 if (state_ == kDecodeFinished) { 176 if (state_ == kDecodeFinished) {
179 decode_cb_bound.Run(kOk); 177 decode_cb_bound.Run(kOk, AudioBuffer::CreateEOSBuffer());
178 return;
179 }
180
181 if (!buffer) {
182 decode_cb_bound.Run(kAborted, NULL);
180 return; 183 return;
181 } 184 }
182 185
183 DecodeBuffer(buffer, decode_cb_bound); 186 DecodeBuffer(buffer, decode_cb_bound);
184 } 187 }
185 188
189 scoped_refptr<AudioBuffer> FFmpegAudioDecoder::GetDecodeOutput() {
190 DCHECK(task_runner_->BelongsToCurrentThread());
191 if (queued_audio_.empty())
192 return NULL;
193 scoped_refptr<AudioBuffer> out = queued_audio_.front();
194 queued_audio_.pop_front();
195 return out;
196 }
197
186 void FFmpegAudioDecoder::Reset(const base::Closure& closure) { 198 void FFmpegAudioDecoder::Reset(const base::Closure& closure) {
187 DCHECK(task_runner_->BelongsToCurrentThread()); 199 DCHECK(task_runner_->BelongsToCurrentThread());
188 200
189 avcodec_flush_buffers(codec_context_.get()); 201 avcodec_flush_buffers(codec_context_.get());
190 state_ = kNormal; 202 state_ = kNormal;
191 ResetTimestampState(); 203 ResetTimestampState();
192 task_runner_->PostTask(FROM_HERE, closure); 204 task_runner_->PostTask(FROM_HERE, closure);
193 } 205 }
194 206
195 void FFmpegAudioDecoder::Stop() { 207 void FFmpegAudioDecoder::Stop() {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 // When avcodec_decode_audio4() returns 0 data. 250 // When avcodec_decode_audio4() returns 0 data.
239 // kFlushCodec -> kError: 251 // kFlushCodec -> kError:
240 // When avcodec_decode_audio4() errors out. 252 // When avcodec_decode_audio4() errors out.
241 // (any state) -> kNormal: 253 // (any state) -> kNormal:
242 // Any time Reset() is called. 254 // Any time Reset() is called.
243 255
244 // Make sure we are notified if http://crbug.com/49709 returns. Issue also 256 // Make sure we are notified if http://crbug.com/49709 returns. Issue also
245 // occurs with some damaged files. 257 // occurs with some damaged files.
246 if (!buffer->end_of_stream() && buffer->timestamp() == kNoTimestamp()) { 258 if (!buffer->end_of_stream() && buffer->timestamp() == kNoTimestamp()) {
247 DVLOG(1) << "Received a buffer without timestamps!"; 259 DVLOG(1) << "Received a buffer without timestamps!";
248 decode_cb.Run(kDecodeError); 260 decode_cb.Run(kDecodeError, NULL);
249 return; 261 return;
250 } 262 }
251 263
252 if (!buffer->end_of_stream() && !discard_helper_->initialized() && 264 if (!buffer->end_of_stream() && !discard_helper_->initialized() &&
253 codec_context_->codec_id == AV_CODEC_ID_VORBIS && 265 codec_context_->codec_id == AV_CODEC_ID_VORBIS &&
254 buffer->timestamp() < base::TimeDelta()) { 266 buffer->timestamp() < base::TimeDelta()) {
255 // Dropping frames for negative timestamps as outlined in section A.2 267 // Dropping frames for negative timestamps as outlined in section A.2
256 // in the Vorbis spec. http://xiph.org/vorbis/doc/Vorbis_I_spec.html 268 // in the Vorbis spec. http://xiph.org/vorbis/doc/Vorbis_I_spec.html
257 const int discard_frames = 269 const int discard_frames =
258 discard_helper_->TimeDeltaToFrames(-buffer->timestamp()); 270 discard_helper_->TimeDeltaToFrames(-buffer->timestamp());
259 discard_helper_->Reset(discard_frames); 271 discard_helper_->Reset(discard_frames);
260 } 272 }
261 273
274 // Transition to kFlushCodec on the first end of stream buffer.
275 if (state_ == kNormal && buffer->end_of_stream()) {
276 state_ = kFlushCodec;
277 }
278
262 if (!FFmpegDecode(buffer)) { 279 if (!FFmpegDecode(buffer)) {
263 state_ = kError; 280 state_ = kError;
264 decode_cb.Run(kDecodeError); 281 decode_cb.Run(kDecodeError, NULL);
265 return; 282 return;
266 } 283 }
267 284
268 if (buffer->end_of_stream()) { 285 if (queued_audio_.empty()) {
269 state_ = kDecodeFinished; 286 if (state_ == kFlushCodec) {
270 output_cb_.Run(AudioBuffer::CreateEOSBuffer()); 287 DCHECK(buffer->end_of_stream());
288 state_ = kDecodeFinished;
289 decode_cb.Run(kOk, AudioBuffer::CreateEOSBuffer());
290 return;
291 }
292
293 decode_cb.Run(kNotEnoughData, NULL);
294 return;
271 } 295 }
272 296
273 decode_cb.Run(kOk); 297 decode_cb.Run(kOk, queued_audio_.front());
298 queued_audio_.pop_front();
274 } 299 }
275 300
276 bool FFmpegAudioDecoder::FFmpegDecode( 301 bool FFmpegAudioDecoder::FFmpegDecode(
277 const scoped_refptr<DecoderBuffer>& buffer) { 302 const scoped_refptr<DecoderBuffer>& buffer) {
303 DCHECK(queued_audio_.empty());
304
278 AVPacket packet; 305 AVPacket packet;
279 av_init_packet(&packet); 306 av_init_packet(&packet);
280 if (buffer->end_of_stream()) { 307 if (buffer->end_of_stream()) {
281 packet.data = NULL; 308 packet.data = NULL;
282 packet.size = 0; 309 packet.size = 0;
283 } else { 310 } else {
284 packet.data = const_cast<uint8*>(buffer->data()); 311 packet.data = const_cast<uint8*>(buffer->data());
285 packet.size = buffer->data_size(); 312 packet.size = buffer->data_size();
286 } 313 }
287 314
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 << ", Sample Format: " << av_frame_->format << " vs " 355 << ", Sample Format: " << av_frame_->format << " vs "
329 << av_sample_format_; 356 << av_sample_format_;
330 357
331 if (config_.codec() == kCodecAAC && 358 if (config_.codec() == kCodecAAC &&
332 av_frame_->sample_rate == 2 * config_.samples_per_second()) { 359 av_frame_->sample_rate == 2 * config_.samples_per_second()) {
333 MEDIA_LOG(log_cb_) << "Implicit HE-AAC signalling is being used." 360 MEDIA_LOG(log_cb_) << "Implicit HE-AAC signalling is being used."
334 << " Please use mp4a.40.5 instead of mp4a.40.2 in" 361 << " Please use mp4a.40.5 instead of mp4a.40.2 in"
335 << " the mimetype."; 362 << " the mimetype.";
336 } 363 }
337 // This is an unrecoverable error, so bail out. 364 // This is an unrecoverable error, so bail out.
365 queued_audio_.clear();
338 av_frame_unref(av_frame_.get()); 366 av_frame_unref(av_frame_.get());
339 return false; 367 return false;
340 } 368 }
341 369
342 // Get the AudioBuffer that the data was decoded into. Adjust the number 370 // Get the AudioBuffer that the data was decoded into. Adjust the number
343 // of frames, in case fewer than requested were actually decoded. 371 // of frames, in case fewer than requested were actually decoded.
344 output = reinterpret_cast<AudioBuffer*>( 372 output = reinterpret_cast<AudioBuffer*>(
345 av_buffer_get_opaque(av_frame_->buf[0])); 373 av_buffer_get_opaque(av_frame_->buf[0]));
346 374
347 DCHECK_EQ(ChannelLayoutToChannelCount(config_.channel_layout()), 375 DCHECK_EQ(ChannelLayoutToChannelCount(config_.channel_layout()),
348 output->channel_count()); 376 output->channel_count());
349 const int unread_frames = output->frame_count() - av_frame_->nb_samples; 377 const int unread_frames = output->frame_count() - av_frame_->nb_samples;
350 DCHECK_GE(unread_frames, 0); 378 DCHECK_GE(unread_frames, 0);
351 if (unread_frames > 0) 379 if (unread_frames > 0)
352 output->TrimEnd(unread_frames); 380 output->TrimEnd(unread_frames);
353 av_frame_unref(av_frame_.get()); 381 av_frame_unref(av_frame_.get());
354 } 382 }
355 383
356 // WARNING: |av_frame_| no longer has valid data at this point. 384 // WARNING: |av_frame_| no longer has valid data at this point.
357 const int decoded_frames = frame_decoded ? output->frame_count() : 0; 385 const int decoded_frames = frame_decoded ? output->frame_count() : 0;
358 if (IsEndOfStream(result, decoded_frames, buffer)) { 386 if (IsEndOfStream(result, decoded_frames, buffer)) {
359 DCHECK_EQ(packet.size, 0); 387 DCHECK_EQ(packet.size, 0);
360 output_cb_.Run(AudioBuffer::CreateEOSBuffer()); 388 queued_audio_.push_back(AudioBuffer::CreateEOSBuffer());
361 } else if (discard_helper_->ProcessBuffers(buffer, output)) { 389 } else if (discard_helper_->ProcessBuffers(buffer, output)) {
362 output_cb_.Run(output); 390 queued_audio_.push_back(output);
363 } 391 }
364 } while (packet.size > 0); 392 } while (packet.size > 0);
365 393
366 return true; 394 return true;
367 } 395 }
368 396
369 void FFmpegAudioDecoder::ReleaseFFmpegResources() { 397 void FFmpegAudioDecoder::ReleaseFFmpegResources() {
370 codec_context_.reset(); 398 codec_context_.reset();
371 av_frame_.reset(); 399 av_frame_.reset();
372 } 400 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 453
426 ResetTimestampState(); 454 ResetTimestampState();
427 return true; 455 return true;
428 } 456 }
429 457
430 void FFmpegAudioDecoder::ResetTimestampState() { 458 void FFmpegAudioDecoder::ResetTimestampState() {
431 discard_helper_->Reset(config_.codec_delay()); 459 discard_helper_->Reset(config_.codec_delay());
432 } 460 }
433 461
434 } // namespace media 462 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/ffmpeg_audio_decoder.h ('k') | media/filters/ffmpeg_audio_decoder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698