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

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
« no previous file with comments | « media/filters/fake_video_decoder.cc ('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/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 11 matching lines...) Expand all
22 22
23 namespace media { 23 namespace media {
24 24
25 // Helper structure for managing multiple decoded audio frames per packet. 25 // Helper structure for managing multiple decoded audio frames per packet.
26 struct QueuedAudioBuffer { 26 struct QueuedAudioBuffer {
27 AudioDecoder::Status status; 27 AudioDecoder::Status status;
28 scoped_refptr<AudioBuffer> buffer; 28 scoped_refptr<AudioBuffer> buffer;
29 }; 29 };
30 30
31 // Returns true if the decode result was end of stream. 31 // Returns true if the decode result was end of stream.
32 static inline bool IsEndOfStream(int result, int decoded_size, 32 static inline bool IsEndOfStream(int result,
33 int decoded_size,
33 const scoped_refptr<DecoderBuffer>& input) { 34 const scoped_refptr<DecoderBuffer>& input) {
34 // Three conditions to meet to declare end of stream for this decoder: 35 // Three conditions to meet to declare end of stream for this decoder:
35 // 1. FFmpeg didn't read anything. 36 // 1. FFmpeg didn't read anything.
36 // 2. FFmpeg didn't output anything. 37 // 2. FFmpeg didn't output anything.
37 // 3. An end of stream buffer is received. 38 // 3. An end of stream buffer is received.
38 return result == 0 && decoded_size == 0 && input->IsEndOfStream(); 39 return result == 0 && decoded_size == 0 && input->end_of_stream();
39 } 40 }
40 41
41 FFmpegAudioDecoder::FFmpegAudioDecoder( 42 FFmpegAudioDecoder::FFmpegAudioDecoder(
42 const scoped_refptr<base::MessageLoopProxy>& message_loop) 43 const scoped_refptr<base::MessageLoopProxy>& message_loop)
43 : message_loop_(message_loop), 44 : message_loop_(message_loop),
44 weak_factory_(this), 45 weak_factory_(this),
45 demuxer_stream_(NULL), 46 demuxer_stream_(NULL),
46 codec_context_(NULL), 47 codec_context_(NULL),
47 bits_per_channel_(0), 48 bits_per_channel_(0),
48 channel_layout_(CHANNEL_LAYOUT_NONE), 49 channel_layout_(CHANNEL_LAYOUT_NONE),
(...skipping 128 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 output_frames_to_drop_ = floor( 201 output_frames_to_drop_ = floor(
201 0.5 + -input->GetTimestamp().InSecondsF() * samples_per_second_); 202 0.5 + -input->timestamp().InSecondsF() * samples_per_second_);
202 } else { 203 } else {
203 last_input_timestamp_ = input->GetTimestamp(); 204 last_input_timestamp_ = input->timestamp();
204 } 205 }
205 } else if (input->GetTimestamp() != kNoTimestamp()) { 206 } else if (input->timestamp() != kNoTimestamp()) {
206 if (input->GetTimestamp() < last_input_timestamp_) { 207 if (input->timestamp() < last_input_timestamp_) {
207 base::TimeDelta diff = input->GetTimestamp() - last_input_timestamp_; 208 base::TimeDelta diff = input->timestamp() - last_input_timestamp_;
208 DVLOG(1) << "Input timestamps are not monotonically increasing! " 209 DVLOG(1) << "Input timestamps are not monotonically increasing! "
209 << " ts " << input->GetTimestamp().InMicroseconds() << " us" 210 << " ts " << input->timestamp().InMicroseconds() << " us"
210 << " diff " << diff.InMicroseconds() << " us"; 211 << " diff " << diff.InMicroseconds() << " us";
211 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); 212 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL);
212 return; 213 return;
213 } 214 }
214 215
215 last_input_timestamp_ = input->GetTimestamp(); 216 last_input_timestamp_ = input->timestamp();
216 } 217 }
217 } 218 }
218 219
219 RunDecodeLoop(input, false); 220 RunDecodeLoop(input, false);
220 221
221 // 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
222 // for more data in order to fulfill this read. 223 // for more data in order to fulfill this read.
223 if (queued_audio_.empty()) { 224 if (queued_audio_.empty()) {
224 ReadFromDemuxerStream(); 225 ReadFromDemuxerStream();
225 return; 226 return;
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); 311 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp());
311 last_input_timestamp_ = kNoTimestamp(); 312 last_input_timestamp_ = kNoTimestamp();
312 output_frames_to_drop_ = 0; 313 output_frames_to_drop_ = 0;
313 } 314 }
314 315
315 void FFmpegAudioDecoder::RunDecodeLoop( 316 void FFmpegAudioDecoder::RunDecodeLoop(
316 const scoped_refptr<DecoderBuffer>& input, 317 const scoped_refptr<DecoderBuffer>& input,
317 bool skip_eos_append) { 318 bool skip_eos_append) {
318 AVPacket packet; 319 AVPacket packet;
319 av_init_packet(&packet); 320 av_init_packet(&packet);
320 if (input->IsEndOfStream()) { 321 if (input->end_of_stream()) {
321 packet.data = NULL; 322 packet.data = NULL;
322 packet.size = 0; 323 packet.size = 0;
323 } else { 324 } else {
324 packet.data = const_cast<uint8*>(input->GetData()); 325 packet.data = const_cast<uint8*>(input->data());
325 packet.size = input->GetDataSize(); 326 packet.size = input->data_size();
326 } 327 }
327 328
328 // Each audio packet may contain several frames, so we must call the decoder 329 // Each audio packet may contain several frames, so we must call the decoder
329 // until we've exhausted the packet. Regardless of the packet size we always 330 // until we've exhausted the packet. Regardless of the packet size we always
330 // want to hand it to the decoder at least once, otherwise we would end up 331 // want to hand it to the decoder at least once, otherwise we would end up
331 // skipping end of stream packets since they have a size of zero. 332 // skipping end of stream packets since they have a size of zero.
332 do { 333 do {
333 // Reset frame to default values. 334 // Reset frame to default values.
334 avcodec_get_frame_defaults(av_frame_); 335 avcodec_get_frame_defaults(av_frame_);
335 336
336 int frame_decoded = 0; 337 int frame_decoded = 0;
337 int result = avcodec_decode_audio4( 338 int result = avcodec_decode_audio4(
338 codec_context_, av_frame_, &frame_decoded, &packet); 339 codec_context_, av_frame_, &frame_decoded, &packet);
339 340
340 if (result < 0) { 341 if (result < 0) {
341 DCHECK(!input->IsEndOfStream()) 342 DCHECK(!input->end_of_stream())
342 << "End of stream buffer produced an error! " 343 << "End of stream buffer produced an error! "
343 << "This is quite possibly a bug in the audio decoder not handling " 344 << "This is quite possibly a bug in the audio decoder not handling "
344 << "end of stream AVPackets correctly."; 345 << "end of stream AVPackets correctly.";
345 346
346 DLOG(ERROR) 347 DLOG(ERROR)
347 << "Error decoding an audio frame with timestamp: " 348 << "Error decoding an audio frame with timestamp: "
348 << input->GetTimestamp().InMicroseconds() << " us, duration: " 349 << input->timestamp().InMicroseconds() << " us, duration: "
349 << input->GetDuration().InMicroseconds() << " us, packet size: " 350 << input->duration().InMicroseconds() << " us, packet size: "
350 << input->GetDataSize() << " bytes"; 351 << input->data_size() << " bytes";
351 352
352 // TODO(dalecurtis): We should return a kDecodeError here instead: 353 // TODO(dalecurtis): We should return a kDecodeError here instead:
353 // http://crbug.com/145276 354 // http://crbug.com/145276
354 break; 355 break;
355 } 356 }
356 357
357 // Update packet size and data pointer in case we need to call the decoder 358 // Update packet size and data pointer in case we need to call the decoder
358 // with the remaining bytes from this packet. 359 // with the remaining bytes from this packet.
359 packet.size -= result; 360 packet.size -= result;
360 packet.data += result; 361 packet.data += result;
361 362
362 if (output_timestamp_helper_->base_timestamp() == kNoTimestamp() && 363 if (output_timestamp_helper_->base_timestamp() == kNoTimestamp() &&
363 !input->IsEndOfStream()) { 364 !input->end_of_stream()) {
364 DCHECK(input->GetTimestamp() != kNoTimestamp()); 365 DCHECK(input->timestamp() != kNoTimestamp());
365 if (output_frames_to_drop_ > 0) { 366 if (output_frames_to_drop_ > 0) {
366 // Currently Vorbis is the only codec that causes us to drop samples. 367 // Currently Vorbis is the only codec that causes us to drop samples.
367 // If we have to drop samples it always means the timeline starts at 0. 368 // If we have to drop samples it always means the timeline starts at 0.
368 DCHECK_EQ(codec_context_->codec_id, AV_CODEC_ID_VORBIS); 369 DCHECK_EQ(codec_context_->codec_id, AV_CODEC_ID_VORBIS);
369 output_timestamp_helper_->SetBaseTimestamp(base::TimeDelta()); 370 output_timestamp_helper_->SetBaseTimestamp(base::TimeDelta());
370 } else { 371 } else {
371 output_timestamp_helper_->SetBaseTimestamp(input->GetTimestamp()); 372 output_timestamp_helper_->SetBaseTimestamp(input->timestamp());
372 } 373 }
373 } 374 }
374 375
375 int decoded_frames = 0; 376 int decoded_frames = 0;
376 #ifdef CHROMIUM_NO_AVFRAME_CHANNELS 377 #ifdef CHROMIUM_NO_AVFRAME_CHANNELS
377 int channels = av_get_channel_layout_nb_channels( 378 int channels = av_get_channel_layout_nb_channels(
378 av_frame_->channel_layout); 379 av_frame_->channel_layout);
379 #else 380 #else
380 int channels = av_frame_->channels; 381 int channels = av_frame_->channels;
381 #endif 382 #endif
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 // Decoding finished successfully, update statistics. 441 // Decoding finished successfully, update statistics.
441 if (result > 0) { 442 if (result > 0) {
442 PipelineStatistics statistics; 443 PipelineStatistics statistics;
443 statistics.audio_bytes_decoded = result; 444 statistics.audio_bytes_decoded = result;
444 statistics_cb_.Run(statistics); 445 statistics_cb_.Run(statistics);
445 } 446 }
446 } while (packet.size > 0); 447 } while (packet.size > 0);
447 } 448 }
448 449
449 } // namespace media 450 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/fake_video_decoder.cc ('k') | media/filters/ffmpeg_audio_decoder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698