Index: media/base/pipeline.cc |
diff --git a/media/base/pipeline.cc b/media/base/pipeline.cc |
index 607cf8c932921d3492435139dda16275d31dc9ed..4b4fec0ac4941068bd308e53d28ed8f5fef61314 100644 |
--- a/media/base/pipeline.cc |
+++ b/media/base/pipeline.cc |
@@ -24,6 +24,8 @@ |
#include "media/base/video_decoder.h" |
#include "media/base/video_renderer.h" |
+using base::TimeDelta; |
+ |
namespace media { |
PipelineStatusNotification::PipelineStatusNotification() |
@@ -73,7 +75,6 @@ Pipeline::Pipeline(MessageLoop* message_loop, MediaLog* media_log) |
clock_(new Clock(&base::Time::Now)), |
waiting_for_clock_update_(false), |
state_(kCreated), |
- current_bytes_(0), |
creation_time_(base::Time::Now()) { |
media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); |
ResetState(); |
@@ -114,8 +115,7 @@ void Pipeline::Stop(const base::Closure& stop_cb) { |
&Pipeline::StopTask, this, stop_cb)); |
} |
-void Pipeline::Seek(base::TimeDelta time, |
- const PipelineStatusCB& seek_cb) { |
+void Pipeline::Seek(TimeDelta time, const PipelineStatusCB& seek_cb) { |
base::AutoLock auto_lock(lock_); |
CHECK(running_) << "Media pipeline isn't running"; |
@@ -190,29 +190,43 @@ void Pipeline::SetVolume(float volume) { |
} |
} |
-base::TimeDelta Pipeline::GetCurrentTime() const { |
+TimeDelta Pipeline::GetCurrentTime() const { |
base::AutoLock auto_lock(lock_); |
return GetCurrentTime_Locked(); |
} |
-base::TimeDelta Pipeline::GetCurrentTime_Locked() const { |
+TimeDelta Pipeline::GetCurrentTime_Locked() const { |
lock_.AssertAcquired(); |
return clock_->Elapsed(); |
} |
-Ranges<base::TimeDelta> Pipeline::GetBufferedTimeRanges() { |
+Ranges<TimeDelta> Pipeline::GetBufferedTimeRanges() { |
base::AutoLock auto_lock(lock_); |
- return buffered_time_ranges_; |
+ Ranges<TimeDelta> time_ranges; |
+ if (clock_->Duration() == TimeDelta() || total_bytes_ == 0) |
+ return time_ranges; |
+ for (size_t i = 0; i < buffered_byte_ranges_.size(); ++i) { |
+ TimeDelta start = TimeForByteOffset_Locked(buffered_byte_ranges_.start(i)); |
+ TimeDelta end = TimeForByteOffset_Locked(buffered_byte_ranges_.end(i)); |
+ // Cap approximated buffered time at the length of the video. |
+ end = std::min(end, clock_->Duration()); |
+ time_ranges.Add(start, end); |
+ } |
+ |
+ return time_ranges; |
} |
-base::TimeDelta Pipeline::GetMediaDuration() const { |
+TimeDelta Pipeline::GetMediaDuration() const { |
base::AutoLock auto_lock(lock_); |
return clock_->Duration(); |
} |
int64 Pipeline::GetBufferedBytes() const { |
base::AutoLock auto_lock(lock_); |
- return buffered_bytes_; |
+ int64 ret = 0; |
+ for (size_t i = 0; i < buffered_byte_ranges_.size(); ++i) |
+ ret += buffered_byte_ranges_.end(i) - buffered_byte_ranges_.start(i); |
+ return ret; |
} |
int64 Pipeline::GetTotalBytes() const { |
@@ -235,31 +249,16 @@ void Pipeline::SetClockForTesting(Clock* clock) { |
clock_.reset(clock); |
} |
-void Pipeline::SetCurrentReadPosition(int64 offset) { |
- base::AutoLock auto_lock(lock_); |
- |
- // The current read position should never be ahead of the buffered byte |
- // position but threading issues between BufferedDataSource::DoneRead_Locked() |
- // and BufferedDataSource::NetworkEventCallback() can cause them to be |
- // temporarily out of sync. The easiest fix for this is to cap both |
- // buffered_bytes_ and current_bytes_ to always be legal values in |
- // SetCurrentReadPosition() and in SetBufferedBytes(). |
- if (offset > buffered_bytes_) |
- buffered_bytes_ = offset; |
- current_bytes_ = offset; |
-} |
- |
void Pipeline::ResetState() { |
base::AutoLock auto_lock(lock_); |
- const base::TimeDelta kZero; |
+ const TimeDelta kZero; |
running_ = false; |
stop_pending_ = false; |
seek_pending_ = false; |
tearing_down_ = false; |
error_caused_teardown_ = false; |
playback_rate_change_pending_ = false; |
- buffered_bytes_ = 0; |
- buffered_time_ranges_.clear(); |
+ buffered_byte_ranges_.clear(); |
total_bytes_ = 0; |
natural_size_.SetSize(0, 0); |
volume_ = 1.0f; |
@@ -378,18 +377,17 @@ void Pipeline::SetError(PipelineStatus error) { |
media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error)); |
} |
-base::TimeDelta Pipeline::GetTime() const { |
+TimeDelta Pipeline::GetTime() const { |
DCHECK(IsRunning()); |
return GetCurrentTime(); |
} |
-base::TimeDelta Pipeline::GetDuration() const { |
+TimeDelta Pipeline::GetDuration() const { |
DCHECK(IsRunning()); |
return GetMediaDuration(); |
} |
-void Pipeline::OnAudioTimeUpdate(base::TimeDelta time, |
- base::TimeDelta max_time) { |
+void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) { |
DCHECK(time <= max_time); |
DCHECK(IsRunning()); |
base::AutoLock auto_lock(lock_); |
@@ -403,7 +401,7 @@ void Pipeline::OnAudioTimeUpdate(base::TimeDelta time, |
StartClockIfWaitingForTimeUpdate_Locked(); |
} |
-void Pipeline::OnVideoTimeUpdate(base::TimeDelta max_time) { |
+void Pipeline::OnVideoTimeUpdate(TimeDelta max_time) { |
DCHECK(IsRunning()); |
base::AutoLock auto_lock(lock_); |
@@ -414,7 +412,7 @@ void Pipeline::OnVideoTimeUpdate(base::TimeDelta max_time) { |
clock_->SetMaxTime(max_time); |
} |
-void Pipeline::SetDuration(base::TimeDelta duration) { |
+void Pipeline::SetDuration(TimeDelta duration) { |
DCHECK(IsRunning()); |
media_log_->AddEvent( |
media_log_->CreateTimeEvent( |
@@ -423,7 +421,6 @@ void Pipeline::SetDuration(base::TimeDelta duration) { |
base::AutoLock auto_lock(lock_); |
clock_->SetDuration(duration); |
- UpdateBufferedTimeRanges_Locked(); |
} |
void Pipeline::SetTotalBytes(int64 total_bytes) { |
@@ -441,29 +438,23 @@ void Pipeline::SetTotalBytes(int64 total_bytes) { |
total_bytes_ = total_bytes; |
} |
-void Pipeline::SetBufferedBytes(int64 buffered_bytes) { |
+TimeDelta Pipeline::TimeForByteOffset_Locked(int64 byte_offset) const { |
+ lock_.AssertAcquired(); |
+ TimeDelta time_offset = byte_offset * clock_->Duration() / total_bytes_; |
+ // Since the byte->time calculation is approximate, fudge the beginning & |
+ // ending areas to look better. |
+ TimeDelta epsilon = clock_->Duration() / 100; |
+ if (time_offset < epsilon) |
+ return TimeDelta(); |
+ if (time_offset + epsilon > clock_->Duration()) |
+ return clock_->Duration(); |
+ return time_offset; |
+} |
+ |
+void Pipeline::AddBufferedByteRange(int64 start, int64 end) { |
DCHECK(IsRunning()); |
base::AutoLock auto_lock(lock_); |
- // See comments in SetCurrentReadPosition() about capping. |
- if (buffered_bytes < current_bytes_) |
- current_bytes_ = buffered_bytes; |
- buffered_bytes_ = buffered_bytes; |
- UpdateBufferedTimeRanges_Locked(); |
-} |
- |
-void Pipeline::UpdateBufferedTimeRanges_Locked() { |
- lock_.AssertAcquired(); |
- if (total_bytes_ == 0) |
- return; |
- base::TimeDelta buffered_time = |
- clock_->Duration() * buffered_bytes_ / total_bytes_; |
- // Cap approximated buffered time at the length of the video. |
- buffered_time = std::min(buffered_time, clock_->Duration()); |
- // Make sure buffered_time is at least the current time and at least the |
- // current seek target. |
- buffered_time = std::max(buffered_time, GetCurrentTime_Locked()); |
- buffered_time = std::max(buffered_time, seek_timestamp_); |
- buffered_time_ranges_.Add(seek_timestamp_, buffered_time); |
+ buffered_byte_ranges_.Add(start, end); |
} |
void Pipeline::SetNaturalVideoSize(const gfx::Size& size) { |
@@ -782,8 +773,7 @@ void Pipeline::VolumeChangedTask(float volume) { |
audio_renderer_->SetVolume(volume); |
} |
-void Pipeline::SeekTask(base::TimeDelta time, |
- const PipelineStatusCB& seek_cb) { |
+void Pipeline::SeekTask(TimeDelta time, const PipelineStatusCB& seek_cb) { |
DCHECK(message_loop_->BelongsToCurrentThread()); |
DCHECK(!IsPipelineStopPending()); |
@@ -1260,7 +1250,7 @@ void Pipeline::OnDemuxerStopDone(const base::Closure& callback) { |
callback.Run(); |
} |
-void Pipeline::DoSeek(base::TimeDelta seek_timestamp) { |
+void Pipeline::DoSeek(TimeDelta seek_timestamp) { |
// TODO(acolwell): We might be able to convert this if (demuxer_) into a |
// DCHECK(). Further investigation is needed to make sure this won't introduce |
// a bug. |
@@ -1273,7 +1263,7 @@ void Pipeline::DoSeek(base::TimeDelta seek_timestamp) { |
OnDemuxerSeekDone(seek_timestamp, PIPELINE_OK); |
} |
-void Pipeline::OnDemuxerSeekDone(base::TimeDelta seek_timestamp, |
+void Pipeline::OnDemuxerSeekDone(TimeDelta seek_timestamp, |
PipelineStatus status) { |
if (!message_loop_->BelongsToCurrentThread()) { |
message_loop_->PostTask(FROM_HERE, base::Bind( |