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"
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
{
19 // Maximum number of frames that can be buffered.
20 const size_t kMaxFrameCount
= 20;
24 MediaComponentDeviceDefault::DefaultDecoderBuffer::DefaultDecoderBuffer()
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),
40 weak_this_
= weak_factory_
.GetWeakPtr();
44 MediaComponentDeviceDefault::~MediaComponentDeviceDefault() {
47 void MediaComponentDeviceDefault::SetClient(const Client
& client
) {
48 DCHECK(CalledOnValidThread());
52 MediaComponentDevice::State
MediaComponentDeviceDefault::GetState() const {
53 DCHECK(CalledOnValidThread());
57 bool MediaComponentDeviceDefault::SetState(State new_state
) {
58 DCHECK(CalledOnValidThread());
59 if (!MediaComponentDevice::IsValidStateTransition(state_
, new_state
))
63 if (state_
== kStateIdle
) {
64 // Back to the idle state: reset a bunch of parameters.
66 rendering_time_
= ::media::kNoTimestamp();
67 decoded_frame_count_
= 0;
68 decoded_byte_count_
= 0;
70 pending_buffer_
= scoped_refptr
<DecoderBufferBase
>();
71 frame_pushed_cb_
.Reset();
75 if (state_
== kStateRunning
) {
76 if (!scheduled_rendering_task_
) {
77 scheduled_rendering_task_
= true;
78 base::ThreadTaskRunnerHandle::Get()->PostTask(
80 base::Bind(&MediaComponentDeviceDefault::RenderTask
, weak_this_
));
88 bool MediaComponentDeviceDefault::SetStartPts(base::TimeDelta time
) {
89 DCHECK(CalledOnValidThread());
90 DCHECK_EQ(state_
, kStateIdle
);
91 rendering_time_
= time
;
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
);
102 DCHECK(!pending_buffer_
.get());
103 DCHECK(buffer
.get());
105 if (buffer
->end_of_stream()) {
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 {
129 return ::media::kNoTimestamp();
132 void MediaComponentDeviceDefault::RenderTask() {
133 scheduled_rendering_task_
= false;
135 if (state_
!= kStateRunning
)
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(
143 base::Bind(&MediaComponentDeviceDefault::RenderTask
, weak_this_
),
144 base::TimeDelta::FromMilliseconds(50));
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
;
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();
169 scheduled_rendering_task_
= true;
170 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
172 base::Bind(&MediaComponentDeviceDefault::RenderTask
, weak_this_
),
173 base::TimeDelta::FromMilliseconds(50));
176 bool MediaComponentDeviceDefault::GetStatistics(Statistics
* stats
) const {
177 if (state_
!= kStateRunning
)
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;
189 } // namespace chromecast