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

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: Created 7 years, 5 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 IsEndOfStream(int result,
32 int decoded_size,
32 const scoped_refptr<DecoderBuffer>& input) { 33 const scoped_refptr<DecoderBuffer>& input) {
33 // Three conditions to meet to declare end of stream for this decoder: 34 // Three conditions to meet to declare end of stream for this decoder:
34 // 1. FFmpeg didn't read anything. 35 // 1. FFmpeg didn't read anything.
35 // 2. FFmpeg didn't output anything. 36 // 2. FFmpeg didn't output anything.
36 // 3. An end of stream buffer is received. 37 // 3. An end of stream buffer is received.
37 return result == 0 && decoded_size == 0 && input->IsEndOfStream(); 38 return result == 0 && decoded_size == 0 && input->end_of_stream();
38 } 39 }
39 40
40 FFmpegAudioDecoder::FFmpegAudioDecoder( 41 FFmpegAudioDecoder::FFmpegAudioDecoder(
41 const scoped_refptr<base::MessageLoopProxy>& message_loop) 42 const scoped_refptr<base::MessageLoopProxy>& message_loop)
42 : message_loop_(message_loop), 43 : message_loop_(message_loop),
43 weak_factory_(this), 44 weak_factory_(this),
44 demuxer_stream_(NULL), 45 demuxer_stream_(NULL),
45 codec_context_(NULL), 46 codec_context_(NULL),
46 bits_per_channel_(0), 47 bits_per_channel_(0),
47 channel_layout_(CHANNEL_LAYOUT_NONE), 48 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); 178 queued_audio_.front().status, queued_audio_.front().buffer);
178 queued_audio_.pop_front(); 179 queued_audio_.pop_front();
179 return; 180 return;
180 } 181 }
181 182
182 DCHECK_EQ(status, DemuxerStream::kOk); 183 DCHECK_EQ(status, DemuxerStream::kOk);
183 DCHECK(input.get()); 184 DCHECK(input.get());
184 185
185 // Make sure we are notified if http://crbug.com/49709 returns. Issue also 186 // Make sure we are notified if http://crbug.com/49709 returns. Issue also
186 // occurs with some damaged files. 187 // occurs with some damaged files.
187 if (!input->IsEndOfStream() && input->GetTimestamp() == kNoTimestamp() && 188 if (!input->end_of_stream() && input->timestamp() == kNoTimestamp() &&
188 output_timestamp_helper_->base_timestamp() == kNoTimestamp()) { 189 output_timestamp_helper_->base_timestamp() == kNoTimestamp()) {
189 DVLOG(1) << "Received a buffer without timestamps!"; 190 DVLOG(1) << "Received a buffer without timestamps!";
190 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); 191 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL);
191 return; 192 return;
192 } 193 }
193 194
194 bool is_vorbis = codec_context_->codec_id == AV_CODEC_ID_VORBIS; 195 bool is_vorbis = codec_context_->codec_id == AV_CODEC_ID_VORBIS;
195 if (!input->IsEndOfStream()) { 196 if (!input->end_of_stream()) {
196 if (last_input_timestamp_ == kNoTimestamp()) { 197 if (last_input_timestamp_ == kNoTimestamp()) {
197 if (is_vorbis && (input->GetTimestamp() < base::TimeDelta())) { 198 if (is_vorbis && (input->timestamp() < base::TimeDelta())) {
198 // Dropping frames for negative timestamps as outlined in section A.2 199 // 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 200 // in the Vorbis spec. http://xiph.org/vorbis/doc/Vorbis_I_spec.html
200 int frames_to_drop = floor( 201 int frames_to_drop = floor(
201 0.5 + -input->GetTimestamp().InSecondsF() * samples_per_second_); 202 0.5 + -input->timestamp().InSecondsF() * samples_per_second_);
202 output_bytes_to_drop_ = bytes_per_frame_ * frames_to_drop; 203 output_bytes_to_drop_ = bytes_per_frame_ * frames_to_drop;
203 } else { 204 } else {
204 last_input_timestamp_ = input->GetTimestamp(); 205 last_input_timestamp_ = input->timestamp();
205 } 206 }
206 } else if (input->GetTimestamp() != kNoTimestamp()) { 207 } else if (input->timestamp() != kNoTimestamp()) {
207 if (input->GetTimestamp() < last_input_timestamp_) { 208 if (input->timestamp() < last_input_timestamp_) {
208 base::TimeDelta diff = input->GetTimestamp() - last_input_timestamp_; 209 base::TimeDelta diff = input->timestamp() - last_input_timestamp_;
209 DVLOG(1) << "Input timestamps are not monotonically increasing! " 210 DVLOG(1) << "Input timestamps are not monotonically increasing! "
210 << " ts " << input->GetTimestamp().InMicroseconds() << " us" 211 << " ts " << input->timestamp().InMicroseconds() << " us"
211 << " diff " << diff.InMicroseconds() << " us"; 212 << " diff " << diff.InMicroseconds() << " us";
212 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); 213 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL);
213 return; 214 return;
214 } 215 }
215 216
216 last_input_timestamp_ = input->GetTimestamp(); 217 last_input_timestamp_ = input->timestamp();
217 } 218 }
218 } 219 }
219 220
220 RunDecodeLoop(input, false); 221 RunDecodeLoop(input, false);
221 222
222 // We exhausted the provided packet, but it wasn't enough for a frame. Ask 223 // We exhausted the provided packet, but it wasn't enough for a frame. Ask
223 // for more data in order to fulfill this read. 224 // for more data in order to fulfill this read.
224 if (queued_audio_.empty()) { 225 if (queued_audio_.empty()) {
225 ReadFromDemuxerStream(); 226 ReadFromDemuxerStream();
226 return; 227 return;
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); 335 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp());
335 last_input_timestamp_ = kNoTimestamp(); 336 last_input_timestamp_ = kNoTimestamp();
336 output_bytes_to_drop_ = 0; 337 output_bytes_to_drop_ = 0;
337 } 338 }
338 339
339 void FFmpegAudioDecoder::RunDecodeLoop( 340 void FFmpegAudioDecoder::RunDecodeLoop(
340 const scoped_refptr<DecoderBuffer>& input, 341 const scoped_refptr<DecoderBuffer>& input,
341 bool skip_eos_append) { 342 bool skip_eos_append) {
342 AVPacket packet; 343 AVPacket packet;
343 av_init_packet(&packet); 344 av_init_packet(&packet);
344 if (input->IsEndOfStream()) { 345 if (input->end_of_stream()) {
345 packet.data = NULL; 346 packet.data = NULL;
346 packet.size = 0; 347 packet.size = 0;
347 } else { 348 } else {
348 packet.data = const_cast<uint8*>(input->GetData()); 349 packet.data = const_cast<uint8*>(input->data());
349 packet.size = input->GetDataSize(); 350 packet.size = input->data_size();
350 } 351 }
351 352
352 // Each audio packet may contain several frames, so we must call the decoder 353 // 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 354 // 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 355 // 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. 356 // skipping end of stream packets since they have a size of zero.
356 do { 357 do {
357 // Reset frame to default values. 358 // Reset frame to default values.
358 avcodec_get_frame_defaults(av_frame_); 359 avcodec_get_frame_defaults(av_frame_);
359 360
360 int frame_decoded = 0; 361 int frame_decoded = 0;
361 int result = avcodec_decode_audio4( 362 int result = avcodec_decode_audio4(
362 codec_context_, av_frame_, &frame_decoded, &packet); 363 codec_context_, av_frame_, &frame_decoded, &packet);
363 364
364 if (result < 0) { 365 if (result < 0) {
365 DCHECK(!input->IsEndOfStream()) 366 DCHECK(!input->end_of_stream())
366 << "End of stream buffer produced an error! " 367 << "End of stream buffer produced an error! "
367 << "This is quite possibly a bug in the audio decoder not handling " 368 << "This is quite possibly a bug in the audio decoder not handling "
368 << "end of stream AVPackets correctly."; 369 << "end of stream AVPackets correctly.";
369 370
370 DLOG(ERROR) 371 DLOG(ERROR)
371 << "Error decoding an audio frame with timestamp: " 372 << "Error decoding an audio frame with timestamp: "
372 << input->GetTimestamp().InMicroseconds() << " us, duration: " 373 << input->timestamp().InMicroseconds() << " us, duration: "
373 << input->GetDuration().InMicroseconds() << " us, packet size: " 374 << input->duration().InMicroseconds() << " us, packet size: "
374 << input->GetDataSize() << " bytes"; 375 << input->data_size() << " bytes";
375 376
376 // TODO(dalecurtis): We should return a kDecodeError here instead: 377 // TODO(dalecurtis): We should return a kDecodeError here instead:
377 // http://crbug.com/145276 378 // http://crbug.com/145276
378 break; 379 break;
379 } 380 }
380 381
381 // Update packet size and data pointer in case we need to call the decoder 382 // Update packet size and data pointer in case we need to call the decoder
382 // with the remaining bytes from this packet. 383 // with the remaining bytes from this packet.
383 packet.size -= result; 384 packet.size -= result;
384 packet.data += result; 385 packet.data += result;
385 386
386 if (output_timestamp_helper_->base_timestamp() == kNoTimestamp() && 387 if (output_timestamp_helper_->base_timestamp() == kNoTimestamp() &&
387 !input->IsEndOfStream()) { 388 !input->end_of_stream()) {
388 DCHECK(input->GetTimestamp() != kNoTimestamp()); 389 DCHECK(input->timestamp() != kNoTimestamp());
389 if (output_bytes_to_drop_ > 0) { 390 if (output_bytes_to_drop_ > 0) {
390 // Currently Vorbis is the only codec that causes us to drop samples. 391 // 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. 392 // 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); 393 DCHECK_EQ(codec_context_->codec_id, AV_CODEC_ID_VORBIS);
393 output_timestamp_helper_->SetBaseTimestamp(base::TimeDelta()); 394 output_timestamp_helper_->SetBaseTimestamp(base::TimeDelta());
394 } else { 395 } else {
395 output_timestamp_helper_->SetBaseTimestamp(input->GetTimestamp()); 396 output_timestamp_helper_->SetBaseTimestamp(input->timestamp());
396 } 397 }
397 } 398 }
398 399
399 int decoded_audio_size = 0; 400 int decoded_audio_size = 0;
400 #ifdef CHROMIUM_NO_AVFRAME_CHANNELS 401 #ifdef CHROMIUM_NO_AVFRAME_CHANNELS
401 int channels = av_get_channel_layout_nb_channels( 402 int channels = av_get_channel_layout_nb_channels(
402 av_frame_->channel_layout); 403 av_frame_->channel_layout);
403 #else 404 #else
404 int channels = av_frame_->channels; 405 int channels = av_frame_->channels;
405 #endif 406 #endif
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 // Decoding finished successfully, update statistics. 500 // Decoding finished successfully, update statistics.
500 if (result > 0) { 501 if (result > 0) {
501 PipelineStatistics statistics; 502 PipelineStatistics statistics;
502 statistics.audio_bytes_decoded = result; 503 statistics.audio_bytes_decoded = result;
503 statistics_cb_.Run(statistics); 504 statistics_cb_.Run(statistics);
504 } 505 }
505 } while (packet.size > 0); 506 } while (packet.size > 0);
506 } 507 }
507 508
508 } // namespace media 509 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698