Index: media/filters/chunk_demuxer.cc |
diff --git a/media/filters/chunk_demuxer.cc b/media/filters/chunk_demuxer.cc |
index 73dbae6c0cf4e3144b4b2a459642e6b63a74ee39..768473c0f3ee9c8b0b79afe00887805943f48ac2 100644 |
--- a/media/filters/chunk_demuxer.cc |
+++ b/media/filters/chunk_demuxer.cc |
@@ -13,6 +13,7 @@ |
#include "base/location.h" |
#include "base/message_loop/message_loop_proxy.h" |
#include "media/base/audio_decoder_config.h" |
+#include "media/base/bind_to_loop.h" |
#include "media/base/stream_parser_buffer.h" |
#include "media/base/video_decoder_config.h" |
#include "media/filters/stream_parser_factory.h" |
@@ -207,7 +208,7 @@ class ChunkDemuxerStream : public DemuxerStream { |
void StartWaitingForSeek(); |
void Seek(TimeDelta time); |
void CancelPendingSeek(); |
- bool IsSeekPending() const; |
+ bool IsSeekWaitingForData() const; |
// Add buffers to this stream. Buffers are stored in SourceBufferStreams, |
// which handle ordering and overlap resolution. |
@@ -215,10 +216,10 @@ class ChunkDemuxerStream : public DemuxerStream { |
bool Append(const StreamParser::BufferQueue& buffers); |
// Signal to the stream that duration has changed to |duration|. |
- void OnSetDuration(base::TimeDelta duration); |
+ void OnSetDuration(TimeDelta duration); |
// Returns the range of buffered data in this stream, capped at |duration|. |
- Ranges<TimeDelta> GetBufferedRanges(base::TimeDelta duration) const; |
+ Ranges<TimeDelta> GetBufferedRanges(TimeDelta duration) const; |
// Signal to the stream that buffers handed in through subsequent calls to |
// Append() belong to a media segment that starts at |start_timestamp|. |
@@ -334,7 +335,7 @@ void ChunkDemuxerStream::CancelPendingSeek() { |
it->Run(kAborted, NULL); |
} |
-bool ChunkDemuxerStream::IsSeekPending() const { |
+bool ChunkDemuxerStream::IsSeekWaitingForData() const { |
base::AutoLock auto_lock(lock_); |
return stream_->IsSeekPending(); |
} |
@@ -365,13 +366,13 @@ bool ChunkDemuxerStream::Append(const StreamParser::BufferQueue& buffers) { |
return true; |
} |
-void ChunkDemuxerStream::OnSetDuration(base::TimeDelta duration) { |
+void ChunkDemuxerStream::OnSetDuration(TimeDelta duration) { |
base::AutoLock auto_lock(lock_); |
stream_->OnSetDuration(duration); |
} |
Ranges<TimeDelta> ChunkDemuxerStream::GetBufferedRanges( |
- base::TimeDelta duration) const { |
+ TimeDelta duration) const { |
base::AutoLock auto_lock(lock_); |
Ranges<TimeDelta> range = stream_->GetBufferedTime(); |
@@ -578,16 +579,15 @@ void ChunkDemuxer::Initialize(DemuxerHost* host, const PipelineStatusCB& cb) { |
base::AutoLock auto_lock(lock_); |
+ init_cb_ = BindToCurrentLoop(cb); |
if (state_ == SHUTDOWN) { |
- base::MessageLoopProxy::current()->PostTask(FROM_HERE, base::Bind( |
- cb, DEMUXER_ERROR_COULD_NOT_OPEN)); |
+ base::ResetAndReturn(&init_cb_).Run(DEMUXER_ERROR_COULD_NOT_OPEN); |
return; |
} |
DCHECK_EQ(state_, WAITING_FOR_INIT); |
host_ = host; |
ChangeState_Locked(INITIALIZING); |
- init_cb_ = cb; |
base::ResetAndReturn(&open_cb_).Run(); |
} |
@@ -604,27 +604,25 @@ void ChunkDemuxer::Seek(TimeDelta time, const PipelineStatusCB& cb) { |
DCHECK(seek_cb_.is_null()); |
PipelineStatus status = PIPELINE_ERROR_INVALID_STATE; |
- { |
- base::AutoLock auto_lock(lock_); |
- |
- if (state_ == INITIALIZED || state_ == ENDED) { |
- if (audio_) |
- audio_->Seek(time); |
+ base::AutoLock auto_lock(lock_); |
- if (video_) |
- video_->Seek(time); |
+ seek_cb_ = BindToCurrentLoop(cb); |
+ if (state_ == INITIALIZED || state_ == ENDED) { |
+ if (audio_) |
+ audio_->Seek(time); |
- if (IsSeekPending_Locked()) { |
- DVLOG(1) << "Seek() : waiting for more data to arrive."; |
- seek_cb_ = cb; |
- return; |
- } |
+ if (video_) |
+ video_->Seek(time); |
- status = PIPELINE_OK; |
+ if (IsSeekWaitingForData_Locked()) { |
+ DVLOG(1) << "Seek() : waiting for more data to arrive."; |
+ return; |
} |
+ |
+ status = PIPELINE_OK; |
} |
- cb.Run(status); |
+ base::ResetAndReturn(&seek_cb_).Run(status); |
} |
void ChunkDemuxer::OnAudioRendererDisabled() { |
@@ -665,21 +663,17 @@ void ChunkDemuxer::StartWaitingForSeek() { |
} |
void ChunkDemuxer::CancelPendingSeek() { |
- PipelineStatusCB cb; |
- { |
- base::AutoLock auto_lock(lock_); |
- if (IsSeekPending_Locked() && !seek_cb_.is_null()) { |
- std::swap(cb, seek_cb_); |
- } |
- if (audio_) |
- audio_->CancelPendingSeek(); |
+ base::AutoLock auto_lock(lock_); |
+ DCHECK(seek_cb_.is_null() != IsSeekWaitingForData_Locked()); |
- if (video_) |
- video_->CancelPendingSeek(); |
- } |
+ if (audio_) |
+ audio_->CancelPendingSeek(); |
+ |
+ if (video_) |
+ video_->CancelPendingSeek(); |
- if (!cb.is_null()) |
- cb.Run(PIPELINE_OK); |
+ if (!seek_cb_.is_null()) |
+ base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK); |
} |
ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id, |
@@ -815,12 +809,12 @@ void ChunkDemuxer::AppendData(const std::string& id, |
Ranges<TimeDelta> ranges; |
- PipelineStatusCB cb; |
{ |
base::AutoLock auto_lock(lock_); |
- // Capture if the SourceBuffer has a pending seek before we start parsing. |
- bool old_seek_pending = IsSeekPending_Locked(); |
+ // Capture if any of the SourceBuffers are waiting for data before we start |
+ // parsing. |
+ bool old_waiting_for_data = IsSeekWaitingForData_Locked(); |
if (state_ == ENDED) { |
ChangeState_Locked(INITIALIZED); |
@@ -867,8 +861,9 @@ void ChunkDemuxer::AppendData(const std::string& id, |
// Check to see if data was appended at the pending seek point. This |
// indicates we have parsed enough data to complete the seek. |
- if (old_seek_pending && !IsSeekPending_Locked() && !seek_cb_.is_null()) { |
- std::swap(cb, seek_cb_); |
+ if (old_waiting_for_data && !IsSeekWaitingForData_Locked() && |
+ !seek_cb_.is_null()) { |
+ base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK); |
} |
ranges = GetBufferedRanges(); |
@@ -876,9 +871,6 @@ void ChunkDemuxer::AppendData(const std::string& id, |
for (size_t i = 0; i < ranges.size(); ++i) |
host_->AddBufferedTimeRange(ranges.start(i), ranges.end(i)); |
- |
- if (!cb.is_null()) |
- cb.Run(PIPELINE_OK); |
} |
void ChunkDemuxer::Abort(const std::string& id) { |
@@ -920,14 +912,13 @@ void ChunkDemuxer::SetDuration(double duration) { |
// Compute & bounds check the TimeDelta representation of duration. |
// This can be different if the value of |duration| doesn't fit the range or |
- // precision of base::TimeDelta. |
- base::TimeDelta min_duration = base::TimeDelta::FromInternalValue(1); |
- base::TimeDelta max_duration = |
- base::TimeDelta::FromInternalValue(kint64max - 1); |
+ // precision of TimeDelta. |
+ TimeDelta min_duration = TimeDelta::FromInternalValue(1); |
+ TimeDelta max_duration = TimeDelta::FromInternalValue(kint64max - 1); |
double min_duration_in_seconds = min_duration.InSecondsF(); |
double max_duration_in_seconds = max_duration.InSecondsF(); |
- base::TimeDelta duration_td; |
+ TimeDelta duration_td; |
if (duration == std::numeric_limits<double>::infinity()) { |
duration_td = media::kInfiniteDuration(); |
} else if (duration < min_duration_in_seconds) { |
@@ -935,11 +926,11 @@ void ChunkDemuxer::SetDuration(double duration) { |
} else if (duration > max_duration_in_seconds) { |
duration_td = max_duration; |
} else { |
- duration_td = base::TimeDelta::FromMicroseconds( |
+ duration_td = TimeDelta::FromMicroseconds( |
duration * base::Time::kMicrosecondsPerSecond); |
} |
- DCHECK(duration_td > base::TimeDelta()); |
+ DCHECK(duration_td > TimeDelta()); |
user_specified_duration_ = duration; |
duration_ = duration_td; |
@@ -962,66 +953,57 @@ bool ChunkDemuxer::SetTimestampOffset(const std::string& id, TimeDelta offset) { |
void ChunkDemuxer::EndOfStream(PipelineStatus status) { |
DVLOG(1) << "EndOfStream(" << status << ")"; |
- PipelineStatusCB cb; |
- { |
- base::AutoLock auto_lock(lock_); |
- DCHECK_NE(state_, WAITING_FOR_INIT); |
- DCHECK_NE(state_, ENDED); |
+ base::AutoLock auto_lock(lock_); |
+ DCHECK_NE(state_, WAITING_FOR_INIT); |
+ DCHECK_NE(state_, ENDED); |
- if (state_ == SHUTDOWN || state_ == PARSE_ERROR) |
- return; |
+ if (state_ == SHUTDOWN || state_ == PARSE_ERROR) |
+ return; |
- if (state_ == INITIALIZING) { |
- ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); |
- return; |
- } |
+ if (state_ == INITIALIZING) { |
+ ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); |
+ return; |
+ } |
- bool old_seek_pending = IsSeekPending_Locked(); |
- if (audio_) |
- audio_->EndOfStream(); |
+ bool old_waiting_for_data = IsSeekWaitingForData_Locked(); |
+ if (audio_) |
+ audio_->EndOfStream(); |
- if (video_) |
- video_->EndOfStream(); |
+ if (video_) |
+ video_->EndOfStream(); |
- // Give a chance to resume the pending seek process. |
- if (status != PIPELINE_OK) { |
- ReportError_Locked(status); |
- return; |
- } |
+ // Give a chance to resume the pending seek process. |
+ if (status != PIPELINE_OK) { |
+ ReportError_Locked(status); |
+ return; |
+ } |
- ChangeState_Locked(ENDED); |
- DecreaseDurationIfNecessary(); |
+ ChangeState_Locked(ENDED); |
+ DecreaseDurationIfNecessary(); |
- if (old_seek_pending && !IsSeekPending_Locked() && !seek_cb_.is_null()) |
- std::swap(cb, seek_cb_); |
+ if (old_waiting_for_data && !IsSeekWaitingForData_Locked() && |
+ !seek_cb_.is_null()) { |
+ base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK); |
} |
- |
- if (!cb.is_null()) |
- cb.Run(PIPELINE_OK); |
} |
void ChunkDemuxer::Shutdown() { |
DVLOG(1) << "Shutdown()"; |
- PipelineStatusCB cb; |
- { |
- base::AutoLock auto_lock(lock_); |
- |
- if (state_ == SHUTDOWN) |
- return; |
+ base::AutoLock auto_lock(lock_); |
- std::swap(cb, seek_cb_); |
+ if (state_ == SHUTDOWN) |
+ return; |
- if (audio_) |
- audio_->Shutdown(); |
+ if (audio_) |
+ audio_->Shutdown(); |
- if (video_) |
- video_->Shutdown(); |
+ if (video_) |
+ video_->Shutdown(); |
- ChangeState_Locked(SHUTDOWN); |
- } |
+ ChangeState_Locked(SHUTDOWN); |
- if (!cb.is_null()) |
- cb.Run(PIPELINE_ERROR_ABORT); |
+ if(!seek_cb_.is_null()) |
+ base::ResetAndReturn(&seek_cb_).Run(PIPELINE_ERROR_ABORT); |
} |
void ChunkDemuxer::ChangeState_Locked(State new_state) { |
@@ -1063,7 +1045,6 @@ void ChunkDemuxer::ReportError_Locked(PipelineStatus error) { |
} |
if (!cb.is_null()) { |
- base::AutoUnlock auto_unlock(lock_); |
cb.Run(error); |
return; |
} |
@@ -1072,17 +1053,17 @@ void ChunkDemuxer::ReportError_Locked(PipelineStatus error) { |
host_->OnDemuxerError(error); |
} |
-bool ChunkDemuxer::IsSeekPending_Locked() const { |
+bool ChunkDemuxer::IsSeekWaitingForData_Locked() const { |
lock_.AssertAcquired(); |
- bool seek_pending = false; |
+ bool waiting_for_data = false; |
if (audio_) |
- seek_pending = audio_->IsSeekPending(); |
+ waiting_for_data = audio_->IsSeekWaitingForData(); |
- if (!seek_pending && video_) |
- seek_pending = video_->IsSeekPending(); |
+ if (!waiting_for_data && video_) |
+ waiting_for_data = video_->IsSeekWaitingForData(); |
- return seek_pending; |
+ return waiting_for_data; |
} |
void ChunkDemuxer::OnSourceInitDone(bool success, TimeDelta duration) { |
@@ -1095,7 +1076,7 @@ void ChunkDemuxer::OnSourceInitDone(bool success, TimeDelta duration) { |
return; |
} |
- if (duration != base::TimeDelta() && duration_ == kNoTimestamp()) |
+ if (duration != TimeDelta() && duration_ == kNoTimestamp()) |
UpdateDuration(duration); |
// Wait until all streams have initialized. |
@@ -1216,8 +1197,8 @@ bool ChunkDemuxer::OnTextBuffers( |
for (StreamParser::BufferQueue::const_iterator itr = buffers.begin(); |
itr != buffers.end(); ++itr) { |
const StreamParserBuffer* const buffer = itr->get(); |
- const base::TimeDelta start = buffer->GetTimestamp(); |
- const base::TimeDelta end = start + buffer->GetDuration(); |
+ const TimeDelta start = buffer->GetTimestamp(); |
+ const TimeDelta end = start + buffer->GetDuration(); |
std::string id, settings, content; |
@@ -1261,7 +1242,7 @@ bool ChunkDemuxer::IsValidId(const std::string& source_id) const { |
return source_state_map_.count(source_id) > 0u; |
} |
-void ChunkDemuxer::UpdateDuration(base::TimeDelta new_duration) { |
+void ChunkDemuxer::UpdateDuration(TimeDelta new_duration) { |
DCHECK(duration_ != new_duration); |
user_specified_duration_ = -1; |
duration_ = new_duration; |
@@ -1278,7 +1259,7 @@ void ChunkDemuxer::IncreaseDurationIfNecessary( |
Ranges<TimeDelta> ranges = stream->GetBufferedRanges(kInfiniteDuration()); |
DCHECK_GT(ranges.size(), 0u); |
- base::TimeDelta last_timestamp_buffered = ranges.end(ranges.size() - 1); |
+ TimeDelta last_timestamp_buffered = ranges.end(ranges.size() - 1); |
if (last_timestamp_buffered > duration_) |
UpdateDuration(last_timestamp_buffered); |
} |
@@ -1288,7 +1269,7 @@ void ChunkDemuxer::DecreaseDurationIfNecessary() { |
if (ranges.size() == 0u) |
return; |
- base::TimeDelta last_timestamp_buffered = ranges.end(ranges.size() - 1); |
+ TimeDelta last_timestamp_buffered = ranges.end(ranges.size() - 1); |
if (last_timestamp_buffered < duration_) |
UpdateDuration(last_timestamp_buffered); |
} |