OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 // TODO(scherkus): clean up PipelineImpl... too many crazy function names, | 5 // TODO(scherkus): clean up PipelineImpl... too many crazy function names, |
6 // potential deadlocks, etc... | 6 // potential deadlocks, etc... |
7 | 7 |
8 #include "base/callback.h" | 8 #include "base/callback.h" |
9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
10 #include "base/condition_variable.h" | 10 #include "base/condition_variable.h" |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 } | 70 } |
71 } | 71 } |
72 | 72 |
73 } // namespace | 73 } // namespace |
74 | 74 |
75 PipelineImpl::PipelineImpl(MessageLoop* message_loop) | 75 PipelineImpl::PipelineImpl(MessageLoop* message_loop) |
76 : message_loop_(message_loop), | 76 : message_loop_(message_loop), |
77 clock_(&base::Time::Now), | 77 clock_(&base::Time::Now), |
78 waiting_for_clock_update_(false), | 78 waiting_for_clock_update_(false), |
79 state_(kCreated), | 79 state_(kCreated), |
80 remaining_transitions_(0) { | 80 remaining_transitions_(0), |
| 81 current_bytes_(0) { |
81 ResetState(); | 82 ResetState(); |
82 } | 83 } |
83 | 84 |
84 PipelineImpl::~PipelineImpl() { | 85 PipelineImpl::~PipelineImpl() { |
85 AutoLock auto_lock(lock_); | 86 AutoLock auto_lock(lock_); |
86 DCHECK(!running_) << "Stop() must complete before destroying object"; | 87 DCHECK(!running_) << "Stop() must complete before destroying object"; |
87 } | 88 } |
88 | 89 |
89 // Creates the PipelineInternal and calls it's start method. | 90 // Creates the PipelineInternal and calls it's start method. |
90 bool PipelineImpl::Start(FilterFactory* factory, | 91 bool PipelineImpl::Start(FilterFactory* factory, |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
213 // is set/get under the lock, because this is breaching the contract that | 214 // is set/get under the lock, because this is breaching the contract that |
214 // |state_| is only accessed on |message_loop_|. | 215 // |state_| is only accessed on |message_loop_|. |
215 AutoLock auto_lock(lock_); | 216 AutoLock auto_lock(lock_); |
216 base::TimeDelta elapsed = clock_.Elapsed(); | 217 base::TimeDelta elapsed = clock_.Elapsed(); |
217 if (state_ == kEnded || elapsed > duration_) { | 218 if (state_ == kEnded || elapsed > duration_) { |
218 return duration_; | 219 return duration_; |
219 } | 220 } |
220 return elapsed; | 221 return elapsed; |
221 } | 222 } |
222 | 223 |
223 base::TimeDelta PipelineImpl::GetBufferedTime() const { | 224 |
| 225 base::TimeDelta PipelineImpl::GetBufferedTime() { |
| 226 DCHECK(buffered_bytes_ >= current_bytes_); |
224 AutoLock auto_lock(lock_); | 227 AutoLock auto_lock(lock_); |
225 | 228 |
226 // If buffered time was set, we report that value directly. | 229 // If buffered time was set, we report that value directly. |
227 if (buffered_time_.ToInternalValue() > 0) | 230 if (buffered_time_.ToInternalValue() > 0) |
228 return buffered_time_; | 231 return buffered_time_; |
229 | 232 |
230 // If buffered time was not set, we use duration and buffered bytes to | 233 if (total_bytes_ == 0 || current_bytes_ == 0) |
231 // estimate the buffered time. | |
232 // TODO(hclam): The estimation is based on linear interpolation which is | |
233 // not accurate enough. We should find a better way to estimate the value. | |
234 if (total_bytes_ == 0) | |
235 return base::TimeDelta(); | 234 return base::TimeDelta(); |
236 | 235 |
237 double ratio = static_cast<double>(buffered_bytes_); | 236 // If buffered time was not set, we use current time, current bytes, and |
238 ratio /= total_bytes_; | 237 // buffered bytes to estimate the buffered time. |
| 238 double current_time = static_cast<double>(current_bytes_) / total_bytes_ * |
| 239 duration_.InMilliseconds(); |
| 240 double rate = current_time / current_bytes_; |
| 241 double buffered_time = rate * (buffered_bytes_ - current_bytes_) + |
| 242 current_time; |
| 243 |
| 244 // Only print the max buffered time for smooth buffering. |
| 245 if (buffered_time > max_buffered_time_) |
| 246 max_buffered_time_ = buffered_time; |
| 247 |
239 return base::TimeDelta::FromMilliseconds( | 248 return base::TimeDelta::FromMilliseconds( |
240 static_cast<int64>(duration_.InMilliseconds() * ratio)); | 249 static_cast<int64>(max_buffered_time_)); |
241 } | 250 } |
242 | 251 |
243 base::TimeDelta PipelineImpl::GetMediaDuration() const { | 252 base::TimeDelta PipelineImpl::GetMediaDuration() const { |
244 AutoLock auto_lock(lock_); | 253 AutoLock auto_lock(lock_); |
245 return duration_; | 254 return duration_; |
246 } | 255 } |
247 | 256 |
248 int64 PipelineImpl::GetBufferedBytes() const { | 257 int64 PipelineImpl::GetBufferedBytes() const { |
249 AutoLock auto_lock(lock_); | 258 AutoLock auto_lock(lock_); |
250 return buffered_bytes_; | 259 return buffered_bytes_; |
(...skipping 20 matching lines...) Expand all Loading... |
271 bool PipelineImpl::IsLoaded() const { | 280 bool PipelineImpl::IsLoaded() const { |
272 AutoLock auto_lock(lock_); | 281 AutoLock auto_lock(lock_); |
273 return loaded_; | 282 return loaded_; |
274 } | 283 } |
275 | 284 |
276 PipelineError PipelineImpl::GetError() const { | 285 PipelineError PipelineImpl::GetError() const { |
277 AutoLock auto_lock(lock_); | 286 AutoLock auto_lock(lock_); |
278 return error_; | 287 return error_; |
279 } | 288 } |
280 | 289 |
| 290 void PipelineImpl::SetCurrentReadPosition(int64 offset) { |
| 291 AutoLock auto_lock(lock_); |
| 292 current_bytes_ = offset; |
| 293 } |
| 294 |
| 295 int64 PipelineImpl::GetCurrentReadPosition() { |
| 296 AutoLock auto_lock(lock_); |
| 297 return current_bytes_; |
| 298 } |
| 299 |
281 void PipelineImpl::SetPipelineEndedCallback(PipelineCallback* ended_callback) { | 300 void PipelineImpl::SetPipelineEndedCallback(PipelineCallback* ended_callback) { |
282 DCHECK(!IsRunning()) | 301 DCHECK(!IsRunning()) |
283 << "Permanent callbacks should be set before the pipeline has started"; | 302 << "Permanent callbacks should be set before the pipeline has started"; |
284 ended_callback_.reset(ended_callback); | 303 ended_callback_.reset(ended_callback); |
285 } | 304 } |
286 | 305 |
287 void PipelineImpl::SetPipelineErrorCallback(PipelineCallback* error_callback) { | 306 void PipelineImpl::SetPipelineErrorCallback(PipelineCallback* error_callback) { |
288 DCHECK(!IsRunning()) | 307 DCHECK(!IsRunning()) |
289 << "Permanent callbacks should be set before the pipeline has started"; | 308 << "Permanent callbacks should be set before the pipeline has started"; |
290 error_callback_.reset(error_callback); | 309 error_callback_.reset(error_callback); |
(...skipping 699 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
990 | 1009 |
991 // Reset the pipeline, which will decrement a reference to this object. | 1010 // Reset the pipeline, which will decrement a reference to this object. |
992 // We will get destroyed as soon as the remaining tasks finish executing. | 1011 // We will get destroyed as soon as the remaining tasks finish executing. |
993 // To be safe, we'll set our pipeline reference to NULL. | 1012 // To be safe, we'll set our pipeline reference to NULL. |
994 filters_.clear(); | 1013 filters_.clear(); |
995 filter_types_.clear(); | 1014 filter_types_.clear(); |
996 STLDeleteElements(&filter_threads_); | 1015 STLDeleteElements(&filter_threads_); |
997 } | 1016 } |
998 | 1017 |
999 } // namespace media | 1018 } // namespace media |
OLD | NEW |