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

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

Issue 173072: Suppress slider thumb jumping around during seeking... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « media/base/pipeline_impl.cc ('k') | media/filters/ffmpeg_demuxer.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) 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
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
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
OLDNEW
« no previous file with comments | « media/base/pipeline_impl.cc ('k') | media/filters/ffmpeg_demuxer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698