Chromium Code Reviews| Index: media/filters/chunk_demuxer.cc |
| diff --git a/media/filters/chunk_demuxer.cc b/media/filters/chunk_demuxer.cc |
| index 2e22cd834f5b69ad66f0a2a95b00207e94d5fcbd..71024a9adf55abc1489b0440fcb25b4b9c1c3e45 100644 |
| --- a/media/filters/chunk_demuxer.cc |
| +++ b/media/filters/chunk_demuxer.cc |
| @@ -108,11 +108,14 @@ class SourceState { |
| // Appends new data to the StreamParser. |
| // Returns true if the data was successfully appended. Returns false if an |
| - // error occurred. Appending uses cached |timestamp_offset_| and may update |
| - // |*timestamp_offset| if |timestamp_offset| is not NULL. |
| - // TODO(wolenetz): Rework so |timestamp_offset_| is only valid during |
| - // Append(). See http://crbug.com/347623. |
| - bool Append(const uint8* data, size_t length, double* timestamp_offset); |
| + // error occurred. |*timestamp_offset| is used and possibly updated by the |
| + // append. |append_window_start| and |append_window_end| correspond to the MSE |
| + // spec's similarly named source buffer attributes that are used in coded |
| + // frame processing. |
| + bool Append(const uint8* data, size_t length, |
| + base::TimeDelta append_window_start_, |
| + base::TimeDelta append_window_end_, |
| + base::TimeDelta* timestamp_offset); |
| // Aborts the current append sequence and resets the parser. |
| void Abort(); |
| @@ -121,20 +124,11 @@ class SourceState { |
| // ChunkDemuxerStreams managed by this object. |
| void Remove(TimeDelta start, TimeDelta end, TimeDelta duration); |
| - // Sets user-specified |timestamp_offset_| if possible. |
| - // Returns true if the offset was set. Returns false if the offset could not |
| - // be set at this time. |
| - bool SetTimestampOffset(TimeDelta timestamp_offset); |
| + // Returns true if currently parsing a media segment, or false otherwise. |
| + bool parsing_media_segment() const { return parsing_media_segment_; } |
| - // Sets |sequence_mode_| to |sequence_mode| if possible. |
| - // Returns true if the mode update was allowed. Returns false if the mode |
| - // could not be updated at this time. |
| - bool SetSequenceMode(bool sequence_mode); |
| - |
| - void set_append_window_start(TimeDelta start) { |
| - append_window_start_ = start; |
| - } |
| - void set_append_window_end(TimeDelta end) { append_window_end_ = end; } |
| + // Sets |sequence_mode_| to |sequence_mode|. |
| + void SetSequenceMode(bool sequence_mode); |
| // Returns the range of buffered data in this source, capped at |duration|. |
| // |ended| - Set to true if end of stream has been signalled and the special |
| @@ -178,10 +172,11 @@ class SourceState { |
| void OnEndOfMediaSegment(); |
| // Called by the |stream_parser_| when new buffers have been parsed. It |
| - // applies |timestamp_offset_| to all buffers in |audio_buffers|, |
| - // |video_buffers| and |text_map| and then calls Append() with the modified |
| - // buffers on |audio_|, |video_| and/or the text demuxer streams associated |
| - // with the track numbers in |text_map|. |
| + // applies |*timestamp_offset_during_append_| to all buffers in |
| + // |audio_buffers|, |video_buffers| and |text_map|, filters buffers against |
| + // |append_window_[start,end]_during_append_| and then calls Append() |
| + // with the surviving modified buffers on |audio_|, |video_| and/or the text |
| + // demuxer streams associated with the track numbers in |text_map|. |
| // Returns true on a successful call. Returns false if an error occurred while |
| // processing the buffers. |
| bool OnNewBuffers(const StreamParser::BufferQueue& audio_buffers, |
| @@ -189,8 +184,9 @@ class SourceState { |
| const StreamParser::TextBufferQueueMap& text_map); |
| // Helper function for OnNewBuffers() when new text buffers have been parsed. |
| - // It applies |timestamp_offset_| to all buffers in |buffers| and then appends |
| - // the (modified) buffers to the demuxer stream associated with |
| + // It applies |*timestamp_offset_during_append_| to all buffers in |buffers|, |
| + // filters the buffers against |append_window_[start,end]_during_append_| and |
| + // then appends the (modified) buffers to the demuxer stream associated with |
| // the track having |text_track_id|. |
| // Returns true on a successful call. Returns false if an error occurred while |
| // processing the buffers. |
| @@ -204,11 +200,12 @@ class SourceState { |
| bool AppendAndUpdateDuration(ChunkDemuxerStream* stream, |
| const StreamParser::BufferQueue& buffers); |
| - // Helper function that adds |timestamp_offset_| to each buffer in |buffers|. |
| + // Helper function that adds |*timestamp_offset_during_append_| to each buffer |
| + // in |buffers|. |
| void AdjustBufferTimestamps(const StreamParser::BufferQueue& buffers); |
| // Filters out buffers that are outside of the append window |
| - // [|append_window_start_|, |append_window_end_|). |
| + // [|append_window_start_during_append_|, |append_window_end_during_append_|). |
| // |needs_keyframe| is a pointer to the |xxx_need_keyframe_| flag |
| // associated with the |buffers|. Its state is read an updated as |
| // this method filters |buffers|. |
| @@ -222,12 +219,17 @@ class SourceState { |
| IncreaseDurationCB increase_duration_cb_; |
| NewTextTrackCB new_text_track_cb_; |
| - // The offset to apply to media segment timestamps. |
| - TimeDelta timestamp_offset_; |
| + // During Append(), if OnNewBuffers() coded frame processing updates the |
| + // timestamp offset then |*timestamp_offset_during_append_| is also updated |
| + // so Append()'s caller can know the new offset. This pointer is only non-NULL |
| + // during the lifetime of an Append() call. |
| + TimeDelta* timestamp_offset_during_append_; |
| - // Flag that tracks whether or not the current Append() operation changed |
| - // |timestamp_offset_|. |
| - bool timestamp_offset_updated_by_append_; |
| + // During Append(), coded frame processing triggered by OnNewBuffers() |
| + // requires these two attributes. These are only valid during the lifetime of |
| + // an Append() call. |
| + TimeDelta append_window_start_during_append_; |
| + TimeDelta append_window_end_during_append_; |
| // Tracks the mode by which appended media is processed. If true, then |
| // appended media is processed using "sequence" mode. Otherwise, appended |
| @@ -236,32 +238,30 @@ class SourceState { |
| // and http://crbug.com/333437. |
| bool sequence_mode_; |
| - TimeDelta append_window_start_; |
| - TimeDelta append_window_end_; |
| - |
| // Set to true if the next buffers appended within the append window |
| // represent the start of a new media segment. This flag being set |
| // triggers a call to |new_segment_cb_| when the new buffers are |
| // appended. The flag is set on actual media segment boundaries and |
| // when the "append window" filtering causes discontinuities in the |
| // appended data. |
| + // TODO(wolenetz/acolwell): Investigate if we need this, or if coded frame |
| + // processing's discontinuity logic is enough. See http://crbug.com/351489. |
| bool new_media_segment_; |
| - // Keeps track of whether |timestamp_offset_| or |sequence_mode_| can be |
| - // updated. These cannot be updated if a media segment is being parsed. |
| + // Keeps track of whether a media segment is being parsed. |
| bool parsing_media_segment_; |
| // The object used to parse appended data. |
| scoped_ptr<StreamParser> stream_parser_; |
| - ChunkDemuxerStream* audio_; |
| + ChunkDemuxerStream* audio_; // Not owned by |this|. |
| bool audio_needs_keyframe_; |
| - ChunkDemuxerStream* video_; |
| + ChunkDemuxerStream* video_; // Not owned by |this|. |
| bool video_needs_keyframe_; |
| typedef std::map<StreamParser::TrackId, ChunkDemuxerStream*> TextStreamMap; |
| - TextStreamMap text_stream_map_; |
| + TextStreamMap text_stream_map_; // |this| owns the map's stream pointers. |
| LogCB log_cb_; |
| @@ -370,9 +370,8 @@ SourceState::SourceState(scoped_ptr<StreamParser> stream_parser, |
| const IncreaseDurationCB& increase_duration_cb) |
| : create_demuxer_stream_cb_(create_demuxer_stream_cb), |
| increase_duration_cb_(increase_duration_cb), |
| - timestamp_offset_updated_by_append_(false), |
| + timestamp_offset_during_append_(NULL), |
| sequence_mode_(false), |
| - append_window_end_(kInfiniteDuration()), |
| new_media_segment_(false), |
| parsing_media_segment_(false), |
| stream_parser_(stream_parser.release()), |
| @@ -414,30 +413,26 @@ void SourceState::Init(const StreamParser::InitCB& init_cb, |
| log_cb_); |
| } |
| -bool SourceState::SetTimestampOffset(TimeDelta timestamp_offset) { |
| - if (parsing_media_segment_) |
| - return false; |
| - |
| - timestamp_offset_ = timestamp_offset; |
| - return true; |
| -} |
| - |
| -bool SourceState::SetSequenceMode(bool sequence_mode) { |
| - if (parsing_media_segment_) |
| - return false; |
| +void SourceState::SetSequenceMode(bool sequence_mode) { |
| + DCHECK(!parsing_media_segment_); |
| sequence_mode_ = sequence_mode; |
| - return true; |
| } |
| bool SourceState::Append(const uint8* data, size_t length, |
| - double* timestamp_offset) { |
| - timestamp_offset_updated_by_append_ = false; |
| + base::TimeDelta append_window_start, |
| + base::TimeDelta append_window_end, |
| + base::TimeDelta* timestamp_offset) { |
| + DCHECK(timestamp_offset); |
| + DCHECK(!timestamp_offset_during_append_); |
| + timestamp_offset_during_append_ = timestamp_offset; |
| + append_window_start_during_append_ = append_window_start; |
| + append_window_end_during_append_ = append_window_end; |
| + |
| + // TODO(wolenetz/acolwell): Curry and pass a NewBuffersCB here bound with |
| + // append window and timestamp offset pointer. See http://crbug.com/351454. |
| bool err = stream_parser_->Parse(data, length); |
| - |
| - if (timestamp_offset_updated_by_append_ && timestamp_offset) |
| - *timestamp_offset = timestamp_offset_.InSecondsF(); |
| - |
| + timestamp_offset_during_append_ = NULL; |
| return err; |
| } |
| @@ -633,14 +628,15 @@ bool SourceState::IsSeekWaitingForData() const { |
| void SourceState::AdjustBufferTimestamps( |
| const StreamParser::BufferQueue& buffers) { |
| - if (timestamp_offset_ == TimeDelta()) |
| + base::TimeDelta timestamp_offset = *timestamp_offset_during_append_; |
|
acolwell GONE FROM CHROMIUM
2014/03/11 23:51:29
nit: drop base::
wolenetz
2014/03/12 00:02:32
Done (fixed here and in a few other places in this
|
| + if (timestamp_offset == TimeDelta()) |
| return; |
| for (StreamParser::BufferQueue::const_iterator itr = buffers.begin(); |
| itr != buffers.end(); ++itr) { |
| (*itr)->SetDecodeTimestamp( |
| - (*itr)->GetDecodeTimestamp() + timestamp_offset_); |
| - (*itr)->set_timestamp((*itr)->timestamp() + timestamp_offset_); |
| + (*itr)->GetDecodeTimestamp() + timestamp_offset); |
| + (*itr)->set_timestamp((*itr)->timestamp() + timestamp_offset); |
| } |
| } |
| @@ -782,6 +778,8 @@ bool SourceState::OnNewBuffers( |
| const StreamParser::BufferQueue& audio_buffers, |
| const StreamParser::BufferQueue& video_buffers, |
| const StreamParser::TextBufferQueueMap& text_map) { |
| + DVLOG(2) << "OnNewBuffers()"; |
| + DCHECK(timestamp_offset_during_append_); |
| DCHECK(!audio_buffers.empty() || !video_buffers.empty() || |
| !text_map.empty()); |
| @@ -915,8 +913,8 @@ void SourceState::FilterWithAppendWindow( |
| // |presentation_timestamp + (*itr)->duration()|, like the spec |
| // requires, once frame durations are actually present in all buffers. |
| TimeDelta frame_end_timestamp = presentation_timestamp; |
| - if (presentation_timestamp < append_window_start_ || |
| - frame_end_timestamp > append_window_end_) { |
| + if (presentation_timestamp < append_window_start_during_append_ || |
| + frame_end_timestamp > append_window_end_during_append_) { |
| DVLOG(1) << "Dropping buffer outside append window." |
| << " presentation_timestamp " |
| << presentation_timestamp.InSecondsF(); |
| @@ -1421,10 +1419,13 @@ Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges(const std::string& id) const { |
| void ChunkDemuxer::AppendData(const std::string& id, |
| const uint8* data, size_t length, |
| - double* timestamp_offset) { |
| + base::TimeDelta append_window_start, |
| + base::TimeDelta append_window_end, |
| + base::TimeDelta* timestamp_offset) { |
| DVLOG(1) << "AppendData(" << id << ", " << length << ")"; |
| DCHECK(!id.empty()); |
| + DCHECK(timestamp_offset); |
| Ranges<TimeDelta> ranges; |
| @@ -1445,6 +1446,8 @@ void ChunkDemuxer::AppendData(const std::string& id, |
| case INITIALIZING: |
| DCHECK(IsValidId(id)); |
| if (!source_state_map_[id]->Append(data, length, |
| + append_window_start, |
| + append_window_end, |
| timestamp_offset)) { |
| ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN); |
| return; |
| @@ -1454,6 +1457,8 @@ void ChunkDemuxer::AppendData(const std::string& id, |
| case INITIALIZED: { |
| DCHECK(IsValidId(id)); |
| if (!source_state_map_[id]->Append(data, length, |
| + append_window_start, |
| + append_window_end, |
| timestamp_offset)) { |
| ReportError_Locked(PIPELINE_ERROR_DECODE); |
| return; |
| @@ -1566,22 +1571,22 @@ void ChunkDemuxer::SetDuration(double duration) { |
| } |
| } |
| -bool ChunkDemuxer::SetTimestampOffset(const std::string& id, TimeDelta offset) { |
| +bool ChunkDemuxer::IsParsingMediaSegment(const std::string& id) { |
| base::AutoLock auto_lock(lock_); |
| - DVLOG(1) << "SetTimestampOffset(" << id << ", " << offset.InSecondsF() << ")"; |
| + DVLOG(1) << "IsParsingMediaSegment(" << id << ")"; |
| CHECK(IsValidId(id)); |
| - return source_state_map_[id]->SetTimestampOffset(offset); |
| + return source_state_map_[id]->parsing_media_segment(); |
| } |
| -bool ChunkDemuxer::SetSequenceMode(const std::string& id, |
| +void ChunkDemuxer::SetSequenceMode(const std::string& id, |
| bool sequence_mode) { |
| base::AutoLock auto_lock(lock_); |
| DVLOG(1) << "SetSequenceMode(" << id << ", " << sequence_mode << ")"; |
| CHECK(IsValidId(id)); |
| DCHECK_NE(state_, ENDED); |
| - return source_state_map_[id]->SetSequenceMode(sequence_mode); |
| + source_state_map_[id]->SetSequenceMode(sequence_mode); |
| } |
| void ChunkDemuxer::MarkEndOfStream(PipelineStatus status) { |
| @@ -1634,22 +1639,6 @@ void ChunkDemuxer::UnmarkEndOfStream() { |
| } |
| } |
| -void ChunkDemuxer::SetAppendWindowStart(const std::string& id, |
| - TimeDelta start) { |
| - base::AutoLock auto_lock(lock_); |
| - DVLOG(1) << "SetAppendWindowStart(" << id << ", " |
| - << start.InSecondsF() << ")"; |
| - CHECK(IsValidId(id)); |
| - source_state_map_[id]->set_append_window_start(start); |
| -} |
| - |
| -void ChunkDemuxer::SetAppendWindowEnd(const std::string& id, TimeDelta end) { |
| - base::AutoLock auto_lock(lock_); |
| - DVLOG(1) << "SetAppendWindowEnd(" << id << ", " << end.InSecondsF() << ")"; |
| - CHECK(IsValidId(id)); |
| - source_state_map_[id]->set_append_window_end(end); |
| -} |
| - |
| void ChunkDemuxer::Shutdown() { |
| DVLOG(1) << "Shutdown()"; |
| base::AutoLock auto_lock(lock_); |