Index: media/filters/frame_processor.cc |
diff --git a/media/filters/frame_processor.cc b/media/filters/frame_processor.cc |
index bf0b2a5c4a4d20e3ea04d46f7360f6a62845a2ec..a10ed5017ed50814a2269dd0fde06d8fa3189618 100644 |
--- a/media/filters/frame_processor.cc |
+++ b/media/filters/frame_processor.cc |
@@ -67,6 +67,14 @@ class MseTrackBuffer { |
// monotonically increasing. |
void SetHighestPresentationTimestampIfIncreased(base::TimeDelta timestamp); |
+ // Adds |frame| to the end of |processed_frames_|. |
+ void EnqueueProcessedFrame(const scoped_refptr<StreamParserBuffer>& frame); |
+ |
+ // Appends |processed_frames_|, if not empty, to |stream_| and clears |
+ // |processed_frames_|. Returns false if append failed, true otherwise. |
+ // |processed_frames_| is cleared in both cases. |
+ bool FlushProcessedFrames(); |
+ |
private: |
// The decode timestamp of the last coded frame appended in the current coded |
// frame group. Initially kNoTimestamp(), meaning "unset". |
@@ -91,6 +99,11 @@ class MseTrackBuffer { |
// by |this|. |
ChunkDemuxerStream* const stream_; |
+ // Queue of processed frames that have not yet been appended to |stream_|. |
+ // EnqueueProcessedFrame() adds to this queue, and FlushProcessedFrames() |
+ // clears it. |
+ StreamParser::BufferQueue processed_frames_; |
+ |
DISALLOW_COPY_AND_ASSIGN(MseTrackBuffer); |
}; |
@@ -124,6 +137,23 @@ void MseTrackBuffer::SetHighestPresentationTimestampIfIncreased( |
} |
} |
+void MseTrackBuffer::EnqueueProcessedFrame( |
+ const scoped_refptr<StreamParserBuffer>& frame) { |
+ processed_frames_.push_back(frame); |
+} |
+ |
+bool MseTrackBuffer::FlushProcessedFrames() { |
+ if (processed_frames_.empty()) |
+ return true; |
+ |
+ bool result = stream_->Append(processed_frames_); |
+ processed_frames_.clear(); |
+ DVLOG_IF(3, !result) << __FUNCTION__ |
+ << "(): Failure appending processed frames to stream"; |
+ |
+ return result; |
+} |
+ |
FrameProcessor::FrameProcessor(const UpdateDurationCB& update_duration_cb) |
: sequence_mode_(false), |
group_start_timestamp_(kNoTimestamp()), |
@@ -180,10 +210,14 @@ bool FrameProcessor::ProcessFrames( |
frames_itr != frames.end(); ++frames_itr) { |
if (!ProcessFrame(*frames_itr, append_window_start, append_window_end, |
timestamp_offset, new_media_segment)) { |
+ FlushProcessedFrames(); |
return false; |
} |
} |
+ if (!FlushProcessedFrames()) |
+ return false; |
+ |
// 2. - 4. Are handled by the WebMediaPlayer / Pipeline / Media Element. |
// Step 5: |
@@ -278,6 +312,20 @@ void FrameProcessor::NotifyNewMediaSegmentStarting( |
} |
} |
+bool FrameProcessor::FlushProcessedFrames() { |
+ DVLOG(2) << __FUNCTION__ << "()"; |
+ |
+ bool result = true; |
+ for (TrackBufferMap::iterator itr = track_buffers_.begin(); |
+ itr != track_buffers_.end(); |
+ ++itr) { |
+ if (!itr->second->FlushProcessedFrames()) |
+ result = false; |
+ } |
+ |
+ return result; |
+} |
+ |
bool FrameProcessor::HandlePartialAppendWindowTrimming( |
base::TimeDelta append_window_start, |
base::TimeDelta append_window_end, |
@@ -595,6 +643,11 @@ bool FrameProcessor::ProcessFrame( |
// If it is the first in a new media segment or following a discontinuity, |
// notify all the track buffers' streams that a new segment is beginning. |
if (*new_media_segment) { |
+ // First, complete the append to track buffer streams of previous media |
+ // segment's frames, if any. |
+ if (!FlushProcessedFrames()) |
+ return false; |
+ |
*new_media_segment = false; |
NotifyNewMediaSegmentStarting(decode_timestamp); |
} |
@@ -603,16 +656,12 @@ bool FrameProcessor::ProcessFrame( |
<< "PTS=" << presentation_timestamp.InSecondsF() |
<< ", DTS=" << decode_timestamp.InSecondsF(); |
- // Steps 13-18: |
- // TODO(wolenetz): Collect and emit more than one buffer at a time, if |
- // possible. Also refactor SourceBufferStream to conform to spec GC timing. |
+ // Steps 13-18: Note, we optimize by appending groups of contiguous |
+ // processed frames for each track buffer at end of ProcessFrames() or prior |
+ // to NotifyNewMediaSegmentStarting(). |
+ // TODO(wolenetz): Refactor SourceBufferStream to conform to spec GC timing. |
// See http://crbug.com/371197. |
- StreamParser::BufferQueue buffer_to_append; |
- buffer_to_append.push_back(frame); |
- if (!track_buffer->stream()->Append(buffer_to_append)) { |
- DVLOG(3) << __FUNCTION__ << ": Failure appending frame to stream"; |
- return false; |
- } |
+ track_buffer->EnqueueProcessedFrame(frame); |
// 19. Set last decode timestamp for track buffer to decode timestamp. |
track_buffer->set_last_decode_timestamp(decode_timestamp); |