Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(306)

Side by Side Diff: chromecast/media/cma/backend/media_pipeline_device_fake.cc

Issue 622853002: Chromecast: adds interfaces for hardware layer of CMA pipeline. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@cma-decrypt-context
Patch Set: style feedback/fixes Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "chromecast/media/cma/backend/media_pipeline_device_fake.h"
6
7 #include <list>
8
9 #include "base/bind.h"
10 #include "base/callback_helpers.h"
11 #include "base/location.h"
12 #include "base/logging.h"
13 #include "base/macros.h"
14 #include "base/message_loop/message_loop_proxy.h"
15 #include "chromecast/media/cma/backend/audio_pipeline_device.h"
16 #include "chromecast/media/cma/backend/media_clock_device.h"
17 #include "chromecast/media/cma/backend/media_component_device.h"
18 #include "chromecast/media/cma/backend/video_pipeline_device.h"
19 #include "chromecast/media/cma/base/decoder_buffer_base.h"
20 #include "media/base/audio_decoder_config.h"
21 #include "media/base/buffers.h"
22 #include "media/base/video_decoder_config.h"
23
24 namespace chromecast {
25 namespace media {
26
27 class MediaClockDeviceFake : public MediaClockDevice {
28 public:
29 MediaClockDeviceFake();
30 virtual ~MediaClockDeviceFake();
31
32 // MediaClockDevice implementation.
33 virtual State GetState() const OVERRIDE;
34 virtual bool SetState(State new_state) OVERRIDE;
35 virtual bool ResetTimeline(base::TimeDelta time) OVERRIDE;
36 virtual bool SetRate(float rate) OVERRIDE;
37 virtual base::TimeDelta GetTime() OVERRIDE;
damienv1 2014/10/06 17:00:23 Replace OVERRIDE with override everywhere in this
38
39 private:
40 State state_;
41
42 // Media time sampled at STC time |stc_|.
43 base::TimeDelta media_time_;
44 base::TimeTicks stc_;
45
46 float rate_;
47
48 DISALLOW_COPY_AND_ASSIGN(MediaClockDeviceFake);
49 };
50
51 MediaClockDeviceFake::MediaClockDeviceFake()
52 : state_(kStateUninitialized),
53 media_time_(::media::kNoTimestamp()) {
54 DetachFromThread();
55 }
56
57 MediaClockDeviceFake::~MediaClockDeviceFake() {
58 }
59
60 MediaClockDevice::State MediaClockDeviceFake::GetState() const {
61 DCHECK(CalledOnValidThread());
62 return state_;
63 }
64
65 bool MediaClockDeviceFake::SetState(State new_state) {
66 DCHECK(CalledOnValidThread());
67 if (!MediaClockDevice::IsValidStateTransition(state_, new_state))
68 return false;
69
70 if (new_state == state_)
71 return true;
72
73 state_ = new_state;
74
75 if (state_ == kStateRunning) {
76 stc_ = base::TimeTicks::Now();
77 DCHECK(media_time_ != ::media::kNoTimestamp());
78 return true;
79 }
80
81 if (state_ == kStateIdle) {
82 media_time_ = ::media::kNoTimestamp();
83 return true;
84 }
85
86 return true;
87 }
88
89 bool MediaClockDeviceFake::ResetTimeline(base::TimeDelta time) {
90 DCHECK(CalledOnValidThread());
91 DCHECK_EQ(state_, kStateIdle);
92 media_time_ = time;
93 return true;
94 }
95
96 bool MediaClockDeviceFake::SetRate(float rate) {
97 DCHECK(CalledOnValidThread());
98 if (state_ == kStateRunning) {
99 base::TimeTicks now = base::TimeTicks::Now();
100 media_time_ = media_time_ + (now - stc_) * rate_;
101 stc_ = now;
102 }
103
104 rate_ = rate;
105 return true;
106 }
107
108 base::TimeDelta MediaClockDeviceFake::GetTime() {
109 DCHECK(CalledOnValidThread());
110 if (state_ != kStateRunning)
111 return media_time_;
112
113 if (media_time_ == ::media::kNoTimestamp())
114 return ::media::kNoTimestamp();
115
116 base::TimeTicks now = base::TimeTicks::Now();
117 base::TimeDelta interpolated_media_time =
118 media_time_ + (now - stc_) * rate_;
119 return interpolated_media_time;
120 }
121
122
123 namespace {
124
125 // Maximum number of frames that can be buffered.
126 const size_t kMaxFrameCount = 20;
127
128 } // namespace
129
130 class MediaComponentDeviceFake : public MediaComponentDevice {
131 public:
132 explicit MediaComponentDeviceFake(MediaClockDeviceFake* media_clock_device);
133 virtual ~MediaComponentDeviceFake();
134
135 // MediaComponentDevice implementation.
136 virtual void SetClient(const Client& client) OVERRIDE;
137 virtual State GetState() const OVERRIDE;
138 virtual bool SetState(State new_state) OVERRIDE;
139 virtual bool SetStartPts(base::TimeDelta time) OVERRIDE;
140 virtual FrameStatus PushFrame(
141 const scoped_refptr<DecryptContext>& decrypt_context,
142 const scoped_refptr<DecoderBufferBase>& buffer,
143 const FrameStatusCB& completion_cb) OVERRIDE;
144 virtual base::TimeDelta GetRenderingTime() const OVERRIDE;
145 virtual base::TimeDelta GetRenderingDelay() const OVERRIDE;
146 virtual bool GetStatistics(Statistics* stats) const OVERRIDE;
147
148 private:
149 struct FakeDecoderBuffer {
150 FakeDecoderBuffer();
151 ~FakeDecoderBuffer();
152
153 // Buffer size.
154 size_t size;
155
156 // Presentation timestamp.
157 base::TimeDelta pts;
158 };
159
160 void RenderTask();
161
162 MediaClockDeviceFake* const media_clock_device_;
163 Client client_;
164
165 State state_;
166
167 // Indicate whether the end of stream has been received.
168 bool is_eos_;
169
170 // Media time of the last rendered audio sample.
171 base::TimeDelta rendering_time_;
172
173 // Frame decoded/rendered since the pipeline left the idle state.
174 uint64 decoded_frame_count_;
175 uint64 decoded_byte_count_;
176
177 // List of frames not rendered yet.
178 std::list<FakeDecoderBuffer> frames_;
179
180 // Indicate whether there is a scheduled rendering task.
181 bool scheduled_rendering_task_;
182
183 // Pending frame.
184 scoped_refptr<DecoderBufferBase> pending_buffer_;
185 FrameStatusCB frame_pushed_cb_;
186
187 base::WeakPtr<MediaComponentDeviceFake> weak_this_;
188 base::WeakPtrFactory<MediaComponentDeviceFake> weak_factory_;
189
190 DISALLOW_COPY_AND_ASSIGN(MediaComponentDeviceFake);
191 };
192
193 MediaComponentDeviceFake::FakeDecoderBuffer::FakeDecoderBuffer()
194 : size(0) {
195 }
196
197 MediaComponentDeviceFake::FakeDecoderBuffer::~FakeDecoderBuffer() {
198 }
199
200 MediaComponentDeviceFake::MediaComponentDeviceFake(
201 MediaClockDeviceFake* media_clock_device)
202 : media_clock_device_(media_clock_device),
203 state_(kStateUninitialized),
204 rendering_time_(::media::kNoTimestamp()),
205 decoded_frame_count_(0),
206 decoded_byte_count_(0),
207 scheduled_rendering_task_(false),
208 weak_factory_(this) {
209 weak_this_ = weak_factory_.GetWeakPtr();
210 DetachFromThread();
211 }
212
213 MediaComponentDeviceFake::~MediaComponentDeviceFake() {
214 }
215
216 void MediaComponentDeviceFake::SetClient(const Client& client) {
217 DCHECK(CalledOnValidThread());
218 client_ = client;
219 }
220
221 MediaComponentDevice::State MediaComponentDeviceFake::GetState() const {
222 DCHECK(CalledOnValidThread());
223 return state_;
224 }
225
226 bool MediaComponentDeviceFake::SetState(State new_state) {
227 DCHECK(CalledOnValidThread());
228 if (!MediaComponentDevice::IsValidStateTransition(state_, new_state))
229 return false;
230 state_ = new_state;
231
232 if (state_ == kStateIdle) {
233 // Back to the idle state: reset a bunch of parameters.
234 is_eos_ = false;
235 rendering_time_ = ::media::kNoTimestamp();
236 decoded_frame_count_ = 0;
237 decoded_byte_count_ = 0;
238 frames_.clear();
239 pending_buffer_ = scoped_refptr<DecoderBufferBase>();
240 frame_pushed_cb_.Reset();
241 return true;
242 }
243
244 if (state_ == kStateRunning) {
245 if (!scheduled_rendering_task_) {
246 scheduled_rendering_task_ = true;
247 base::MessageLoopProxy::current()->PostTask(
248 FROM_HERE,
249 base::Bind(&MediaComponentDeviceFake::RenderTask, weak_this_));
250 }
251 return true;
252 }
253
254 return true;
255 }
256
257 bool MediaComponentDeviceFake::SetStartPts(base::TimeDelta time) {
258 DCHECK(CalledOnValidThread());
259 DCHECK_EQ(state_, kStateIdle);
260 rendering_time_ = time;
261 return true;
262 }
263
264 MediaComponentDevice::FrameStatus MediaComponentDeviceFake::PushFrame(
265 const scoped_refptr<DecryptContext>& decrypt_context,
266 const scoped_refptr<DecoderBufferBase>& buffer,
267 const FrameStatusCB& completion_cb) {
268 DCHECK(CalledOnValidThread());
269 DCHECK(state_ == kStatePaused || state_ == kStateRunning);
270 DCHECK(!is_eos_);
271 DCHECK(!pending_buffer_.get());
272 DCHECK(buffer.get());
273
274 if (buffer->end_of_stream()) {
275 is_eos_ = true;
276 return kFrameSuccess;
277 }
278
279 if (frames_.size() > kMaxFrameCount) {
280 pending_buffer_ = buffer;
281 frame_pushed_cb_ = completion_cb;
282 return kFramePending;
283 }
284
285 FakeDecoderBuffer fake_buffer;
286 fake_buffer.size = buffer->data_size();
287 fake_buffer.pts = buffer->timestamp();
288 frames_.push_back(fake_buffer);
289 return kFrameSuccess;
290 }
291
292 base::TimeDelta MediaComponentDeviceFake::GetRenderingTime() const {
293 return rendering_time_;
294 }
295
296 base::TimeDelta MediaComponentDeviceFake::GetRenderingDelay() const {
297 NOTIMPLEMENTED();
298 return ::media::kNoTimestamp();
299 }
300
301 void MediaComponentDeviceFake::RenderTask() {
302 scheduled_rendering_task_ = false;
303
304 if (state_ != kStateRunning)
305 return;
306
307 base::TimeDelta media_time = media_clock_device_->GetTime();
308 if (media_time == ::media::kNoTimestamp()) {
309 scheduled_rendering_task_ = true;
310 base::MessageLoopProxy::current()->PostDelayedTask(
311 FROM_HERE,
312 base::Bind(&MediaComponentDeviceFake::RenderTask, weak_this_),
313 base::TimeDelta::FromMilliseconds(50));
314 return;
315 }
316
317 while (!frames_.empty() && frames_.front().pts <= media_time) {
318 rendering_time_ = frames_.front().pts;
319 decoded_frame_count_++;
320 decoded_byte_count_ += frames_.front().size;
321 frames_.pop_front();
322 if (pending_buffer_.get()) {
323 FakeDecoderBuffer fake_buffer;
324 fake_buffer.size = pending_buffer_->data_size();
325 fake_buffer.pts = pending_buffer_->timestamp();
326 frames_.push_back(fake_buffer);
327 pending_buffer_ = scoped_refptr<DecoderBufferBase>();
328 base::ResetAndReturn(&frame_pushed_cb_).Run(kFrameSuccess);
329 }
330 }
331
332 if (frames_.empty() && is_eos_) {
333 if (!client_.eos_cb.is_null())
334 client_.eos_cb.Run();
335 return;
336 }
337
338 scheduled_rendering_task_ = true;
339 base::MessageLoopProxy::current()->PostDelayedTask(
340 FROM_HERE,
341 base::Bind(&MediaComponentDeviceFake::RenderTask, weak_this_),
342 base::TimeDelta::FromMilliseconds(50));
343 }
344
345 bool MediaComponentDeviceFake::GetStatistics(Statistics* stats) const {
346 if (state_ != kStateRunning)
347 return false;
348
349 // Note: what is returned here is not the number of samples but the number of
350 // frames. The value is different for audio.
351 stats->decoded_bytes = decoded_byte_count_;
352 stats->decoded_samples = decoded_frame_count_;
353 stats->dropped_samples = 0;
354 return true;
355 }
356
357
358 class AudioPipelineDeviceFake : public AudioPipelineDevice {
359 public:
360 explicit AudioPipelineDeviceFake(MediaClockDeviceFake* media_clock_device);
361 virtual ~AudioPipelineDeviceFake();
362
363 // AudioPipelineDevice implementation.
364 virtual void SetClient(const Client& client) OVERRIDE;
365 virtual State GetState() const OVERRIDE;
366 virtual bool SetState(State new_state) OVERRIDE;
367 virtual bool SetStartPts(base::TimeDelta time) OVERRIDE;
368 virtual FrameStatus PushFrame(
369 const scoped_refptr<DecryptContext>& decrypt_context,
370 const scoped_refptr<DecoderBufferBase>& buffer,
371 const FrameStatusCB& completion_cb) OVERRIDE;
372 virtual base::TimeDelta GetRenderingTime() const OVERRIDE;
373 virtual base::TimeDelta GetRenderingDelay() const OVERRIDE;
374 virtual bool SetConfig(const ::media::AudioDecoderConfig& config) OVERRIDE;
375 virtual void SetStreamVolumeMultiplier(float multiplier) OVERRIDE;
376 virtual bool GetStatistics(Statistics* stats) const OVERRIDE;
377
378 private:
379 scoped_ptr<MediaComponentDeviceFake> fake_pipeline_;
380
381 ::media::AudioDecoderConfig config_;
382
383 DISALLOW_COPY_AND_ASSIGN(AudioPipelineDeviceFake);
384 };
385
386 AudioPipelineDeviceFake::AudioPipelineDeviceFake(
387 MediaClockDeviceFake* media_clock_device)
388 : fake_pipeline_(new MediaComponentDeviceFake(media_clock_device)) {
389 DetachFromThread();
390 }
391
392 AudioPipelineDeviceFake::~AudioPipelineDeviceFake() {
393 }
394
395 void AudioPipelineDeviceFake::SetClient(const Client& client) {
396 fake_pipeline_->SetClient(client);
397 }
398
399 MediaComponentDevice::State AudioPipelineDeviceFake::GetState() const {
400 return fake_pipeline_->GetState();
401 }
402
403 bool AudioPipelineDeviceFake::SetState(State new_state) {
404 bool success = fake_pipeline_->SetState(new_state);
405 if (!success)
406 return false;
407
408 if (new_state == kStateIdle) {
409 DCHECK(config_.IsValidConfig());
410 }
411 if (new_state == kStateUninitialized) {
412 config_ = ::media::AudioDecoderConfig();
413 }
414 return true;
415 }
416
417 bool AudioPipelineDeviceFake::SetStartPts(base::TimeDelta time) {
418 return fake_pipeline_->SetStartPts(time);
419 }
420
421 MediaComponentDevice::FrameStatus AudioPipelineDeviceFake::PushFrame(
422 const scoped_refptr<DecryptContext>& decrypt_context,
423 const scoped_refptr<DecoderBufferBase>& buffer,
424 const FrameStatusCB& completion_cb) {
425 return fake_pipeline_->PushFrame(decrypt_context, buffer, completion_cb);
426 }
427
428 base::TimeDelta AudioPipelineDeviceFake::GetRenderingTime() const {
429 return fake_pipeline_->GetRenderingTime();
430 }
431
432 base::TimeDelta AudioPipelineDeviceFake::GetRenderingDelay() const {
433 return fake_pipeline_->GetRenderingDelay();
434 }
435
436 bool AudioPipelineDeviceFake::SetConfig(
437 const ::media::AudioDecoderConfig& config) {
438 DCHECK(CalledOnValidThread());
439 if (!config.IsValidConfig())
440 return false;
441 config_ = config;
442 return true;
443 }
444
445 void AudioPipelineDeviceFake::SetStreamVolumeMultiplier(float multiplier) {
446 DCHECK(CalledOnValidThread());
447 }
448
449 bool AudioPipelineDeviceFake::GetStatistics(Statistics* stats) const {
450 return fake_pipeline_->GetStatistics(stats);
451 }
452
453
454 class VideoPipelineDeviceFake : public VideoPipelineDevice {
455 public:
456 explicit VideoPipelineDeviceFake(MediaClockDeviceFake* media_clock_device);
457 virtual ~VideoPipelineDeviceFake();
458
459 // VideoPipelineDevice implementation.
460 virtual void SetClient(const Client& client) OVERRIDE;
461 virtual State GetState() const OVERRIDE;
462 virtual bool SetState(State new_state) OVERRIDE;
463 virtual bool SetStartPts(base::TimeDelta time) OVERRIDE;
464 virtual FrameStatus PushFrame(
465 const scoped_refptr<DecryptContext>& decrypt_context,
466 const scoped_refptr<DecoderBufferBase>& buffer,
467 const FrameStatusCB& completion_cb) OVERRIDE;
468 virtual base::TimeDelta GetRenderingTime() const OVERRIDE;
469 virtual base::TimeDelta GetRenderingDelay() const OVERRIDE;
470 virtual void SetVideoClient(const VideoClient& client) OVERRIDE;
471 virtual bool SetConfig(const ::media::VideoDecoderConfig& config) OVERRIDE;
472 virtual bool GetStatistics(Statistics* stats) const OVERRIDE;
473
474 private:
475 scoped_ptr<MediaComponentDeviceFake> fake_pipeline_;
476
477 ::media::VideoDecoderConfig config_;
478
479 DISALLOW_COPY_AND_ASSIGN(VideoPipelineDeviceFake);
480 };
481
482 VideoPipelineDeviceFake::VideoPipelineDeviceFake(
483 MediaClockDeviceFake* media_clock_device)
484 : fake_pipeline_(new MediaComponentDeviceFake(media_clock_device)) {
485 DetachFromThread();
486 }
487
488 VideoPipelineDeviceFake::~VideoPipelineDeviceFake() {
489 }
490
491 void VideoPipelineDeviceFake::SetClient(const Client& client) {
492 fake_pipeline_->SetClient(client);
493 }
494
495 MediaComponentDevice::State VideoPipelineDeviceFake::GetState() const {
496 return fake_pipeline_->GetState();
497 }
498
499 bool VideoPipelineDeviceFake::SetState(State new_state) {
500 bool success = fake_pipeline_->SetState(new_state);
501 if (!success)
502 return false;
503
504 if (new_state == kStateIdle) {
505 DCHECK(config_.IsValidConfig());
506 }
507 if (new_state == kStateUninitialized) {
508 config_ = ::media::VideoDecoderConfig();
509 }
510 return true;
511 }
512
513 bool VideoPipelineDeviceFake::SetStartPts(base::TimeDelta time) {
514 return fake_pipeline_->SetStartPts(time);
515 }
516
517 MediaComponentDevice::FrameStatus VideoPipelineDeviceFake::PushFrame(
518 const scoped_refptr<DecryptContext>& decrypt_context,
519 const scoped_refptr<DecoderBufferBase>& buffer,
520 const FrameStatusCB& completion_cb) {
521 return fake_pipeline_->PushFrame(decrypt_context, buffer, completion_cb);
522 }
523
524 base::TimeDelta VideoPipelineDeviceFake::GetRenderingTime() const {
525 return fake_pipeline_->GetRenderingTime();
526 }
527
528 base::TimeDelta VideoPipelineDeviceFake::GetRenderingDelay() const {
529 return fake_pipeline_->GetRenderingDelay();
530 }
531
532 void VideoPipelineDeviceFake::SetVideoClient(const VideoClient& client) {
533 }
534
535 bool VideoPipelineDeviceFake::SetConfig(
536 const ::media::VideoDecoderConfig& config) {
537 DCHECK(CalledOnValidThread());
538 if (!config.IsValidConfig())
539 return false;
540 config_ = config;
541 return true;
542 }
543
544 bool VideoPipelineDeviceFake::GetStatistics(Statistics* stats) const {
545 return fake_pipeline_->GetStatistics(stats);
546 }
547
548
549 MediaPipelineDeviceFake::MediaPipelineDeviceFake()
550 : media_clock_device_(new MediaClockDeviceFake()),
551 audio_pipeline_device_(
552 new AudioPipelineDeviceFake(media_clock_device_.get())),
553 video_pipeline_device_(
554 new VideoPipelineDeviceFake(media_clock_device_.get())) {
555 }
556
557 MediaPipelineDeviceFake::~MediaPipelineDeviceFake() {
558 }
559
560 AudioPipelineDevice* MediaPipelineDeviceFake::GetAudioPipelineDevice() const {
561 return audio_pipeline_device_.get();
562 }
563
564 VideoPipelineDevice* MediaPipelineDeviceFake::GetVideoPipelineDevice() const {
565 return video_pipeline_device_.get();
566 }
567
568 MediaClockDevice* MediaPipelineDeviceFake::GetMediaClockDevice() const {
569 return media_clock_device_.get();
570 }
571
572 } // namespace media
573 } // namespace chromecast
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698