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

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

Issue 17408005: Refactored DecoderBuffer to use unix_hacker_style naming. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@localrefactor
Patch Set: Fixed naming error that somehow got reverted" Created 7 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
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/message_loop/message_loop_proxy.h" 10 #include "base/message_loop/message_loop_proxy.h"
(...skipping 10 matching lines...) Expand all
21 21
22 namespace media { 22 namespace media {
23 23
24 // Helper structure for managing multiple decoded audio frames per packet. 24 // Helper structure for managing multiple decoded audio frames per packet.
25 struct QueuedAudioBuffer { 25 struct QueuedAudioBuffer {
26 AudioDecoder::Status status; 26 AudioDecoder::Status status;
27 scoped_refptr<DataBuffer> buffer; 27 scoped_refptr<DataBuffer> buffer;
28 }; 28 };
29 29
30 // Returns true if the decode result was end of stream. 30 // Returns true if the decode result was end of stream.
31 static inline bool IsEndOfStream(int result, int decoded_size, 31 static inline bool end_of_stream(int result, int decoded_size,
scherkus (not reviewing) 2013/06/22 00:09:28 revert this change
32 const scoped_refptr<DecoderBuffer>& input) { 32 const scoped_refptr<DecoderBuffer>& input) {
33 // Three conditions to meet to declare end of stream for this decoder: 33 // Three conditions to meet to declare end of stream for this decoder:
34 // 1. FFmpeg didn't read anything. 34 // 1. FFmpeg didn't read anything.
35 // 2. FFmpeg didn't output anything. 35 // 2. FFmpeg didn't output anything.
36 // 3. An end of stream buffer is received. 36 // 3. An end of stream buffer is received.
37 return result == 0 && decoded_size == 0 && input->IsEndOfStream(); 37 return result == 0 && decoded_size == 0 && input->end_of_stream();
38 } 38 }
39 39
40 FFmpegAudioDecoder::FFmpegAudioDecoder( 40 FFmpegAudioDecoder::FFmpegAudioDecoder(
41 const scoped_refptr<base::MessageLoopProxy>& message_loop) 41 const scoped_refptr<base::MessageLoopProxy>& message_loop)
42 : message_loop_(message_loop), 42 : message_loop_(message_loop),
43 weak_factory_(this), 43 weak_factory_(this),
44 demuxer_stream_(NULL), 44 demuxer_stream_(NULL),
45 codec_context_(NULL), 45 codec_context_(NULL),
46 bits_per_channel_(0), 46 bits_per_channel_(0),
47 channel_layout_(CHANNEL_LAYOUT_NONE), 47 channel_layout_(CHANNEL_LAYOUT_NONE),
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 queued_audio_.front().status, queued_audio_.front().buffer); 177 queued_audio_.front().status, queued_audio_.front().buffer);
178 queued_audio_.pop_front(); 178 queued_audio_.pop_front();
179 return; 179 return;
180 } 180 }
181 181
182 DCHECK_EQ(status, DemuxerStream::kOk); 182 DCHECK_EQ(status, DemuxerStream::kOk);
183 DCHECK(input.get()); 183 DCHECK(input.get());
184 184
185 // Make sure we are notified if http://crbug.com/49709 returns. Issue also 185 // Make sure we are notified if http://crbug.com/49709 returns. Issue also
186 // occurs with some damaged files. 186 // occurs with some damaged files.
187 if (!input->IsEndOfStream() && input->GetTimestamp() == kNoTimestamp() && 187 if (!input->end_of_stream() && input->timestamp() == kNoTimestamp() &&
188 output_timestamp_helper_->base_timestamp() == kNoTimestamp()) { 188 output_timestamp_helper_->base_timestamp() == kNoTimestamp()) {
189 DVLOG(1) << "Received a buffer without timestamps!"; 189 DVLOG(1) << "Received a buffer without timestamps!";
190 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); 190 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL);
191 return; 191 return;
192 } 192 }
193 193
194 bool is_vorbis = codec_context_->codec_id == AV_CODEC_ID_VORBIS; 194 bool is_vorbis = codec_context_->codec_id == AV_CODEC_ID_VORBIS;
195 if (!input->IsEndOfStream()) { 195 if (!input->end_of_stream()) {
196 if (last_input_timestamp_ == kNoTimestamp()) { 196 if (last_input_timestamp_ == kNoTimestamp()) {
197 if (is_vorbis && (input->GetTimestamp() < base::TimeDelta())) { 197 if (is_vorbis && (input->timestamp() < base::TimeDelta())) {
198 // Dropping frames for negative timestamps as outlined in section A.2 198 // Dropping frames for negative timestamps as outlined in section A.2
199 // in the Vorbis spec. http://xiph.org/vorbis/doc/Vorbis_I_spec.html 199 // in the Vorbis spec. http://xiph.org/vorbis/doc/Vorbis_I_spec.html
200 int frames_to_drop = floor( 200 int frames_to_drop = floor(
201 0.5 + -input->GetTimestamp().InSecondsF() * samples_per_second_); 201 0.5 + -input->timestamp().InSecondsF() * samples_per_second_);
202 output_bytes_to_drop_ = bytes_per_frame_ * frames_to_drop; 202 output_bytes_to_drop_ = bytes_per_frame_ * frames_to_drop;
203 } else { 203 } else {
204 last_input_timestamp_ = input->GetTimestamp(); 204 last_input_timestamp_ = input->timestamp();
205 } 205 }
206 } else if (input->GetTimestamp() != kNoTimestamp()) { 206 } else if (input->timestamp() != kNoTimestamp()) {
207 if (input->GetTimestamp() < last_input_timestamp_) { 207 if (input->timestamp() < last_input_timestamp_) {
208 base::TimeDelta diff = input->GetTimestamp() - last_input_timestamp_; 208 base::TimeDelta diff = input->timestamp() - last_input_timestamp_;
209 DVLOG(1) << "Input timestamps are not monotonically increasing! " 209 DVLOG(1) << "Input timestamps are not monotonically increasing! "
210 << " ts " << input->GetTimestamp().InMicroseconds() << " us" 210 << " ts " << input->timestamp().InMicroseconds() << " us"
211 << " diff " << diff.InMicroseconds() << " us"; 211 << " diff " << diff.InMicroseconds() << " us";
212 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); 212 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL);
213 return; 213 return;
214 } 214 }
215 215
216 last_input_timestamp_ = input->GetTimestamp(); 216 last_input_timestamp_ = input->timestamp();
217 } 217 }
218 } 218 }
219 219
220 RunDecodeLoop(input, false); 220 RunDecodeLoop(input, false);
221 221
222 // We exhausted the provided packet, but it wasn't enough for a frame. Ask 222 // We exhausted the provided packet, but it wasn't enough for a frame. Ask
223 // for more data in order to fulfill this read. 223 // for more data in order to fulfill this read.
224 if (queued_audio_.empty()) { 224 if (queued_audio_.empty()) {
225 ReadFromDemuxerStream(); 225 ReadFromDemuxerStream();
226 return; 226 return;
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); 334 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp());
335 last_input_timestamp_ = kNoTimestamp(); 335 last_input_timestamp_ = kNoTimestamp();
336 output_bytes_to_drop_ = 0; 336 output_bytes_to_drop_ = 0;
337 } 337 }
338 338
339 void FFmpegAudioDecoder::RunDecodeLoop( 339 void FFmpegAudioDecoder::RunDecodeLoop(
340 const scoped_refptr<DecoderBuffer>& input, 340 const scoped_refptr<DecoderBuffer>& input,
341 bool skip_eos_append) { 341 bool skip_eos_append) {
342 AVPacket packet; 342 AVPacket packet;
343 av_init_packet(&packet); 343 av_init_packet(&packet);
344 if (input->IsEndOfStream()) { 344 if (input->end_of_stream()) {
345 packet.data = NULL; 345 packet.data = NULL;
346 packet.size = 0; 346 packet.size = 0;
347 } else { 347 } else {
348 packet.data = const_cast<uint8*>(input->GetData()); 348 packet.data = const_cast<uint8*>(input->data());
349 packet.size = input->GetDataSize(); 349 packet.size = input->data_size();
350 } 350 }
351 351
352 // Each audio packet may contain several frames, so we must call the decoder 352 // Each audio packet may contain several frames, so we must call the decoder
353 // until we've exhausted the packet. Regardless of the packet size we always 353 // until we've exhausted the packet. Regardless of the packet size we always
354 // want to hand it to the decoder at least once, otherwise we would end up 354 // want to hand it to the decoder at least once, otherwise we would end up
355 // skipping end of stream packets since they have a size of zero. 355 // skipping end of stream packets since they have a size of zero.
356 do { 356 do {
357 // Reset frame to default values. 357 // Reset frame to default values.
358 avcodec_get_frame_defaults(av_frame_); 358 avcodec_get_frame_defaults(av_frame_);
359 359
360 int frame_decoded = 0; 360 int frame_decoded = 0;
361 int result = avcodec_decode_audio4( 361 int result = avcodec_decode_audio4(
362 codec_context_, av_frame_, &frame_decoded, &packet); 362 codec_context_, av_frame_, &frame_decoded, &packet);
363 363
364 if (result < 0) { 364 if (result < 0) {
365 DCHECK(!input->IsEndOfStream()) 365 DCHECK(!input->end_of_stream())
366 << "End of stream buffer produced an error! " 366 << "End of stream buffer produced an error! "
367 << "This is quite possibly a bug in the audio decoder not handling " 367 << "This is quite possibly a bug in the audio decoder not handling "
368 << "end of stream AVPackets correctly."; 368 << "end of stream AVPackets correctly.";
369 369
370 DLOG(ERROR) 370 DLOG(ERROR)
371 << "Error decoding an audio frame with timestamp: " 371 << "Error decoding an audio frame with timestamp: "
372 << input->GetTimestamp().InMicroseconds() << " us, duration: " 372 << input->timestamp().InMicroseconds() << " us, duration: "
373 << input->GetDuration().InMicroseconds() << " us, packet size: " 373 << input->duration().InMicroseconds() << " us, packet size: "
374 << input->GetDataSize() << " bytes"; 374 << input->data_size() << " bytes";
375 375
376 // TODO(dalecurtis): We should return a kDecodeError here instead: 376 // TODO(dalecurtis): We should return a kDecodeError here instead:
377 // http://crbug.com/145276 377 // http://crbug.com/145276
378 break; 378 break;
379 } 379 }
380 380
381 // Update packet size and data pointer in case we need to call the decoder 381 // Update packet size and data pointer in case we need to call the decoder
382 // with the remaining bytes from this packet. 382 // with the remaining bytes from this packet.
383 packet.size -= result; 383 packet.size -= result;
384 packet.data += result; 384 packet.data += result;
385 385
386 if (output_timestamp_helper_->base_timestamp() == kNoTimestamp() && 386 if (output_timestamp_helper_->base_timestamp() == kNoTimestamp() &&
387 !input->IsEndOfStream()) { 387 !input->end_of_stream()) {
388 DCHECK(input->GetTimestamp() != kNoTimestamp()); 388 DCHECK(input->timestamp() != kNoTimestamp());
389 if (output_bytes_to_drop_ > 0) { 389 if (output_bytes_to_drop_ > 0) {
390 // Currently Vorbis is the only codec that causes us to drop samples. 390 // Currently Vorbis is the only codec that causes us to drop samples.
391 // If we have to drop samples it always means the timeline starts at 0. 391 // If we have to drop samples it always means the timeline starts at 0.
392 DCHECK_EQ(codec_context_->codec_id, AV_CODEC_ID_VORBIS); 392 DCHECK_EQ(codec_context_->codec_id, AV_CODEC_ID_VORBIS);
393 output_timestamp_helper_->SetBaseTimestamp(base::TimeDelta()); 393 output_timestamp_helper_->SetBaseTimestamp(base::TimeDelta());
394 } else { 394 } else {
395 output_timestamp_helper_->SetBaseTimestamp(input->GetTimestamp()); 395 output_timestamp_helper_->SetBaseTimestamp(input->timestamp());
396 } 396 }
397 } 397 }
398 398
399 int decoded_audio_size = 0; 399 int decoded_audio_size = 0;
400 #ifdef CHROMIUM_NO_AVFRAME_CHANNELS 400 #ifdef CHROMIUM_NO_AVFRAME_CHANNELS
401 int channels = av_get_channel_layout_nb_channels( 401 int channels = av_get_channel_layout_nb_channels(
402 av_frame_->channel_layout); 402 av_frame_->channel_layout);
403 #else 403 #else
404 int channels = av_frame_->channels; 404 int channels = av_frame_->channels;
405 #endif 405 #endif
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 output->writable_data()); 478 output->writable_data());
479 } else { 479 } else {
480 output = DataBuffer::CopyFrom( 480 output = DataBuffer::CopyFrom(
481 av_frame_->extended_data[0] + start_sample * bytes_per_frame_, 481 av_frame_->extended_data[0] + start_sample * bytes_per_frame_,
482 decoded_audio_size); 482 decoded_audio_size);
483 } 483 }
484 output->set_timestamp(output_timestamp_helper_->GetTimestamp()); 484 output->set_timestamp(output_timestamp_helper_->GetTimestamp());
485 output->set_duration( 485 output->set_duration(
486 output_timestamp_helper_->GetDuration(decoded_audio_size)); 486 output_timestamp_helper_->GetDuration(decoded_audio_size));
487 output_timestamp_helper_->AddBytes(decoded_audio_size); 487 output_timestamp_helper_->AddBytes(decoded_audio_size);
488 } else if (IsEndOfStream(result, decoded_audio_size, input) && 488 } else if (end_of_stream(result, decoded_audio_size, input) &&
489 !skip_eos_append) { 489 !skip_eos_append) {
490 DCHECK_EQ(packet.size, 0); 490 DCHECK_EQ(packet.size, 0);
491 output = DataBuffer::CreateEOSBuffer(); 491 output = DataBuffer::CreateEOSBuffer();
492 } 492 }
493 493
494 if (output.get()) { 494 if (output.get()) {
495 QueuedAudioBuffer queue_entry = { kOk, output }; 495 QueuedAudioBuffer queue_entry = { kOk, output };
496 queued_audio_.push_back(queue_entry); 496 queued_audio_.push_back(queue_entry);
497 } 497 }
498 498
499 // Decoding finished successfully, update statistics. 499 // Decoding finished successfully, update statistics.
500 if (result > 0) { 500 if (result > 0) {
501 PipelineStatistics statistics; 501 PipelineStatistics statistics;
502 statistics.audio_bytes_decoded = result; 502 statistics.audio_bytes_decoded = result;
503 statistics_cb_.Run(statistics); 503 statistics_cb_.Run(statistics);
504 } 504 }
505 } while (packet.size > 0); 505 } while (packet.size > 0);
506 } 506 }
507 507
508 } // namespace media 508 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698