| Index: chromecast/media/cma/backend/media_sink_default.cc
|
| diff --git a/chromecast/media/cma/backend/media_sink_default.cc b/chromecast/media/cma/backend/media_sink_default.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..61d58c62d7c602bc896c46013172c73af5277e4b
|
| --- /dev/null
|
| +++ b/chromecast/media/cma/backend/media_sink_default.cc
|
| @@ -0,0 +1,89 @@
|
| +// Copyright 2016 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 "chromecast/media/cma/backend/media_sink_default.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/location.h"
|
| +#include "base/threading/thread_task_runner_handle.h"
|
| +#include "chromecast/public/media/cast_decoder_buffer.h"
|
| +#include "media/base/timestamp_constants.h"
|
| +
|
| +namespace chromecast {
|
| +namespace media {
|
| +
|
| +MediaSinkDefault::MediaSinkDefault(
|
| + MediaPipelineBackend::Decoder::Delegate* delegate,
|
| + base::TimeDelta start_pts)
|
| + : delegate_(delegate),
|
| + time_interpolator_(&tick_clock_),
|
| + playback_rate_(1.0f),
|
| + last_frame_pts_(start_pts),
|
| + received_eos_(false) {
|
| + DCHECK(delegate_);
|
| + time_interpolator_.SetPlaybackRate(playback_rate_);
|
| + time_interpolator_.SetBounds(start_pts, start_pts, tick_clock_.NowTicks());
|
| + time_interpolator_.StartInterpolating();
|
| +}
|
| +
|
| +MediaSinkDefault::~MediaSinkDefault() {}
|
| +
|
| +void MediaSinkDefault::SetPlaybackRate(float rate) {
|
| + DCHECK_GE(rate, 0.0f);
|
| + playback_rate_ = rate;
|
| + time_interpolator_.SetPlaybackRate(playback_rate_);
|
| +
|
| + // Changing the playback rate affects the delay after which EOS callback
|
| + // should run. Reschedule the task according to the new delay.
|
| + if (received_eos_) {
|
| + eos_task_.Cancel();
|
| + ScheduleEndOfStreamTask();
|
| + }
|
| +}
|
| +
|
| +base::TimeDelta MediaSinkDefault::GetCurrentPts() {
|
| + return time_interpolator_.GetInterpolatedTime();
|
| +}
|
| +
|
| +MediaPipelineBackend::BufferStatus MediaSinkDefault::PushBuffer(
|
| + CastDecoderBuffer* buffer) {
|
| + if (buffer->end_of_stream()) {
|
| + received_eos_ = true;
|
| + ScheduleEndOfStreamTask();
|
| + return MediaPipelineBackend::kBufferSuccess;
|
| + }
|
| +
|
| + // This is wrong on several levels.
|
| + // 1. The correct PTS should be buffer->timestamp() + buffer->duration().
|
| + // But CastDecoderBuffer does not expose duration unlike
|
| + // ::media::DecoderBuffer.
|
| + // 2. The PTS reported by GetCurrentPts should not move backwards.
|
| + // It should be clamped in the range [start_pts, last_frame_pts_].
|
| + // But doing so makes several AudioVideoPipelineDeviceTest cases fail.
|
| + // Those tests are wrong should be fixed.
|
| + // TODO(alokp): Fix these issues when the next version of CMA backend is
|
| + // scheduled to roll out. crbug.com/678394
|
| + last_frame_pts_ = base::TimeDelta::FromMicroseconds(buffer->timestamp());
|
| + time_interpolator_.SetUpperBound(last_frame_pts_);
|
| + return MediaPipelineBackend::kBufferSuccess;
|
| +}
|
| +
|
| +void MediaSinkDefault::ScheduleEndOfStreamTask() {
|
| + DCHECK(received_eos_);
|
| + DCHECK(eos_task_.IsCancelled());
|
| +
|
| + // Do not schedule if playback is paused.
|
| + if (playback_rate_ == 0.0f)
|
| + return;
|
| +
|
| + eos_task_.Reset(
|
| + base::Bind(&MediaPipelineBackend::Decoder::Delegate::OnEndOfStream,
|
| + base::Unretained(delegate_)));
|
| + base::TimeDelta delay = (last_frame_pts_ - GetCurrentPts()) / playback_rate_;
|
| + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
|
| + FROM_HERE, eos_task_.callback(), delay);
|
| +}
|
| +
|
| +} // namespace media
|
| +} // namespace chromecast
|
|
|