Upstream version 9.37.197.0
[platform/framework/web/crosswalk.git] / src / media / filters / frame_processor_base.cc
index 09b1b86..c0593fe 100644 (file)
@@ -4,6 +4,8 @@
 
 #include "media/filters/frame_processor_base.h"
 
+#include <cstdlib>
+
 #include "base/stl_util.h"
 #include "media/base/buffers.h"
 
@@ -55,6 +57,9 @@ void FrameProcessorBase::SetGroupStartTimestampIfInSequenceMode(
   DCHECK(kNoTimestamp() != timestamp_offset);
   if (sequence_mode_)
     group_start_timestamp_ = timestamp_offset;
+
+  // Changes to timestampOffset should invalidate the preroll buffer.
+  audio_preroll_buffer_ = NULL;
 }
 
 bool FrameProcessorBase::AddTrack(StreamParser::TrackId id,
@@ -70,6 +75,26 @@ bool FrameProcessorBase::AddTrack(StreamParser::TrackId id,
   return true;
 }
 
+bool FrameProcessorBase::UpdateTrack(StreamParser::TrackId old_id,
+                                     StreamParser::TrackId new_id) {
+  DVLOG(2) << __FUNCTION__ << "() : old_id=" << old_id << ", new_id=" << new_id;
+
+  if (old_id == new_id || !FindTrack(old_id) || FindTrack(new_id))
+    return false;
+
+  track_buffers_[new_id] = track_buffers_[old_id];
+  CHECK_EQ(1u, track_buffers_.erase(old_id));
+  return true;
+}
+
+void FrameProcessorBase::SetAllTrackBuffersNeedRandomAccessPoint() {
+  for (TrackBufferMap::iterator itr = track_buffers_.begin();
+       itr != track_buffers_.end();
+       ++itr) {
+    itr->second->set_needs_random_access_point(true);
+  }
+}
+
 void FrameProcessorBase::Reset() {
   DVLOG(2) << __FUNCTION__ << "()";
   for (TrackBufferMap::iterator itr = track_buffers_.begin();
@@ -97,4 +122,93 @@ void FrameProcessorBase::NotifyNewMediaSegmentStarting(
   }
 }
 
+bool FrameProcessorBase::HandlePartialAppendWindowTrimming(
+    base::TimeDelta append_window_start,
+    base::TimeDelta append_window_end,
+    const scoped_refptr<StreamParserBuffer>& buffer) {
+  DCHECK(buffer->duration() > base::TimeDelta());
+  DCHECK_EQ(DemuxerStream::AUDIO, buffer->type());
+
+  const base::TimeDelta frame_end_timestamp =
+      buffer->timestamp() + buffer->duration();
+
+  // Ignore any buffers which start after |append_window_start| or end after
+  // |append_window_end|.  For simplicity, even those that start before
+  // |append_window_start|.
+  if (buffer->timestamp() > append_window_start ||
+      frame_end_timestamp > append_window_end) {
+    // TODO(dalecurtis): Partial append window trimming could also be done
+    // around |append_window_end|, but is not necessary since splice frames
+    // cover overlaps there.
+    return false;
+  }
+
+  // If the buffer is entirely before |append_window_start|, save it as preroll
+  // for the first buffer which overlaps |append_window_start|.
+  if (buffer->timestamp() < append_window_start &&
+      frame_end_timestamp <= append_window_start) {
+    audio_preroll_buffer_ = buffer;
+    return false;
+  }
+
+  // There's nothing to be done if we have no preroll and the buffer starts on
+  // the append window start.
+  if (buffer->timestamp() == append_window_start && !audio_preroll_buffer_)
+    return false;
+
+  // See if a partial discard can be done around |append_window_start|.
+  DCHECK(buffer->timestamp() <= append_window_start);
+  DCHECK(buffer->IsKeyframe());
+  DVLOG(1) << "Truncating buffer which overlaps append window start."
+           << " presentation_timestamp " << buffer->timestamp().InSecondsF()
+           << " append_window_start " << append_window_start.InSecondsF();
+
+  // If this isn't the first buffer discarded by the append window, try to use
+  // the last buffer discarded for preroll.  This ensures that the partially
+  // trimmed buffer can be correctly decoded.
+  if (audio_preroll_buffer_) {
+    // We only want to use the preroll buffer if it directly precedes (less than
+    // one sample apart) the current buffer.
+    const int64 delta = std::abs((audio_preroll_buffer_->timestamp() +
+                                  audio_preroll_buffer_->duration() -
+                                  buffer->timestamp()).InMicroseconds());
+    if (delta < sample_duration_.InMicroseconds()) {
+      buffer->SetPrerollBuffer(audio_preroll_buffer_);
+    } else {
+      // TODO(dalecurtis): Add a MEDIA_LOG() for when this is dropped unused.
+    }
+    audio_preroll_buffer_ = NULL;
+  }
+
+  // Decrease the duration appropriately.  We only need to shorten the buffer if
+  // it overlaps |append_window_start|.
+  if (buffer->timestamp() < append_window_start) {
+    buffer->set_discard_padding(std::make_pair(
+        append_window_start - buffer->timestamp(), base::TimeDelta()));
+    buffer->set_duration(frame_end_timestamp - append_window_start);
+  }
+
+  // Adjust the timestamp of this buffer forward to |append_window_start|.  The
+  // timestamps are always set, even if |buffer|'s timestamp is already set to
+  // |append_window_start|, to ensure the preroll buffer is setup correctly.
+  buffer->set_timestamp(append_window_start);
+  buffer->SetDecodeTimestamp(append_window_start);
+  return true;
+}
+
+void FrameProcessorBase::OnPossibleAudioConfigUpdate(
+    const AudioDecoderConfig& config) {
+  DCHECK(config.IsValidConfig());
+
+  // Always clear the preroll buffer when a config update is received.
+  audio_preroll_buffer_ = NULL;
+
+  if (config.Matches(current_audio_config_))
+    return;
+
+  current_audio_config_ = config;
+  sample_duration_ = base::TimeDelta::FromSecondsD(
+      1.0 / current_audio_config_.samples_per_second());
+}
+
 }  // namespace media