Upstreaming browser/ui/uikit_ui_util from iOS.
[chromium-blink-merge.git] / chromecast / media / cma / backend / media_component_device_default.cc
blob3ed5f01f3956e2e5390804c48e7812f944a1e1e9
1 // Copyright 2015 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.
5 #include "chromecast/media/cma/backend/media_component_device_default.h"
7 #include "base/bind.h"
8 #include "base/callback_helpers.h"
9 #include "base/location.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "chromecast/media/cma/base/decoder_buffer_base.h"
12 #include "media/base/buffers.h"
14 namespace chromecast {
15 namespace media {
17 namespace {
19 // Maximum number of frames that can be buffered.
20 const size_t kMaxFrameCount = 20;
22 } // namespace
24 MediaComponentDeviceDefault::DefaultDecoderBuffer::DefaultDecoderBuffer()
25 : size(0) {
28 MediaComponentDeviceDefault::DefaultDecoderBuffer::~DefaultDecoderBuffer() {
31 MediaComponentDeviceDefault::MediaComponentDeviceDefault(
32 MediaClockDevice* media_clock_device)
33 : media_clock_device_(media_clock_device),
34 state_(kStateUninitialized),
35 rendering_time_(::media::kNoTimestamp()),
36 decoded_frame_count_(0),
37 decoded_byte_count_(0),
38 scheduled_rendering_task_(false),
39 weak_factory_(this) {
40 weak_this_ = weak_factory_.GetWeakPtr();
41 DetachFromThread();
44 MediaComponentDeviceDefault::~MediaComponentDeviceDefault() {
47 void MediaComponentDeviceDefault::SetClient(const Client& client) {
48 DCHECK(CalledOnValidThread());
49 client_ = client;
52 MediaComponentDevice::State MediaComponentDeviceDefault::GetState() const {
53 DCHECK(CalledOnValidThread());
54 return state_;
57 bool MediaComponentDeviceDefault::SetState(State new_state) {
58 DCHECK(CalledOnValidThread());
59 if (!MediaComponentDevice::IsValidStateTransition(state_, new_state))
60 return false;
61 state_ = new_state;
63 if (state_ == kStateIdle) {
64 // Back to the idle state: reset a bunch of parameters.
65 is_eos_ = false;
66 rendering_time_ = ::media::kNoTimestamp();
67 decoded_frame_count_ = 0;
68 decoded_byte_count_ = 0;
69 frames_.clear();
70 pending_buffer_ = scoped_refptr<DecoderBufferBase>();
71 frame_pushed_cb_.Reset();
72 return true;
75 if (state_ == kStateRunning) {
76 if (!scheduled_rendering_task_) {
77 scheduled_rendering_task_ = true;
78 base::ThreadTaskRunnerHandle::Get()->PostTask(
79 FROM_HERE,
80 base::Bind(&MediaComponentDeviceDefault::RenderTask, weak_this_));
82 return true;
85 return true;
88 bool MediaComponentDeviceDefault::SetStartPts(base::TimeDelta time) {
89 DCHECK(CalledOnValidThread());
90 DCHECK_EQ(state_, kStateIdle);
91 rendering_time_ = time;
92 return true;
95 MediaComponentDevice::FrameStatus MediaComponentDeviceDefault::PushFrame(
96 const scoped_refptr<DecryptContext>& decrypt_context,
97 const scoped_refptr<DecoderBufferBase>& buffer,
98 const FrameStatusCB& completion_cb) {
99 DCHECK(CalledOnValidThread());
100 DCHECK(state_ == kStatePaused || state_ == kStateRunning);
101 DCHECK(!is_eos_);
102 DCHECK(!pending_buffer_.get());
103 DCHECK(buffer.get());
105 if (buffer->end_of_stream()) {
106 is_eos_ = true;
107 return kFrameSuccess;
110 if (frames_.size() > kMaxFrameCount) {
111 pending_buffer_ = buffer;
112 frame_pushed_cb_ = completion_cb;
113 return kFramePending;
116 DefaultDecoderBuffer fake_buffer;
117 fake_buffer.size = buffer->data_size();
118 fake_buffer.pts = buffer->timestamp();
119 frames_.push_back(fake_buffer);
120 return kFrameSuccess;
123 base::TimeDelta MediaComponentDeviceDefault::GetRenderingTime() const {
124 return rendering_time_;
127 base::TimeDelta MediaComponentDeviceDefault::GetRenderingDelay() const {
128 NOTIMPLEMENTED();
129 return ::media::kNoTimestamp();
132 void MediaComponentDeviceDefault::RenderTask() {
133 scheduled_rendering_task_ = false;
135 if (state_ != kStateRunning)
136 return;
138 base::TimeDelta media_time = media_clock_device_->GetTime();
139 if (media_time == ::media::kNoTimestamp()) {
140 scheduled_rendering_task_ = true;
141 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
142 FROM_HERE,
143 base::Bind(&MediaComponentDeviceDefault::RenderTask, weak_this_),
144 base::TimeDelta::FromMilliseconds(50));
145 return;
148 while (!frames_.empty() && frames_.front().pts <= media_time) {
149 rendering_time_ = frames_.front().pts;
150 decoded_frame_count_++;
151 decoded_byte_count_ += frames_.front().size;
152 frames_.pop_front();
153 if (pending_buffer_.get()) {
154 DefaultDecoderBuffer fake_buffer;
155 fake_buffer.size = pending_buffer_->data_size();
156 fake_buffer.pts = pending_buffer_->timestamp();
157 frames_.push_back(fake_buffer);
158 pending_buffer_ = scoped_refptr<DecoderBufferBase>();
159 base::ResetAndReturn(&frame_pushed_cb_).Run(kFrameSuccess);
163 if (frames_.empty() && is_eos_) {
164 if (!client_.eos_cb.is_null())
165 client_.eos_cb.Run();
166 return;
169 scheduled_rendering_task_ = true;
170 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
171 FROM_HERE,
172 base::Bind(&MediaComponentDeviceDefault::RenderTask, weak_this_),
173 base::TimeDelta::FromMilliseconds(50));
176 bool MediaComponentDeviceDefault::GetStatistics(Statistics* stats) const {
177 if (state_ != kStateRunning)
178 return false;
180 // Note: what is returned here is not the number of samples but the number of
181 // frames. The value is different for audio.
182 stats->decoded_bytes = decoded_byte_count_;
183 stats->decoded_samples = decoded_frame_count_;
184 stats->dropped_samples = 0;
185 return true;
188 } // namespace media
189 } // namespace chromecast