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

Side by Side Diff: chromecast/media/cma/backend/media_component_device_feeder_for_test.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: rebased onto CMA testing CL 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_component_device_feeder_for_test.h"
6
7 #include <list>
8 #include <vector>
9
10 #include "base/basictypes.h"
11 #include "base/bind.h"
12 #include "base/logging.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/message_loop/message_loop_proxy.h"
17 #include "base/time/time.h"
18 #include "chromecast/media/base/decrypt_context.h"
19 #include "chromecast/media/cma/backend/audio_pipeline_device.h"
20 #include "chromecast/media/cma/backend/media_clock_device.h"
21 #include "chromecast/media/cma/backend/media_pipeline_device.h"
22 #include "chromecast/media/cma/backend/video_pipeline_device.h"
23 #include "chromecast/media/cma/base/decoder_buffer_adapter.h"
24 #include "chromecast/media/cma/base/decoder_buffer_base.h"
25 #include "chromecast/media/cma/test/frame_segmenter_for_test.h"
26 #include "media/base/audio_decoder_config.h"
27 #include "media/base/buffers.h"
28 #include "media/base/decoder_buffer.h"
29 #include "media/base/video_decoder_config.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31
32 namespace chromecast {
33 namespace media {
34
35 MediaComponentDeviceFeeder::MediaComponentDeviceFeeder(
36 MediaComponentDevice *device,
37 MediaClockDevice *clock,
38 const FrameList& frames)
39 : media_component_device_(device),
40 media_clock_device_(clock),
41 rendering_frame_idx_(1),
42 clock_frame_idx_(1),
43 eos_cb_(),
44 feeding_completed_(false),
45 frame_count_since_last_pause_(0),
46 frame_count_between_pause_(0),
47 delayed_feed_pattern_(),
48 delayed_feed_pattern_idx_(0) {
49 // Copy pointers over, claiming ownership on buffers
50 frames_ = frames;
51 delayed_feed_pattern_.push_back(false);
52 }
53
54 MediaComponentDeviceFeeder::~MediaComponentDeviceFeeder() {
55 }
56
57 // Accessors
58 void MediaComponentDeviceFeeder::SetEosCB(base::Callback<void()> eos_cb) {
59 eos_cb_ = eos_cb;
60 }
61
62 void MediaComponentDeviceFeeder::SetFrameCountBetweenPause(int frame_count) {
63 ASSERT_GT(frame_count,0);
64 frame_count_between_pause_ = frame_count;
65 }
66
67 void MediaComponentDeviceFeeder::SetDelayedFeedPattern(
68 const std::vector<bool>& pattern) {
69 // Copy pattern over
70 delayed_feed_pattern_ = pattern;
71 }
72
73 void MediaComponentDeviceFeeder::Initialize() {
74 MediaComponentDevice::Client client;
75 client.eos_cb =
76 base::Bind(&MediaComponentDeviceFeeder::OnEos, base::Unretained(this));
77 media_component_device_->SetClient(client);
78
79 bool success =
80 media_component_device_->SetState(MediaComponentDevice::kStateIdle);
81 ASSERT_TRUE(success);
82 success = media_component_device_->SetStartPts(base::TimeDelta());
83 ASSERT_TRUE(success);
84 success =
85 media_component_device_->SetState(MediaComponentDevice::kStatePaused);
86 ASSERT_TRUE(success);
87 }
88
89 void MediaComponentDeviceFeeder::Feed() {
90 // Start rendering if needed.
91 if (rendering_frame_idx_ == 0) {
92 media_component_device_->SetState(MediaComponentDevice::kStateRunning);
93 } else {
94 rendering_frame_idx_--;
95 }
96
97 // Start the clock if needed.
98 if (clock_frame_idx_ == 0) {
99 media_clock_device_->SetState(MediaClockDevice::kStateRunning);
100 } else {
101 clock_frame_idx_--;
102 }
103
104 // Possibly feed one frame
105 DCHECK(!frames_.empty());
106 scoped_refptr<DecoderBufferBase> buffer = frames_.front();
107
108 MediaComponentDevice::FrameStatus status =
109 media_component_device_->PushFrame(
110 scoped_refptr<DecryptContext>(),
111 buffer,
112 base::Bind(&MediaComponentDeviceFeeder::OnFramePushed,
113 base::Unretained(this)));
114 EXPECT_NE(status, MediaComponentDevice::kFrameFailed);
115 frames_.pop_front();
116
117 // Feeding is done, just wait for the end of stream callback.
118 if (buffer->end_of_stream() || frames_.empty()) {
119 if (frames_.empty() && !buffer->end_of_stream()) {
120 LOG(WARNING) << "Stream emptied without feeding EOS frame";
121 }
122
123 feeding_completed_ = true;
124 return;
125 }
126
127 if (status == MediaComponentDevice::kFramePending)
128 return;
129
130 OnFramePushed(MediaComponentDevice::kFrameSuccess);
131 }
132
133 void MediaComponentDeviceFeeder::OnFramePushed(
134 MediaComponentDevice::FrameStatus status) {
135 EXPECT_NE(status, MediaComponentDevice::kFrameFailed);
136 if (feeding_completed_)
137 return;
138
139 // Introduce some pauses in the playback at regular intervals.
140 if (frame_count_between_pause_) {
141 frame_count_since_last_pause_ =
142 (frame_count_since_last_pause_ + 1) % frame_count_between_pause_;
143 if (frame_count_since_last_pause_ == 0) {
144 Pause();
145 return;
146 }
147 }
148
149 // Feeder loop.
150 bool delayed_feed = delayed_feed_pattern_[delayed_feed_pattern_idx_];
151 delayed_feed_pattern_idx_ =
152 (delayed_feed_pattern_idx_ + 1) % delayed_feed_pattern_.size();
153
154 if (delayed_feed) {
155 base::MessageLoopProxy::current()->PostDelayedTask(
156 FROM_HERE,
157 base::Bind(&MediaComponentDeviceFeeder::Feed,
158 base::Unretained(this)),
159 base::TimeDelta::FromMilliseconds(50));
160 } else {
161 base::MessageLoopProxy::current()->PostTask(
162 FROM_HERE,
163 base::Bind(&MediaComponentDeviceFeeder::Feed,
164 base::Unretained(this)));
165 }
166 }
167
168 void MediaComponentDeviceFeeder::Pause() {
169 media_clock_device_->SetRate(0.0);
170 media_time_ = media_clock_device_->GetTime();
171 base::MessageLoopProxy::current()->PostDelayedTask(
172 FROM_HERE,
173 base::Bind(&MediaComponentDeviceFeeder::OnPauseCompleted,
174 base::Unretained(this)),
175 base::TimeDelta::FromMilliseconds(500));
176 }
177
178 void MediaComponentDeviceFeeder::OnPauseCompleted() {
179 // Make sure the media time didn't move during that time.
180 base::TimeDelta media_time = media_clock_device_->GetTime();
181
182 // TODO(gunsch): this should be EXPECT_EQ(media_time, media_time_);
183 // However, some backends may move the time forward when rendering the first
184 // frame while in paused mode. This behaviour is not intended.
185 EXPECT_GE(media_time, media_time_);
186 EXPECT_LE(media_time, media_time_ + base::TimeDelta::FromMilliseconds(50));
187
188 // Resume playback and frame feeding.
189 media_clock_device_->SetRate(1.0);
190
191 Feed();
192 }
193
194 void MediaComponentDeviceFeeder::OnEos() {
195 // Shutdown the pipeline.
196 bool success = media_component_device_->SetState(
197 MediaComponentDevice::kStateIdle);
198 ASSERT_TRUE(success);
199 success = media_component_device_->SetState(
200 MediaComponentDevice::kStateUninitialized);
201 ASSERT_TRUE(success);
202
203 if(!eos_cb_.is_null()) {
204 eos_cb_.Run();
205 }
206 }
207
208 } // namespace media
209 } // namespace chromecast
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698