| 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" | 5 #include "media/filters/ffmpeg_audio_decoder.h" |
| 6 | 6 |
| 7 #include "media/base/data_buffer.h" | 7 #include "media/base/data_buffer.h" |
| 8 #include "media/filters/ffmpeg_common.h" | 8 #include "media/filters/ffmpeg_common.h" |
| 9 #include "media/filters/ffmpeg_demuxer.h" | 9 #include "media/filters/ffmpeg_demuxer.h" |
| 10 | 10 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 69 output_buffer_.reset(static_cast<uint8*>(av_malloc(kOutputBufferSize))); | 69 output_buffer_.reset(static_cast<uint8*>(av_malloc(kOutputBufferSize))); |
| 70 if (!output_buffer_.get()) { | 70 if (!output_buffer_.get()) { |
| 71 host()->SetError(PIPELINE_ERROR_OUT_OF_MEMORY); | 71 host()->SetError(PIPELINE_ERROR_OUT_OF_MEMORY); |
| 72 return false; | 72 return false; |
| 73 } | 73 } |
| 74 return true; | 74 return true; |
| 75 } | 75 } |
| 76 | 76 |
| 77 void FFmpegAudioDecoder::OnSeek(base::TimeDelta time) { | 77 void FFmpegAudioDecoder::OnSeek(base::TimeDelta time) { |
| 78 avcodec_flush_buffers(codec_context_); | 78 avcodec_flush_buffers(codec_context_); |
| 79 estimated_next_timestamp_ = base::TimeDelta(); | 79 estimated_next_timestamp_ = StreamSample::kInvalidTimestamp; |
| 80 } | 80 } |
| 81 | 81 |
| 82 void FFmpegAudioDecoder::OnStop() { | 82 void FFmpegAudioDecoder::OnStop() { |
| 83 } | 83 } |
| 84 | 84 |
| 85 void FFmpegAudioDecoder::OnDecode(Buffer* input) { | 85 void FFmpegAudioDecoder::OnDecode(Buffer* input) { |
| 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()); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 107 | 107 |
| 108 // If we have decoded something, enqueue the result. | 108 // If we have decoded something, enqueue the result. |
| 109 if (output_buffer_size) { | 109 if (output_buffer_size) { |
| 110 DataBuffer* result_buffer = new DataBuffer(output_buffer_size); | 110 DataBuffer* result_buffer = new DataBuffer(output_buffer_size); |
| 111 result_buffer->SetDataSize(output_buffer_size); | 111 result_buffer->SetDataSize(output_buffer_size); |
| 112 uint8* data = result_buffer->GetWritableData(); | 112 uint8* data = result_buffer->GetWritableData(); |
| 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().ToInternalValue() == 0) { |
| 118 result_buffer->SetDuration(CalculateDuration(output_buffer_size)); | 118 result_buffer->SetDuration(CalculateDuration(output_buffer_size)); |
| 119 } else { | 119 } else { |
| 120 DCHECK(input->GetDuration() != StreamSample::kInvalidTimestamp); |
| 120 result_buffer->SetDuration(input->GetDuration()); | 121 result_buffer->SetDuration(input->GetDuration()); |
| 121 } | 122 } |
| 122 | 123 |
| 123 // Use our estimate for the timestamp if |input| does not have one. | 124 // Use our estimate for the timestamp if |input| does not have one. |
| 124 // Otherwise, copy over the timestamp. | 125 // Otherwise, copy over the timestamp. |
| 125 if (input->GetTimestamp().InMicroseconds() == 0) { | 126 if (input->GetTimestamp() == StreamSample::kInvalidTimestamp) { |
| 126 result_buffer->SetTimestamp(estimated_next_timestamp_); | 127 result_buffer->SetTimestamp(estimated_next_timestamp_); |
| 127 } else { | 128 } else { |
| 128 result_buffer->SetTimestamp(input->GetTimestamp()); | 129 result_buffer->SetTimestamp(input->GetTimestamp()); |
| 129 } | 130 } |
| 130 | 131 |
| 131 // Only use the timestamp of |result_buffer| to estimate the next timestamp | 132 // Only use the timestamp of |result_buffer| to estimate the next timestamp |
| 132 // if it is valid (i.e. greater than 0). Otherwise the error will stack | 133 // if it is valid (i.e. != StreamSample::kInvalidTimestamp). Otherwise the |
| 133 // together and we will get a series of incorrect timestamps. In this case, | 134 // error will stack together and we will get a series of incorrect |
| 134 // this will maintain a series of zero timestamps. | 135 // timestamps. In this case, this will maintain a series of zero |
| 135 // TODO(hclam): We should use another invalid value other than 0. | 136 // timestamps. |
| 136 if (result_buffer->GetTimestamp().InMicroseconds() > 0) { | 137 if (result_buffer->GetTimestamp() != StreamSample::kInvalidTimestamp) { |
| 137 // Update our estimated timestamp for the next packet. | 138 // Update our estimated timestamp for the next packet. |
| 138 estimated_next_timestamp_ = result_buffer->GetTimestamp() + | 139 estimated_next_timestamp_ = result_buffer->GetTimestamp() + |
| 139 result_buffer->GetDuration(); | 140 result_buffer->GetDuration(); |
| 140 } | 141 } |
| 141 | 142 |
| 142 EnqueueResult(result_buffer); | 143 EnqueueResult(result_buffer); |
| 143 return; | 144 return; |
| 144 } | 145 } |
| 145 | 146 |
| 147 // We can get a positive result but no decoded data. This is ok because this |
| 148 // this can be a marker packet that only contains timestamp. In this case we |
| 149 // save the timestamp for later use. |
| 150 if (result && !input->IsEndOfStream() && |
| 151 input->GetTimestamp() != StreamSample::kInvalidTimestamp && |
| 152 input->GetDuration() != StreamSample::kInvalidTimestamp) { |
| 153 estimated_next_timestamp_ = input->GetTimestamp() + input->GetDuration(); |
| 154 return; |
| 155 } |
| 156 |
| 146 // Three conditions to meet to declare end of stream for this decoder: | 157 // Three conditions to meet to declare end of stream for this decoder: |
| 147 // 1. FFmpeg didn't read anything. | 158 // 1. FFmpeg didn't read anything. |
| 148 // 2. FFmpeg didn't output anything. | 159 // 2. FFmpeg didn't output anything. |
| 149 // 3. An end of stream buffer is received. | 160 // 3. An end of stream buffer is received. |
| 150 if (result == 0 && output_buffer_size == 0 && input->IsEndOfStream()) { | 161 if (result == 0 && output_buffer_size == 0 && input->IsEndOfStream()) { |
| 151 DataBuffer* result_buffer = new DataBuffer(0); | 162 DataBuffer* result_buffer = new DataBuffer(0); |
| 152 result_buffer->SetTimestamp(input->GetTimestamp()); | 163 result_buffer->SetTimestamp(input->GetTimestamp()); |
| 153 result_buffer->SetDuration(input->GetDuration()); | 164 result_buffer->SetDuration(input->GetDuration()); |
| 154 EnqueueResult(result_buffer); | 165 EnqueueResult(result_buffer); |
| 155 } | 166 } |
| 156 } | 167 } |
| 157 | 168 |
| 158 base::TimeDelta FFmpegAudioDecoder::CalculateDuration(size_t size) { | 169 base::TimeDelta FFmpegAudioDecoder::CalculateDuration(size_t size) { |
| 159 int64 denominator = codec_context_->channels * | 170 int64 denominator = codec_context_->channels * |
| 160 av_get_bits_per_sample_format(codec_context_->sample_fmt) / 8 * | 171 av_get_bits_per_sample_format(codec_context_->sample_fmt) / 8 * |
| 161 codec_context_->sample_rate; | 172 codec_context_->sample_rate; |
| 162 double microseconds = size / | 173 double microseconds = size / |
| 163 (denominator / static_cast<double>(base::Time::kMicrosecondsPerSecond)); | 174 (denominator / static_cast<double>(base::Time::kMicrosecondsPerSecond)); |
| 164 return base::TimeDelta::FromMicroseconds(static_cast<int64>(microseconds)); | 175 return base::TimeDelta::FromMicroseconds(static_cast<int64>(microseconds)); |
| 165 } | 176 } |
| 166 | 177 |
| 167 } // namespace | 178 } // namespace |
| OLD | NEW |