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

Unified Diff: media/filters/chunk_demuxer.cc

Issue 13652012: Refactor ChunkDemuxer code so all source state is in a SourceState class. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address CR comments. Created 7 years, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/filters/chunk_demuxer.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/filters/chunk_demuxer.cc
diff --git a/media/filters/chunk_demuxer.cc b/media/filters/chunk_demuxer.cc
index fdd47e7fcf8cb4f2e3871fb82b03658d519bec51..cc086af4c5f4b04eb49306b212665c1d5f116ecb 100644
--- a/media/filters/chunk_demuxer.cc
+++ b/media/filters/chunk_demuxer.cc
@@ -21,6 +21,147 @@ using base::TimeDelta;
namespace media {
+// Contains state belonging to a source id.
+class SourceState {
+ public:
+ explicit SourceState(scoped_ptr<StreamParser> stream_parser);
+
+ void Init(const StreamParser::InitCB& init_cb,
+ const StreamParser::NewConfigCB& config_cb,
+ const StreamParser::NewBuffersCB& audio_cb,
+ const StreamParser::NewBuffersCB& video_cb,
+ const StreamParser::NeedKeyCB& need_key_cb,
+ const StreamParser::NewMediaSegmentCB& new_segment_cb,
+ const LogCB& log_cb);
+
+ // Appends new data to the StreamParser.
+ // Returns true if the data was successfully appended. Returns false if an
+ // error occurred.
+ bool Append(const uint8* data, size_t length);
+
+ // Aborts the current append sequence and resets the parser.
+ void Abort();
+
+ // Sets |timestamp_offset_| if possible.
+ // Returns if the offset was set. Returns false if the offset could not be
+ // updated at this time.
+ bool SetTimestampOffset(TimeDelta timestamp_offset);
+
+ TimeDelta timestamp_offset() const { return timestamp_offset_; }
+
+ private:
+ // Called by the |stream_parser_| at the beginning of a new media segment.
+ // |timestamp| is the timestamp on the first buffer in the segment.
+ // It modifies the state of this object and then calls |new_segment_cb| with
+ // modified version of |timestamp|.
+ void OnNewMediaSegment(const StreamParser::NewMediaSegmentCB& new_segment_cb,
+ TimeDelta timestamp);
+
+ // Called by the |stream_parser_| at the end of a media segment.
+ void OnEndOfMediaSegment();
+
+ // Called by the |stream_parser_| when new buffers have been parsed. It
+ // applies |timestamp_offset_| to all buffers in |buffers| and then calls
+ // |new_buffers_cb| with the modified buffers.
+ // Returns true on a successful call. Returns false if an error occured while
+ // processing the buffers.
+ bool OnBuffers(const StreamParser::NewBuffersCB& new_buffers_cb,
+ const StreamParser::BufferQueue& buffers);
+
+ // Helper function that adds |timestamp_offset_| to each buffer in |buffers|.
+ void AdjustBufferTimestamps(const StreamParser::BufferQueue& buffers);
+
+ // The offset to apply to media segment timestamps.
+ TimeDelta timestamp_offset_;
+
+ // Keeps track of whether |timestamp_offset_| can be modified.
+ bool can_update_offset_;
+
+ // The object used to parse appended data.
+ scoped_ptr<StreamParser> stream_parser_;
+
+ DISALLOW_COPY_AND_ASSIGN(SourceState);
+};
+
+SourceState::SourceState(scoped_ptr<StreamParser> stream_parser)
+ : can_update_offset_(true),
+ stream_parser_(stream_parser.release()) {
+}
+
+void SourceState::Init(const StreamParser::InitCB& init_cb,
+ const StreamParser::NewConfigCB& config_cb,
+ const StreamParser::NewBuffersCB& audio_cb,
+ const StreamParser::NewBuffersCB& video_cb,
+ const StreamParser::NeedKeyCB& need_key_cb,
+ const StreamParser::NewMediaSegmentCB& new_segment_cb,
+ const LogCB& log_cb) {
+ stream_parser_->Init(init_cb, config_cb,
+ base::Bind(&SourceState::OnBuffers,
+ base::Unretained(this), audio_cb),
+ base::Bind(&SourceState::OnBuffers,
+ base::Unretained(this), video_cb),
+ need_key_cb,
+ base::Bind(&SourceState::OnNewMediaSegment,
+ base::Unretained(this), new_segment_cb),
+ base::Bind(&SourceState::OnEndOfMediaSegment,
+ base::Unretained(this)),
+ log_cb);
+}
+
+bool SourceState::SetTimestampOffset(TimeDelta timestamp_offset) {
+ if (!can_update_offset_)
+ return false;
+
+ timestamp_offset_ = timestamp_offset;
+ return true;
+}
+
+bool SourceState::Append(const uint8* data, size_t length) {
+ return stream_parser_->Parse(data, length);
+}
+
+void SourceState::Abort() {
+ stream_parser_->Flush();
+ can_update_offset_ = true;
+}
+
+void SourceState::AdjustBufferTimestamps(
+ const StreamParser::BufferQueue& buffers) {
+ if (timestamp_offset_ == TimeDelta())
+ return;
+
+ for (StreamParser::BufferQueue::const_iterator itr = buffers.begin();
+ itr != buffers.end(); ++itr) {
+ (*itr)->SetDecodeTimestamp(
+ (*itr)->GetDecodeTimestamp() + timestamp_offset_);
+ (*itr)->SetTimestamp((*itr)->GetTimestamp() + timestamp_offset_);
+ }
+}
+
+void SourceState::OnNewMediaSegment(
+ const StreamParser::NewMediaSegmentCB& new_segment_cb,
+ TimeDelta timestamp) {
+ DCHECK(timestamp != kNoTimestamp());
+ DVLOG(2) << "OnNewMediaSegment(" << timestamp.InSecondsF() << ")";
+
+ can_update_offset_ = false;
+ new_segment_cb.Run(timestamp + timestamp_offset_);
+}
+
+void SourceState::OnEndOfMediaSegment() {
+ DVLOG(2) << "OnEndOfMediaSegment()";
+ can_update_offset_ = true;
+}
+
+bool SourceState::OnBuffers(const StreamParser::NewBuffersCB& new_buffers_cb,
+ const StreamParser::BufferQueue& buffers) {
+ if (new_buffers_cb.is_null())
+ return false;
+
+ AdjustBufferTimestamps(buffers);
+
+ return new_buffers_cb.Run(buffers);
+}
class ChunkDemuxerStream : public DemuxerStream {
public:
@@ -533,8 +674,7 @@ ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id,
DCHECK_GT(codecs.size(), 0u);
base::AutoLock auto_lock(lock_);
- if ((state_ != WAITING_FOR_INIT && state_ != INITIALIZING) ||
- stream_parser_map_.count(id) > 0u)
+ if ((state_ != WAITING_FOR_INIT && state_ != INITIALIZING) || IsValidId(id))
return kReachedIdLimit;
bool has_audio = false;
@@ -565,22 +705,18 @@ ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id,
base::Unretained(this));
}
- stream_parser->Init(
- base::Bind(&ChunkDemuxer::OnStreamParserInitDone, base::Unretained(this)),
+ scoped_ptr<SourceState> source_state(new SourceState(stream_parser.Pass()));
+ source_state->Init(
+ base::Bind(&ChunkDemuxer::OnSourceInitDone, base::Unretained(this)),
base::Bind(&ChunkDemuxer::OnNewConfigs, base::Unretained(this),
has_audio, has_video),
audio_cb,
video_cb,
base::Bind(&ChunkDemuxer::OnNeedKey, base::Unretained(this)),
base::Bind(&ChunkDemuxer::OnNewMediaSegment, base::Unretained(this), id),
- base::Bind(&ChunkDemuxer::OnEndOfMediaSegment,
- base::Unretained(this), id),
log_cb_);
- stream_parser_map_[id] = stream_parser.release();
- SourceInfo info = { base::TimeDelta(), true };
- source_info_map_[id] = info;
-
+ source_state_map_[id] = source_state.release();
return kOk;
}
@@ -588,9 +724,8 @@ void ChunkDemuxer::RemoveId(const std::string& id) {
base::AutoLock auto_lock(lock_);
CHECK(IsValidId(id));
- delete stream_parser_map_[id];
- stream_parser_map_.erase(id);
- source_info_map_.erase(id);
+ delete source_state_map_[id];
+ source_state_map_.erase(id);
if (source_id_audio_ == id) {
if (audio_)
@@ -689,7 +824,7 @@ void ChunkDemuxer::AppendData(const std::string& id,
switch (state_) {
case INITIALIZING:
DCHECK(IsValidId(id));
- if (!stream_parser_map_[id]->Parse(data, length)) {
+ if (!source_state_map_[id]->Append(data, length)) {
ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN);
return;
}
@@ -697,7 +832,7 @@ void ChunkDemuxer::AppendData(const std::string& id,
case INITIALIZED: {
DCHECK(IsValidId(id));
- if (!stream_parser_map_[id]->Parse(data, length)) {
+ if (!source_state_map_[id]->Append(data, length)) {
ReportError_Locked(PIPELINE_ERROR_DECODE);
return;
}
@@ -735,8 +870,7 @@ void ChunkDemuxer::Abort(const std::string& id) {
base::AutoLock auto_lock(lock_);
DCHECK(!id.empty());
CHECK(IsValidId(id));
- stream_parser_map_[id]->Flush();
- source_info_map_[id].can_update_offset = true;
+ source_state_map_[id]->Abort();
}
double ChunkDemuxer::GetDuration() {
@@ -807,11 +941,7 @@ bool ChunkDemuxer::SetTimestampOffset(const std::string& id, TimeDelta offset) {
DVLOG(1) << "SetTimestampOffset(" << id << ", " << offset.InSecondsF() << ")";
CHECK(IsValidId(id));
- if (!source_info_map_[id].can_update_offset)
- return false;
-
- source_info_map_[id].timestamp_offset = offset;
- return true;
+ return source_state_map_[id]->SetTimestampOffset(offset);
}
bool ChunkDemuxer::EndOfStream(PipelineStatus status) {
@@ -880,11 +1010,11 @@ void ChunkDemuxer::ChangeState_Locked(State new_state) {
ChunkDemuxer::~ChunkDemuxer() {
DCHECK_NE(state_, INITIALIZED);
- for (StreamParserMap::iterator it = stream_parser_map_.begin();
- it != stream_parser_map_.end(); ++it) {
+ for (SourceStateMap::iterator it = source_state_map_.begin();
+ it != source_state_map_.end(); ++it) {
delete it->second;
}
- stream_parser_map_.clear();
+ source_state_map_.clear();
}
void ChunkDemuxer::ReportError_Locked(PipelineStatus error) {
@@ -938,8 +1068,8 @@ bool ChunkDemuxer::CanEndOfStream_Locked() const {
(!video_ || video_->CanEndOfStream());
}
-void ChunkDemuxer::OnStreamParserInitDone(bool success, TimeDelta duration) {
- DVLOG(1) << "OnStreamParserInitDone(" << success << ", "
+void ChunkDemuxer::OnSourceInitDone(bool success, TimeDelta duration) {
+ DVLOG(1) << "OnSourceInitDone(" << success << ", "
<< duration.InSecondsF() << ")";
lock_.AssertAcquired();
DCHECK_EQ(state_, INITIALIZING);
@@ -1036,9 +1166,6 @@ bool ChunkDemuxer::OnAudioBuffers(const StreamParser::BufferQueue& buffers) {
return false;
CHECK(IsValidId(source_id_audio_));
- AdjustBufferTimestamps(
- buffers, source_info_map_[source_id_audio_].timestamp_offset);
-
if (!audio_->Append(buffers))
return false;
@@ -1054,9 +1181,6 @@ bool ChunkDemuxer::OnVideoBuffers(const StreamParser::BufferQueue& buffers) {
return false;
CHECK(IsValidId(source_id_video_));
- AdjustBufferTimestamps(
- buffers, source_info_map_[source_id_video_].timestamp_offset);
-
if (!video_->Append(buffers))
return false;
@@ -1083,40 +1207,15 @@ void ChunkDemuxer::OnNewMediaSegment(const std::string& source_id,
lock_.AssertAcquired();
CHECK(IsValidId(source_id));
- source_info_map_[source_id].can_update_offset = false;
- base::TimeDelta start_timestamp =
- timestamp + source_info_map_[source_id].timestamp_offset;
-
if (audio_ && source_id == source_id_audio_)
- audio_->OnNewMediaSegment(start_timestamp);
+ audio_->OnNewMediaSegment(timestamp);
if (video_ && source_id == source_id_video_)
- video_->OnNewMediaSegment(start_timestamp);
-}
-
-void ChunkDemuxer::OnEndOfMediaSegment(const std::string& source_id) {
- DVLOG(2) << "OnEndOfMediaSegment(" << source_id << ")";
- CHECK(IsValidId(source_id));
- source_info_map_[source_id].can_update_offset = true;
-}
-
-void ChunkDemuxer::AdjustBufferTimestamps(
- const StreamParser::BufferQueue& buffers,
- base::TimeDelta timestamp_offset) {
- if (timestamp_offset == base::TimeDelta())
- return;
-
- for (StreamParser::BufferQueue::const_iterator itr = buffers.begin();
- itr != buffers.end(); ++itr) {
- (*itr)->SetDecodeTimestamp(
- (*itr)->GetDecodeTimestamp() + timestamp_offset);
- (*itr)->SetTimestamp((*itr)->GetTimestamp() + timestamp_offset);
- }
+ video_->OnNewMediaSegment(timestamp);
}
bool ChunkDemuxer::IsValidId(const std::string& source_id) const {
lock_.AssertAcquired();
- return source_info_map_.count(source_id) > 0u &&
- stream_parser_map_.count(source_id) > 0u;
+ return source_state_map_.count(source_id) > 0u;
}
void ChunkDemuxer::UpdateDuration(base::TimeDelta new_duration) {
« no previous file with comments | « media/filters/chunk_demuxer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698