| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this |
| 2 // source code is governed by a BSD-style license that can be found in the | 2 // source code is governed by a BSD-style license that can be found in the |
| 3 // LICENSE file. | 3 // LICENSE file. |
| 4 | 4 |
| 5 #include "media/filters/ffmpeg_audio_decoder.h" |
| 6 |
| 5 #include "media/base/data_buffer.h" | 7 #include "media/base/data_buffer.h" |
| 6 #include "media/filters/ffmpeg_audio_decoder.h" | |
| 7 #include "media/filters/ffmpeg_common.h" | 8 #include "media/filters/ffmpeg_common.h" |
| 8 #include "media/filters/ffmpeg_demuxer.h" | 9 #include "media/filters/ffmpeg_demuxer.h" |
| 9 | 10 |
| 10 namespace media { | 11 namespace media { |
| 11 | 12 |
| 12 // Size of the decoded audio buffer. | 13 // Size of the decoded audio buffer. |
| 13 const size_t FFmpegAudioDecoder::kOutputBufferSize = | 14 const size_t FFmpegAudioDecoder::kOutputBufferSize = |
| 14 AVCODEC_MAX_AUDIO_FRAME_SIZE; | 15 AVCODEC_MAX_AUDIO_FRAME_SIZE; |
| 15 | 16 |
| 16 FFmpegAudioDecoder::FFmpegAudioDecoder() | 17 FFmpegAudioDecoder::FFmpegAudioDecoder() |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 | 67 |
| 67 // Prepare the output buffer. | 68 // Prepare the output buffer. |
| 68 output_buffer_.reset(static_cast<uint8*>(av_malloc(kOutputBufferSize))); | 69 output_buffer_.reset(static_cast<uint8*>(av_malloc(kOutputBufferSize))); |
| 69 if (!output_buffer_.get()) { | 70 if (!output_buffer_.get()) { |
| 70 host()->SetError(PIPELINE_ERROR_OUT_OF_MEMORY); | 71 host()->SetError(PIPELINE_ERROR_OUT_OF_MEMORY); |
| 71 return false; | 72 return false; |
| 72 } | 73 } |
| 73 return true; | 74 return true; |
| 74 } | 75 } |
| 75 | 76 |
| 77 void FFmpegAudioDecoder::OnSeek(base::TimeDelta time) { |
| 78 avcodec_flush_buffers(codec_context_); |
| 79 estimated_next_timestamp_ = base::TimeDelta(); |
| 80 } |
| 81 |
| 76 void FFmpegAudioDecoder::OnStop() { | 82 void FFmpegAudioDecoder::OnStop() { |
| 77 } | 83 } |
| 78 | 84 |
| 79 void FFmpegAudioDecoder::OnDecode(Buffer* input) { | 85 void FFmpegAudioDecoder::OnDecode(Buffer* input) { |
| 80 // Check for discontinuous buffer. If we receive a discontinuous buffer here, | |
| 81 // flush the internal buffer of FFmpeg. | |
| 82 if (input->IsDiscontinuous()) { | |
| 83 avcodec_flush_buffers(codec_context_); | |
| 84 } | |
| 85 | |
| 86 // Due to FFmpeg API changes we no longer have const read-only pointers. | 86 // Due to FFmpeg API changes we no longer have const read-only pointers. |
| 87 AVPacket packet; | 87 AVPacket packet; |
| 88 av_init_packet(&packet); | 88 av_init_packet(&packet); |
| 89 packet.data = const_cast<uint8*>(input->GetData()); | 89 packet.data = const_cast<uint8*>(input->GetData()); |
| 90 packet.size = input->GetDataSize(); | 90 packet.size = input->GetDataSize(); |
| 91 | 91 |
| 92 int16_t* output_buffer = reinterpret_cast<int16_t*>(output_buffer_.get()); | 92 int16_t* output_buffer = reinterpret_cast<int16_t*>(output_buffer_.get()); |
| 93 int output_buffer_size = kOutputBufferSize; | 93 int output_buffer_size = kOutputBufferSize; |
| 94 int result = avcodec_decode_audio3(codec_context_, | 94 int result = avcodec_decode_audio3(codec_context_, |
| 95 output_buffer, | 95 output_buffer, |
| (...skipping 17 matching lines...) Expand all Loading... |
| 113 memcpy(data, output_buffer, output_buffer_size); | 113 memcpy(data, output_buffer, output_buffer_size); |
| 114 | 114 |
| 115 // Determine the duration if the demuxer couldn't figure it out, otherwise | 115 // Determine the duration if the demuxer couldn't figure it out, otherwise |
| 116 // copy it over. | 116 // copy it over. |
| 117 if (input->GetDuration().InMicroseconds() == 0) { | 117 if (input->GetDuration().InMicroseconds() == 0) { |
| 118 result_buffer->SetDuration(CalculateDuration(output_buffer_size)); | 118 result_buffer->SetDuration(CalculateDuration(output_buffer_size)); |
| 119 } else { | 119 } else { |
| 120 result_buffer->SetDuration(input->GetDuration()); | 120 result_buffer->SetDuration(input->GetDuration()); |
| 121 } | 121 } |
| 122 | 122 |
| 123 // Copy over the timestamp. | 123 // Use our estimate for the timestamp if |input| does not have one. |
| 124 result_buffer->SetTimestamp(input->GetTimestamp()); | 124 // Otherwise, copy over the timestamp. |
| 125 if (input->GetTimestamp().InMicroseconds() == 0) { |
| 126 result_buffer->SetTimestamp(estimated_next_timestamp_); |
| 127 } else { |
| 128 result_buffer->SetTimestamp(input->GetTimestamp()); |
| 129 } |
| 130 |
| 131 // Update our estimated timestamp for the next packet. |
| 132 estimated_next_timestamp_ = result_buffer->GetTimestamp() + |
| 133 result_buffer->GetDuration(); |
| 125 | 134 |
| 126 EnqueueResult(result_buffer); | 135 EnqueueResult(result_buffer); |
| 127 return; | 136 return; |
| 128 } | 137 } |
| 129 | 138 |
| 130 // Three conditions to meet to declare end of stream for this decoder: | 139 // Three conditions to meet to declare end of stream for this decoder: |
| 131 // 1. FFmpeg didn't read anything. | 140 // 1. FFmpeg didn't read anything. |
| 132 // 2. FFmpeg didn't output anything. | 141 // 2. FFmpeg didn't output anything. |
| 133 // 3. An end of stream buffer is received. | 142 // 3. An end of stream buffer is received. |
| 134 if (result == 0 && output_buffer_size == 0 && input->IsEndOfStream()) { | 143 if (result == 0 && output_buffer_size == 0 && input->IsEndOfStream()) { |
| 135 DataBuffer* result_buffer = new DataBuffer(0); | 144 DataBuffer* result_buffer = new DataBuffer(0); |
| 136 result_buffer->SetTimestamp(input->GetTimestamp()); | 145 result_buffer->SetTimestamp(input->GetTimestamp()); |
| 137 result_buffer->SetDuration(input->GetDuration()); | 146 result_buffer->SetDuration(input->GetDuration()); |
| 138 EnqueueResult(result_buffer); | 147 EnqueueResult(result_buffer); |
| 139 } | 148 } |
| 140 } | 149 } |
| 141 | 150 |
| 142 base::TimeDelta FFmpegAudioDecoder::CalculateDuration(size_t size) { | 151 base::TimeDelta FFmpegAudioDecoder::CalculateDuration(size_t size) { |
| 143 int64 denominator = codec_context_->channels * | 152 int64 denominator = codec_context_->channels * |
| 144 av_get_bits_per_sample_format(codec_context_->sample_fmt) / 8 * | 153 av_get_bits_per_sample_format(codec_context_->sample_fmt) / 8 * |
| 145 codec_context_->sample_rate; | 154 codec_context_->sample_rate; |
| 146 double microseconds = size / | 155 double microseconds = size / |
| 147 (denominator / static_cast<double>(base::Time::kMicrosecondsPerSecond)); | 156 (denominator / static_cast<double>(base::Time::kMicrosecondsPerSecond)); |
| 148 return base::TimeDelta::FromMicroseconds(static_cast<int64>(microseconds)); | 157 return base::TimeDelta::FromMicroseconds(static_cast<int64>(microseconds)); |
| 149 } | 158 } |
| 150 | 159 |
| 151 } // namespace | 160 } // namespace |
| OLD | NEW |