OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "chromecast/media/cma/backend/media_sink_default.h" |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/location.h" |
| 9 #include "base/threading/thread_task_runner_handle.h" |
| 10 #include "chromecast/public/media/cast_decoder_buffer.h" |
| 11 #include "media/base/timestamp_constants.h" |
| 12 |
| 13 namespace chromecast { |
| 14 namespace media { |
| 15 |
| 16 MediaSinkDefault::MediaSinkDefault( |
| 17 MediaPipelineBackend::Decoder::Delegate* delegate, |
| 18 base::TimeDelta start_pts) |
| 19 : delegate_(delegate), |
| 20 time_interpolator_(&tick_clock_), |
| 21 playback_rate_(1.0f), |
| 22 last_frame_pts_(start_pts), |
| 23 received_eos_(false) { |
| 24 DCHECK(delegate_); |
| 25 time_interpolator_.SetPlaybackRate(playback_rate_); |
| 26 time_interpolator_.SetBounds(start_pts, start_pts, tick_clock_.NowTicks()); |
| 27 time_interpolator_.StartInterpolating(); |
| 28 } |
| 29 |
| 30 MediaSinkDefault::~MediaSinkDefault() {} |
| 31 |
| 32 void MediaSinkDefault::SetPlaybackRate(float rate) { |
| 33 DCHECK_GE(rate, 0.0f); |
| 34 playback_rate_ = rate; |
| 35 time_interpolator_.SetPlaybackRate(playback_rate_); |
| 36 |
| 37 // Changing the playback rate affects the delay after which EOS callback |
| 38 // should run. Reschedule the task according to the new delay. |
| 39 if (received_eos_) { |
| 40 eos_task_.Cancel(); |
| 41 ScheduleEndOfStreamTask(); |
| 42 } |
| 43 } |
| 44 |
| 45 base::TimeDelta MediaSinkDefault::GetCurrentPts() { |
| 46 return time_interpolator_.GetInterpolatedTime(); |
| 47 } |
| 48 |
| 49 MediaPipelineBackend::BufferStatus MediaSinkDefault::PushBuffer( |
| 50 CastDecoderBuffer* buffer) { |
| 51 if (buffer->end_of_stream()) { |
| 52 received_eos_ = true; |
| 53 ScheduleEndOfStreamTask(); |
| 54 return MediaPipelineBackend::kBufferSuccess; |
| 55 } |
| 56 |
| 57 // This is wrong on several levels. |
| 58 // 1. The correct PTS should be buffer->timestamp() + buffer->duration(). |
| 59 // But CastDecoderBuffer does not expose duration unlike |
| 60 // ::media::DecoderBuffer. |
| 61 // 2. The PTS reported by GetCurrentPts should not move backwards. |
| 62 // It should be clamped in the range [start_pts, last_frame_pts_]. |
| 63 // But doing so makes several AudioVideoPipelineDeviceTest cases fail. |
| 64 // Those tests are wrong should be fixed. |
| 65 // TODO(alokp): Fix these issues when the next version of CMA backend is |
| 66 // scheduled to roll out. crbug.com/678394 |
| 67 last_frame_pts_ = base::TimeDelta::FromMicroseconds(buffer->timestamp()); |
| 68 time_interpolator_.SetUpperBound(last_frame_pts_); |
| 69 return MediaPipelineBackend::kBufferSuccess; |
| 70 } |
| 71 |
| 72 void MediaSinkDefault::ScheduleEndOfStreamTask() { |
| 73 DCHECK(received_eos_); |
| 74 DCHECK(eos_task_.IsCancelled()); |
| 75 |
| 76 // Do not schedule if playback is paused. |
| 77 if (playback_rate_ == 0.0f) |
| 78 return; |
| 79 |
| 80 eos_task_.Reset( |
| 81 base::Bind(&MediaPipelineBackend::Decoder::Delegate::OnEndOfStream, |
| 82 base::Unretained(delegate_))); |
| 83 base::TimeDelta delay = (last_frame_pts_ - GetCurrentPts()) / playback_rate_; |
| 84 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 85 FROM_HERE, eos_task_.callback(), delay); |
| 86 } |
| 87 |
| 88 } // namespace media |
| 89 } // namespace chromecast |
OLD | NEW |