ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / chromecast / media / cma / pipeline / av_pipeline_impl.cc
blob2e2da54facea855610ce4925b4979c3927d82fbb
1 // Copyright 2014 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/pipeline/av_pipeline_impl.h"
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "base/message_loop/message_loop_proxy.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "chromecast/media/base/decrypt_context.h"
12 #include "chromecast/media/cdm/browser_cdm_cast.h"
13 #include "chromecast/media/cma/backend/media_clock_device.h"
14 #include "chromecast/media/cma/backend/media_component_device.h"
15 #include "chromecast/media/cma/base/buffering_frame_provider.h"
16 #include "chromecast/media/cma/base/buffering_state.h"
17 #include "chromecast/media/cma/base/cma_logging.h"
18 #include "chromecast/media/cma/base/coded_frame_provider.h"
19 #include "chromecast/media/cma/base/decoder_buffer_base.h"
20 #include "chromecast/media/cma/pipeline/decrypt_util.h"
21 #include "media/base/audio_decoder_config.h"
22 #include "media/base/bind_to_current_loop.h"
23 #include "media/base/decrypt_config.h"
25 namespace chromecast {
26 namespace media {
28 namespace {
30 const int kNoCallbackId = -1;
32 } // namespace
34 AvPipelineImpl::AvPipelineImpl(
35 MediaComponentDevice* media_component_device,
36 const UpdateConfigCB& update_config_cb)
37 : update_config_cb_(update_config_cb),
38 media_component_device_(media_component_device),
39 state_(kUninitialized),
40 buffered_time_(::media::kNoTimestamp()),
41 playable_buffered_time_(::media::kNoTimestamp()),
42 enable_feeding_(false),
43 pending_read_(false),
44 pending_push_(false),
45 enable_time_update_(false),
46 pending_time_update_task_(false),
47 media_keys_(NULL),
48 media_keys_callback_id_(kNoCallbackId),
49 weak_factory_(this) {
50 DCHECK(media_component_device);
51 weak_this_ = weak_factory_.GetWeakPtr();
52 thread_checker_.DetachFromThread();
55 AvPipelineImpl::~AvPipelineImpl() {
56 // If there are weak pointers in the wild, they must be invalidated
57 // on the right thread.
58 DCHECK(thread_checker_.CalledOnValidThread());
59 media_component_device_->SetClient(MediaComponentDevice::Client());
61 if (media_keys_ && media_keys_callback_id_ != kNoCallbackId)
62 media_keys_->UnregisterPlayer(media_keys_callback_id_);
65 void AvPipelineImpl::TransitionToState(State state) {
66 DCHECK(thread_checker_.CalledOnValidThread());
67 state_ = state;
70 void AvPipelineImpl::SetCodedFrameProvider(
71 scoped_ptr<CodedFrameProvider> frame_provider,
72 size_t max_buffer_size,
73 size_t max_frame_size) {
74 DCHECK_EQ(state_, kUninitialized);
75 DCHECK(frame_provider);
77 // Wrap the incoming frame provider to add some buffering capabilities.
78 frame_provider_.reset(
79 new BufferingFrameProvider(
80 frame_provider.Pass(),
81 max_buffer_size,
82 max_frame_size,
83 base::Bind(&AvPipelineImpl::OnFrameBuffered, weak_this_)));
86 void AvPipelineImpl::SetClient(const AvPipelineClient& client) {
87 DCHECK(thread_checker_.CalledOnValidThread());
88 DCHECK_EQ(state_, kUninitialized);
89 client_ = client;
92 bool AvPipelineImpl::Initialize() {
93 DCHECK(thread_checker_.CalledOnValidThread());
94 DCHECK_EQ(state_, kUninitialized);
96 MediaComponentDevice::Client client;
97 client.eos_cb = base::Bind(&AvPipelineImpl::OnEos, weak_this_);
98 media_component_device_->SetClient(client);
99 if (!media_component_device_->SetState(MediaComponentDevice::kStateIdle))
100 return false;
102 return true;
105 bool AvPipelineImpl::StartPlayingFrom(
106 base::TimeDelta time,
107 const scoped_refptr<BufferingState>& buffering_state) {
108 DCHECK(thread_checker_.CalledOnValidThread());
109 DCHECK_EQ(state_, kFlushed);
111 // Media time where rendering should start
112 // and switch to a state where the audio device accepts incoming buffers.
113 if (!media_component_device_->SetStartPts(time) ||
114 !media_component_device_->SetState(MediaComponentDevice::kStatePaused)) {
115 return false;
118 // Buffering related initialization.
119 DCHECK(frame_provider_);
120 buffering_state_ = buffering_state;
121 if (buffering_state_.get())
122 buffering_state_->SetMediaTime(time);
124 if (!media_component_device_->SetState(MediaComponentDevice::kStateRunning))
125 return false;
127 // Start feeding the pipeline.
128 enable_feeding_ = true;
129 base::MessageLoopProxy::current()->PostTask(
130 FROM_HERE,
131 base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, weak_this_));
133 return true;
136 void AvPipelineImpl::Flush(const base::Closure& done_cb) {
137 DCHECK(thread_checker_.CalledOnValidThread());
138 DCHECK_EQ(state_, kFlushing);
139 DCHECK_EQ(
140 media_component_device_->GetState(), MediaComponentDevice::kStateRunning);
141 // Note: returning to idle state aborts any pending frame push.
142 media_component_device_->SetState(MediaComponentDevice::kStateIdle);
143 pending_push_ = false;
145 // Break the feeding loop.
146 enable_feeding_ = false;
148 // Remove any pending buffer.
149 pending_buffer_ = scoped_refptr<DecoderBufferBase>();
151 // Finally, remove any frames left in the frame provider.
152 pending_read_ = false;
153 buffered_time_ = ::media::kNoTimestamp();
154 playable_buffered_time_ = ::media::kNoTimestamp();
155 non_playable_frames_.clear();
156 frame_provider_->Flush(done_cb);
159 void AvPipelineImpl::Stop() {
160 DCHECK(thread_checker_.CalledOnValidThread());
162 // Stop can be called from any state.
163 if (state_ == kUninitialized || state_ == kStopped)
164 return;
166 // Stop feeding the pipeline.
167 enable_feeding_ = false;
169 // Release hardware resources on Stop.
170 if (media_component_device_->GetState() ==
171 MediaComponentDevice::kStatePaused ||
172 media_component_device_->GetState() ==
173 MediaComponentDevice::kStateRunning) {
174 media_component_device_->SetState(MediaComponentDevice::kStateIdle);
176 if (media_component_device_->GetState() == MediaComponentDevice::kStateIdle) {
177 media_component_device_->SetState(
178 MediaComponentDevice::kStateUninitialized);
182 void AvPipelineImpl::SetCdm(BrowserCdmCast* media_keys) {
183 DCHECK(thread_checker_.CalledOnValidThread());
184 DCHECK(media_keys);
186 if (media_keys_ && media_keys_callback_id_ != kNoCallbackId)
187 media_keys_->UnregisterPlayer(media_keys_callback_id_);
189 media_keys_ = media_keys;
190 media_keys_callback_id_ = media_keys_->RegisterPlayer(
191 ::media::BindToCurrentLoop(
192 base::Bind(&AvPipelineImpl::OnCdmStateChanged, weak_this_)),
193 ::media::BindToCurrentLoop(
194 base::Bind(&AvPipelineImpl::OnCdmDestroyed, weak_this_)));
197 void AvPipelineImpl::OnEos() {
198 DCHECK(thread_checker_.CalledOnValidThread());
199 CMALOG(kLogControl) << __FUNCTION__;
200 if (state_ != kPlaying)
201 return;
203 if (!client_.eos_cb.is_null())
204 client_.eos_cb.Run();
207 void AvPipelineImpl::FetchBufferIfNeeded() {
208 DCHECK(thread_checker_.CalledOnValidThread());
209 if (!enable_feeding_)
210 return;
212 if (pending_read_ || pending_buffer_.get())
213 return;
215 pending_read_ = true;
216 frame_provider_->Read(
217 base::Bind(&AvPipelineImpl::OnNewFrame, weak_this_));
220 void AvPipelineImpl::OnNewFrame(
221 const scoped_refptr<DecoderBufferBase>& buffer,
222 const ::media::AudioDecoderConfig& audio_config,
223 const ::media::VideoDecoderConfig& video_config) {
224 DCHECK(thread_checker_.CalledOnValidThread());
225 pending_read_ = false;
227 if (audio_config.IsValidConfig() || video_config.IsValidConfig())
228 update_config_cb_.Run(audio_config, video_config);
230 pending_buffer_ = buffer;
231 ProcessPendingBuffer();
233 base::MessageLoopProxy::current()->PostTask(
234 FROM_HERE,
235 base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, weak_this_));
238 void AvPipelineImpl::ProcessPendingBuffer() {
239 if (!enable_feeding_)
240 return;
242 // Initiate a read if there isn't already one.
243 if (!pending_buffer_.get() && !pending_read_) {
244 base::MessageLoopProxy::current()->PostTask(
245 FROM_HERE,
246 base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, weak_this_));
247 return;
250 if (!pending_buffer_.get() || pending_push_)
251 return;
253 // Break the feeding loop when the end of stream is reached.
254 if (pending_buffer_->end_of_stream()) {
255 CMALOG(kLogControl) << __FUNCTION__ << ": EOS reached, stopped feeding";
256 enable_feeding_ = false;
259 scoped_refptr<DecryptContext> decrypt_context;
260 if (!pending_buffer_->end_of_stream() &&
261 pending_buffer_->decrypt_config()) {
262 // Verify that CDM has the key ID.
263 // Should not send the frame if the key ID is not available yet.
264 std::string key_id(pending_buffer_->decrypt_config()->key_id());
265 if (!media_keys_) {
266 CMALOG(kLogControl) << "No CDM for frame: pts="
267 << pending_buffer_->timestamp().InMilliseconds();
268 return;
270 decrypt_context = media_keys_->GetDecryptContext(key_id);
271 if (!decrypt_context.get()) {
272 CMALOG(kLogControl) << "frame(pts="
273 << pending_buffer_->timestamp().InMilliseconds()
274 << "): waiting for key id "
275 << base::HexEncode(&key_id[0], key_id.size());
276 return;
279 // If we do have the clear key, decrypt the pending buffer
280 // and reset the decryption context (not needed anymore).
281 crypto::SymmetricKey* key = decrypt_context->GetKey();
282 if (key != NULL) {
283 pending_buffer_ = DecryptDecoderBuffer(pending_buffer_, key);
284 decrypt_context = scoped_refptr<DecryptContext>();
288 if (!pending_buffer_->end_of_stream() && buffering_state_.get()) {
289 base::TimeDelta timestamp = pending_buffer_->timestamp();
290 if (timestamp != ::media::kNoTimestamp())
291 buffering_state_->SetMaxRenderingTime(timestamp);
294 MediaComponentDevice::FrameStatus status = media_component_device_->PushFrame(
295 decrypt_context,
296 pending_buffer_,
297 base::Bind(&AvPipelineImpl::OnFramePushed, weak_this_));
298 pending_buffer_ = scoped_refptr<DecoderBufferBase>();
300 pending_push_ = (status == MediaComponentDevice::kFramePending);
301 if (!pending_push_)
302 OnFramePushed(status);
305 void AvPipelineImpl::OnFramePushed(MediaComponentDevice::FrameStatus status) {
306 DCHECK(thread_checker_.CalledOnValidThread());
307 pending_push_ = false;
308 if (status == MediaComponentDevice::kFrameFailed) {
309 LOG(WARNING) << "AvPipelineImpl: PushFrame failed";
310 enable_feeding_ = false;
311 state_ = kError;
312 return;
314 base::MessageLoopProxy::current()->PostTask(
315 FROM_HERE,
316 base::Bind(&AvPipelineImpl::ProcessPendingBuffer, weak_this_));
319 void AvPipelineImpl::OnCdmStateChanged() {
320 DCHECK(thread_checker_.CalledOnValidThread());
322 // Update the buffering state if needed.
323 if (buffering_state_.get())
324 UpdatePlayableFrames();
326 // Process the pending buffer in case the CDM now has the frame key id.
327 ProcessPendingBuffer();
330 void AvPipelineImpl::OnCdmDestroyed() {
331 DCHECK(thread_checker_.CalledOnValidThread());
332 media_keys_ = NULL;
335 void AvPipelineImpl::OnFrameBuffered(
336 const scoped_refptr<DecoderBufferBase>& buffer,
337 bool is_at_max_capacity) {
338 DCHECK(thread_checker_.CalledOnValidThread());
340 if (!buffering_state_.get())
341 return;
343 if (!buffer->end_of_stream() &&
344 (buffered_time_ == ::media::kNoTimestamp() ||
345 buffered_time_ < buffer->timestamp())) {
346 buffered_time_ = buffer->timestamp();
349 if (is_at_max_capacity)
350 buffering_state_->NotifyMaxCapacity(buffered_time_);
352 // No need to update the list of playable frames,
353 // if we are already blocking on a frame.
354 bool update_playable_frames = non_playable_frames_.empty();
355 non_playable_frames_.push_back(buffer);
356 if (update_playable_frames)
357 UpdatePlayableFrames();
360 void AvPipelineImpl::UpdatePlayableFrames() {
361 while (!non_playable_frames_.empty()) {
362 const scoped_refptr<DecoderBufferBase>& non_playable_frame =
363 non_playable_frames_.front();
365 if (non_playable_frame->end_of_stream()) {
366 buffering_state_->NotifyEos();
367 } else {
368 const ::media::DecryptConfig* decrypt_config =
369 non_playable_frame->decrypt_config();
370 if (decrypt_config &&
371 !(media_keys_ &&
372 media_keys_->GetDecryptContext(decrypt_config->key_id()).get())) {
373 // The frame is still not playable. All the following are thus not
374 // playable.
375 break;
378 if (playable_buffered_time_ == ::media::kNoTimestamp() ||
379 playable_buffered_time_ < non_playable_frame->timestamp()) {
380 playable_buffered_time_ = non_playable_frame->timestamp();
381 buffering_state_->SetBufferedTime(playable_buffered_time_);
385 // The frame is playable: remove it from the list of non playable frames.
386 non_playable_frames_.pop_front();
390 } // namespace media
391 } // namespace chromecast