| Index: media/filters/legacy_frame_processor.cc
|
| diff --git a/media/filters/legacy_frame_processor.cc b/media/filters/legacy_frame_processor.cc
|
| deleted file mode 100644
|
| index 3707b01d633178f422d71ba9ae0fe0be0d581f6b..0000000000000000000000000000000000000000
|
| --- a/media/filters/legacy_frame_processor.cc
|
| +++ /dev/null
|
| @@ -1,288 +0,0 @@
|
| -// Copyright 2014 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "media/filters/legacy_frame_processor.h"
|
| -
|
| -#include "media/base/buffers.h"
|
| -#include "media/base/stream_parser_buffer.h"
|
| -
|
| -namespace media {
|
| -
|
| -LegacyFrameProcessor::LegacyFrameProcessor(
|
| - const IncreaseDurationCB& increase_duration_cb)
|
| - : increase_duration_cb_(increase_duration_cb) {
|
| - DVLOG(2) << __FUNCTION__ << "()";
|
| - DCHECK(!increase_duration_cb_.is_null());
|
| -}
|
| -
|
| -LegacyFrameProcessor::~LegacyFrameProcessor() {
|
| - DVLOG(2) << __FUNCTION__ << "()";
|
| -}
|
| -
|
| -void LegacyFrameProcessor::SetSequenceMode(bool sequence_mode) {
|
| - DVLOG(2) << __FUNCTION__ << "(" << sequence_mode << ")";
|
| -
|
| - sequence_mode_ = sequence_mode;
|
| -}
|
| -
|
| -bool LegacyFrameProcessor::ProcessFrames(
|
| - const StreamParser::BufferQueue& audio_buffers,
|
| - const StreamParser::BufferQueue& video_buffers,
|
| - const StreamParser::TextBufferQueueMap& text_map,
|
| - base::TimeDelta append_window_start,
|
| - base::TimeDelta append_window_end,
|
| - bool* new_media_segment,
|
| - base::TimeDelta* timestamp_offset) {
|
| - DVLOG(2) << __FUNCTION__ << "()";
|
| - DCHECK(new_media_segment);
|
| - DCHECK(timestamp_offset);
|
| -
|
| - // NOTE: Legacy coded frame processing does not update timestamp offset.
|
| - base::TimeDelta offset = *timestamp_offset;
|
| -
|
| - DCHECK(!audio_buffers.empty() || !video_buffers.empty() ||
|
| - !text_map.empty());
|
| -
|
| - MseTrackBuffer* audio_track = FindTrack(kAudioTrackId);
|
| - DCHECK(audio_buffers.empty() || audio_track);
|
| -
|
| - MseTrackBuffer* video_track = FindTrack(kVideoTrackId);
|
| - DCHECK(video_buffers.empty() || video_track);
|
| -
|
| - StreamParser::BufferQueue filtered_audio;
|
| - StreamParser::BufferQueue filtered_video;
|
| - StreamParser::TextBufferQueueMap filtered_text;
|
| -
|
| - if (audio_track) {
|
| - AdjustBufferTimestamps(audio_buffers, offset);
|
| - FilterWithAppendWindow(append_window_start, append_window_end,
|
| - audio_buffers, audio_track,
|
| - new_media_segment, &filtered_audio);
|
| - }
|
| -
|
| - if (video_track) {
|
| - AdjustBufferTimestamps(video_buffers, offset);
|
| - FilterWithAppendWindow(append_window_start, append_window_end,
|
| - video_buffers, video_track,
|
| - new_media_segment, &filtered_video);
|
| - }
|
| -
|
| - // The earliest timestamp in the filtered buffers will be used for the segment
|
| - // start timestamp.
|
| - base::TimeDelta segment_timestamp = kInfiniteDuration();
|
| -
|
| - // Process any buffers for each of the text tracks in the map.
|
| - for (StreamParser::TextBufferQueueMap::const_iterator itr = text_map.begin();
|
| - itr != text_map.end();
|
| - ++itr) {
|
| - const StreamParser::BufferQueue& text_buffers = itr->second;
|
| - if (text_buffers.empty())
|
| - continue;
|
| -
|
| - if (!FilterTextBuffers(itr->first,
|
| - append_window_start,
|
| - append_window_end,
|
| - offset,
|
| - text_buffers,
|
| - new_media_segment,
|
| - &segment_timestamp,
|
| - &filtered_text)) {
|
| - return false;
|
| - }
|
| - }
|
| -
|
| - if ((!filtered_audio.empty() || !filtered_video.empty() ||
|
| - !filtered_text.empty()) &&
|
| - *new_media_segment) {
|
| - if (!filtered_audio.empty()) {
|
| - segment_timestamp = std::min(filtered_audio.front()->GetDecodeTimestamp(),
|
| - segment_timestamp);
|
| - }
|
| -
|
| - if (!filtered_video.empty()) {
|
| - segment_timestamp = std::min(filtered_video.front()->GetDecodeTimestamp(),
|
| - segment_timestamp);
|
| - }
|
| -
|
| - *new_media_segment = false;
|
| - DCHECK(segment_timestamp != kInfiniteDuration());
|
| - NotifyNewMediaSegmentStarting(segment_timestamp);
|
| - }
|
| -
|
| - if (!filtered_audio.empty() &&
|
| - !AppendAndUpdateDuration(audio_track->stream(), filtered_audio)) {
|
| - return false;
|
| - }
|
| -
|
| - if (!filtered_video.empty() &&
|
| - !AppendAndUpdateDuration(video_track->stream(), filtered_video)) {
|
| - return false;
|
| - }
|
| -
|
| - if (!filtered_text.empty()) {
|
| - for (StreamParser::TextBufferQueueMap::const_iterator itr =
|
| - filtered_text.begin();
|
| - itr != filtered_text.end();
|
| - ++itr) {
|
| - MseTrackBuffer* track = FindTrack(itr->first);
|
| - if (!track || !AppendAndUpdateDuration(track->stream(), itr->second))
|
| - return false;
|
| - }
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -void LegacyFrameProcessor::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)->set_timestamp((*itr)->timestamp() + timestamp_offset);
|
| - }
|
| -}
|
| -
|
| -void LegacyFrameProcessor::FilterWithAppendWindow(
|
| - base::TimeDelta append_window_start,
|
| - base::TimeDelta append_window_end,
|
| - const StreamParser::BufferQueue& buffers,
|
| - MseTrackBuffer* track,
|
| - bool* new_media_segment,
|
| - StreamParser::BufferQueue* filtered_buffers) {
|
| - DCHECK(track);
|
| - DCHECK(new_media_segment);
|
| - DCHECK(filtered_buffers);
|
| -
|
| - // This loop implements steps 1.9, 1.10, & 1.11 of the "Coded frame
|
| - // processing loop" in the Media Source Extensions spec.
|
| - // These steps filter out buffers that are not within the "append
|
| - // window" and handles resyncing on the next random access point
|
| - // (i.e., next keyframe) if a buffer gets dropped.
|
| - for (StreamParser::BufferQueue::const_iterator itr = buffers.begin();
|
| - itr != buffers.end(); ++itr) {
|
| - const scoped_refptr<StreamParserBuffer>& buffer = *itr;
|
| -
|
| - // Filter out buffers that are outside the append window. Anytime
|
| - // a buffer gets dropped we need to set |*needs_keyframe| to true
|
| - // because we can only resume decoding at keyframes.
|
| - base::TimeDelta presentation_timestamp = buffer->timestamp();
|
| -
|
| - // TODO(acolwell): Change |frame_end_timestamp| value to always be
|
| - // |presentation_timestamp + (*itr)->duration()|, like the spec
|
| - // requires, once frame durations are actually present in all buffers.
|
| - // See http://crbug.com/351166.
|
| - base::TimeDelta frame_end_timestamp = presentation_timestamp;
|
| - base::TimeDelta frame_duration = buffer->duration();
|
| - if (frame_duration > base::TimeDelta()) {
|
| - DCHECK(frame_duration != kNoTimestamp());
|
| - frame_end_timestamp += frame_duration;
|
| -
|
| - if (track->stream()->supports_partial_append_window_trimming() &&
|
| - HandlePartialAppendWindowTrimming(append_window_start,
|
| - append_window_end,
|
| - buffer)) {
|
| - // If |buffer| was shortened a discontinuity may exist, so treat the
|
| - // next frames appended as if they were the beginning of a new media
|
| - // segment.
|
| - if (buffer->timestamp() != presentation_timestamp)
|
| - *new_media_segment = true;
|
| -
|
| - // |buffer| has been partially trimmed or had preroll added.
|
| - presentation_timestamp = buffer->timestamp();
|
| - frame_duration = buffer->duration();
|
| -
|
| - // The end timestamp of the frame should be unchanged.
|
| - DCHECK(frame_end_timestamp == presentation_timestamp + frame_duration);
|
| - }
|
| - }
|
| -
|
| - if (presentation_timestamp < append_window_start ||
|
| - frame_end_timestamp > append_window_end) {
|
| - track->set_needs_random_access_point(true);
|
| - DVLOG(1) << "Dropping buffer outside append window."
|
| - << " presentation_timestamp "
|
| - << presentation_timestamp.InSecondsF();
|
| - // This triggers a discontinuity so we need to treat the next frames
|
| - // appended within the append window as if they were the beginning of a
|
| - // new segment.
|
| - *new_media_segment = true;
|
| - continue;
|
| - }
|
| -
|
| - // If the track needs a keyframe, then filter out buffers until we
|
| - // encounter the next keyframe.
|
| - if (track->needs_random_access_point()) {
|
| - if (!buffer->IsKeyframe()) {
|
| - DVLOG(1) << "Dropping non-keyframe. presentation_timestamp "
|
| - << presentation_timestamp.InSecondsF();
|
| - continue;
|
| - }
|
| -
|
| - track->set_needs_random_access_point(false);
|
| - }
|
| -
|
| - filtered_buffers->push_back(buffer);
|
| - }
|
| -}
|
| -
|
| -bool LegacyFrameProcessor::AppendAndUpdateDuration(
|
| - ChunkDemuxerStream* stream,
|
| - const StreamParser::BufferQueue& buffers) {
|
| - DCHECK(!buffers.empty());
|
| -
|
| - if (!stream || !stream->Append(buffers))
|
| - return false;
|
| -
|
| - // Approximate spec's "highest presentation end timestamp".
|
| - base::TimeDelta highest_end_timestamp = stream->GetBufferedDuration();
|
| - DCHECK(highest_end_timestamp > base::TimeDelta());
|
| -
|
| - increase_duration_cb_.Run(highest_end_timestamp);
|
| - return true;
|
| -}
|
| -
|
| -bool LegacyFrameProcessor::FilterTextBuffers(
|
| - StreamParser::TrackId text_track_id,
|
| - base::TimeDelta append_window_start,
|
| - base::TimeDelta append_window_end,
|
| - base::TimeDelta timestamp_offset,
|
| - const StreamParser::BufferQueue& buffers,
|
| - bool* new_media_segment,
|
| - base::TimeDelta* lowest_segment_timestamp,
|
| - StreamParser::TextBufferQueueMap* filtered_text) {
|
| - DCHECK(!buffers.empty());
|
| - DCHECK(text_track_id != kAudioTrackId && text_track_id != kVideoTrackId);
|
| - DCHECK(new_media_segment);
|
| -
|
| - MseTrackBuffer* track = FindTrack(text_track_id);
|
| - if (!track)
|
| - return false;
|
| -
|
| - AdjustBufferTimestamps(buffers, timestamp_offset);
|
| -
|
| - StreamParser::BufferQueue filtered_buffers;
|
| - FilterWithAppendWindow(append_window_start,
|
| - append_window_end,
|
| - buffers,
|
| - track,
|
| - new_media_segment,
|
| - &filtered_buffers);
|
| -
|
| - if (!filtered_buffers.empty()) {
|
| - *lowest_segment_timestamp =
|
| - std::min(*lowest_segment_timestamp,
|
| - filtered_buffers.front()->GetDecodeTimestamp());
|
| - DCHECK(filtered_text->find(text_track_id) == filtered_text->end());
|
| - filtered_text->insert(std::make_pair(text_track_id, filtered_buffers));
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -} // namespace media
|
|
|