Chromium Code Reviews| Index: media/filters/chunk_demuxer.cc |
| diff --git a/media/filters/chunk_demuxer.cc b/media/filters/chunk_demuxer.cc |
| index 17f1d96c9046de426f653cddef6ff0565b403901..bde7e0d78f8e44efa1a843789544dc59d86b8c77 100644 |
| --- a/media/filters/chunk_demuxer.cc |
| +++ b/media/filters/chunk_demuxer.cc |
| @@ -24,6 +24,30 @@ using base::TimeDelta; |
| namespace media { |
| +// Compute the end timestamp for buffers within an append window range. |
| +// TODO(dalecurtis): This code should probably live in the frame processor, but |
| +// requires some spec updates before we can do so. For now it's a logical clone |
| +// of LegacyFrameProcessor::FilterWithAppendWindow(). |
| +static TimeDelta EndTimestamp(const StreamParser::BufferQueue& buffers, |
| + TimeDelta append_window_start, |
| + TimeDelta append_window_end) { |
| + TimeDelta end_timestamp = kNoTimestamp(); |
| + |
| + // Find the last buffer within the append window range. |
| + for (StreamParser::BufferQueue::const_reverse_iterator itr = buffers.rbegin(); |
| + itr != buffers.rend(); |
| + ++itr) { |
| + const scoped_refptr<StreamParserBuffer>& buffer = *itr; |
| + if (buffer->timestamp() >= append_window_start && |
|
DaleCurtis
2014/03/18 17:49:55
This will iterate more than necessary if |buffers|
|
| + buffer->timestamp() <= append_window_end) { |
| + end_timestamp = buffer->timestamp() + buffer->duration(); |
| + break; |
| + } |
| + } |
| + |
| + return end_timestamp; |
| +} |
| + |
| // List of time ranges for each SourceBuffer. |
| typedef std::list<Ranges<TimeDelta> > RangesList; |
| static Ranges<TimeDelta> ComputeIntersection(const RangesList& activeRanges, |
| @@ -89,6 +113,13 @@ class SourceState { |
| typedef base::Callback<void( |
| ChunkDemuxerStream*, const TextTrackConfig&)> NewTextTrackCB; |
| + // First parameter - Indicates initialization success. Set to true if |
| + // initialization was successful. False if an error |
| + // occurred. |
| + // Second parameter - Indicates the stream duration. Only contains a valid |
| + // value if the first parameter is true. |
| + typedef base::Callback<void(bool, TimeDelta)> InitCB; |
| + |
| SourceState( |
| scoped_ptr<StreamParser> stream_parser, |
| scoped_ptr<FrameProcessorBase> frame_processor, const LogCB& log_cb, |
| @@ -96,7 +127,7 @@ class SourceState { |
| ~SourceState(); |
| - void Init(const StreamParser::InitCB& init_cb, |
| + void Init(const InitCB& init_cb, |
| bool allow_audio, |
| bool allow_video, |
| const StreamParser::NeedKeyCB& need_key_cb, |
| @@ -177,6 +208,10 @@ class SourceState { |
| const StreamParser::BufferQueue& video_buffers, |
| const StreamParser::TextBufferQueueMap& text_map); |
| + void OnSourceInitDone(bool success, |
| + TimeDelta duration, |
| + bool auto_update_timestamp_offset); |
| + |
| CreateDemuxerStreamCB create_demuxer_stream_cb_; |
| NewTextTrackCB new_text_track_cb_; |
| @@ -216,6 +251,11 @@ class SourceState { |
| scoped_ptr<FrameProcessorBase> frame_processor_; |
| LogCB log_cb_; |
| + InitCB init_cb_; |
| + |
| + // Indicates that timestampOffset should be updated automatically during |
| + // OnNewBuffers() based on the earliest end timestamp of the buffers provided. |
| + bool auto_update_timestamp_offset_; |
| DISALLOW_COPY_AND_ASSIGN(SourceState); |
| }; |
| @@ -233,7 +273,8 @@ SourceState::SourceState( |
| audio_(NULL), |
| video_(NULL), |
| frame_processor_(frame_processor.release()), |
| - log_cb_(log_cb) { |
| + log_cb_(log_cb), |
| + auto_update_timestamp_offset_(false) { |
| DCHECK(!create_demuxer_stream_cb_.is_null()); |
| DCHECK(frame_processor_); |
| } |
| @@ -244,14 +285,16 @@ SourceState::~SourceState() { |
| STLDeleteValues(&text_stream_map_); |
| } |
| -void SourceState::Init(const StreamParser::InitCB& init_cb, |
| +void SourceState::Init(const InitCB& init_cb, |
| bool allow_audio, |
| bool allow_video, |
| const StreamParser::NeedKeyCB& need_key_cb, |
| const NewTextTrackCB& new_text_track_cb) { |
| new_text_track_cb_ = new_text_track_cb; |
| + init_cb_ = init_cb; |
| - stream_parser_->Init(init_cb, |
| + stream_parser_->Init(base::Bind(&SourceState::OnSourceInitDone, |
| + base::Unretained(this)), |
| base::Bind(&SourceState::OnNewConfigs, |
| base::Unretained(this), |
| allow_audio, |
| @@ -638,10 +681,46 @@ bool SourceState::OnNewBuffers( |
| DVLOG(2) << "OnNewBuffers()"; |
| DCHECK(timestamp_offset_during_append_); |
| - return frame_processor_->ProcessFrames( |
| - audio_buffers, video_buffers, text_map, |
| - append_window_start_during_append_, append_window_end_during_append_, |
| - &new_media_segment_, timestamp_offset_during_append_); |
| + const TimeDelta current_timestamp_offset = *timestamp_offset_during_append_; |
| + if (!frame_processor_->ProcessFrames(audio_buffers, |
| + video_buffers, |
| + text_map, |
| + append_window_start_during_append_, |
| + append_window_end_during_append_, |
| + &new_media_segment_, |
| + timestamp_offset_during_append_)) { |
| + return false; |
| + } |
| + |
| + // Update the timestamp offset for audio/video tracks if it hasn't already |
| + // been updated by the frame processor. |
| + if (auto_update_timestamp_offset_ && |
| + current_timestamp_offset == *timestamp_offset_during_append_) { |
| + const TimeDelta audio_end = EndTimestamp(audio_buffers, |
| + append_window_start_during_append_, |
| + append_window_end_during_append_); |
| + const TimeDelta video_end = EndTimestamp(video_buffers, |
| + append_window_start_during_append_, |
| + append_window_end_during_append_); |
| + const bool have_audio_buffers = audio_end != kNoTimestamp(); |
| + const bool have_video_buffers = video_end != kNoTimestamp(); |
| + if (have_audio_buffers && have_video_buffers) { |
| + *timestamp_offset_during_append_ = std::min(audio_end, video_end); |
| + } else if (have_audio_buffers) { |
| + *timestamp_offset_during_append_ = audio_end; |
| + } else if (have_video_buffers) { |
| + *timestamp_offset_during_append_ = video_end; |
| + } |
| + } |
| + |
| + return true; |
| +} |
| + |
| +void SourceState::OnSourceInitDone(bool success, |
| + TimeDelta duration, |
| + bool auto_update_timestamp_offset) { |
| + auto_update_timestamp_offset_ = auto_update_timestamp_offset; |
| + base::ResetAndReturn(&init_cb_).Run(success, duration); |
| } |
| ChunkDemuxerStream::ChunkDemuxerStream(Type type) |
| @@ -1417,8 +1496,8 @@ bool ChunkDemuxer::IsSeekWaitingForData_Locked() const { |
| } |
| void ChunkDemuxer::OnSourceInitDone(bool success, TimeDelta duration) { |
| - DVLOG(1) << "OnSourceInitDone(" << success << ", " |
| - << duration.InSecondsF() << ")"; |
| + DVLOG(1) << "OnSourceInitDone(" << success |
| + << ", " << duration.InSecondsF() << ")"; |
| lock_.AssertAcquired(); |
| DCHECK_EQ(state_, INITIALIZING); |
| if (!success || (!audio_ && !video_)) { |