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

Side by Side Diff: chromecast/media/cma/pipeline/av_pipeline_impl.cc

Issue 1372393007: [Chromecast] Upgrade to new CMA backend API (Closed) Base URL: https://chromium.googlesource.com/chromium/src@master
Patch Set: Fix GN build Created 5 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
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chromecast/media/cma/pipeline/av_pipeline_impl.h" 5 #include "chromecast/media/cma/pipeline/av_pipeline_impl.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/location.h" 8 #include "base/location.h"
9 #include "base/single_thread_task_runner.h" 9 #include "base/single_thread_task_runner.h"
10 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_number_conversions.h"
11 #include "base/thread_task_runner_handle.h" 11 #include "base/thread_task_runner_handle.h"
12 #include "chromecast/media/base/decrypt_context_impl.h" 12 #include "chromecast/media/base/decrypt_context_impl.h"
13 #include "chromecast/media/cdm/browser_cdm_cast.h" 13 #include "chromecast/media/cdm/browser_cdm_cast.h"
14 #include "chromecast/media/cma/base/buffering_frame_provider.h" 14 #include "chromecast/media/cma/base/buffering_frame_provider.h"
15 #include "chromecast/media/cma/base/buffering_state.h" 15 #include "chromecast/media/cma/base/buffering_state.h"
16 #include "chromecast/media/cma/base/cast_decoder_buffer_impl.h" 16 #include "chromecast/media/cma/base/cast_decoder_buffer_impl.h"
17 #include "chromecast/media/cma/base/cma_logging.h" 17 #include "chromecast/media/cma/base/cma_logging.h"
18 #include "chromecast/media/cma/base/coded_frame_provider.h" 18 #include "chromecast/media/cma/base/coded_frame_provider.h"
19 #include "chromecast/media/cma/base/decoder_buffer_base.h" 19 #include "chromecast/media/cma/base/decoder_buffer_base.h"
20 #include "chromecast/media/cma/pipeline/decrypt_util.h" 20 #include "chromecast/media/cma/pipeline/decrypt_util.h"
21 #include "chromecast/media/cma/pipeline/frame_status_cb_impl.h"
22 #include "chromecast/media/cma/pipeline/media_component_device_client_impl.h"
23 #include "chromecast/public/media/cast_decrypt_config.h" 21 #include "chromecast/public/media/cast_decrypt_config.h"
24 #include "chromecast/public/media/media_clock_device.h"
25 #include "chromecast/public/media/media_component_device.h"
26 #include "media/base/audio_decoder_config.h" 22 #include "media/base/audio_decoder_config.h"
27 #include "media/base/bind_to_current_loop.h" 23 #include "media/base/bind_to_current_loop.h"
28 #include "media/base/decrypt_config.h" 24 #include "media/base/decrypt_config.h"
29 #include "media/base/timestamp_constants.h" 25 #include "media/base/timestamp_constants.h"
30 26
31 namespace chromecast { 27 namespace chromecast {
32 namespace media { 28 namespace media {
33 29
34 namespace { 30 namespace {
35 31
36 const int kNoCallbackId = -1; 32 const int kNoCallbackId = -1;
37 33
38 } // namespace 34 } // namespace
39 35
40 AvPipelineImpl::AvPipelineImpl(MediaComponentDevice* media_component_device, 36 AvPipelineImpl::AvPipelineImpl(MediaPipelineBackend::Decoder* decoder,
41 const UpdateConfigCB& update_config_cb) 37 const UpdateConfigCB& update_config_cb)
42 : update_config_cb_(update_config_cb), 38 : update_config_cb_(update_config_cb),
43 media_component_device_(media_component_device), 39 decoder_(decoder),
44 state_(kUninitialized), 40 state_(kUninitialized),
45 buffered_time_(::media::kNoTimestamp()), 41 buffered_time_(::media::kNoTimestamp()),
46 playable_buffered_time_(::media::kNoTimestamp()), 42 playable_buffered_time_(::media::kNoTimestamp()),
47 enable_feeding_(false), 43 enable_feeding_(false),
48 pending_read_(false), 44 pending_read_(false),
49 pending_push_(false),
50 enable_time_update_(false), 45 enable_time_update_(false),
51 pending_time_update_task_(false), 46 pending_time_update_task_(false),
52 media_keys_(NULL), 47 media_keys_(NULL),
53 media_keys_callback_id_(kNoCallbackId), 48 media_keys_callback_id_(kNoCallbackId),
54 weak_factory_(this) { 49 weak_factory_(this) {
55 DCHECK(media_component_device); 50 DCHECK(decoder_);
56 weak_this_ = weak_factory_.GetWeakPtr(); 51 weak_this_ = weak_factory_.GetWeakPtr();
57 thread_checker_.DetachFromThread(); 52 thread_checker_.DetachFromThread();
58 } 53 }
59 54
60 AvPipelineImpl::~AvPipelineImpl() { 55 AvPipelineImpl::~AvPipelineImpl() {
61 DCHECK(thread_checker_.CalledOnValidThread()); 56 DCHECK(thread_checker_.CalledOnValidThread());
62 media_component_device_->SetClient(nullptr);
63 57
64 if (media_keys_ && media_keys_callback_id_ != kNoCallbackId) 58 if (media_keys_ && media_keys_callback_id_ != kNoCallbackId)
65 media_keys_->UnregisterPlayer(media_keys_callback_id_); 59 media_keys_->UnregisterPlayer(media_keys_callback_id_);
66 } 60 }
67 61
68 void AvPipelineImpl::TransitionToState(State state) { 62 void AvPipelineImpl::TransitionToState(State state) {
69 DCHECK(thread_checker_.CalledOnValidThread()); 63 DCHECK(thread_checker_.CalledOnValidThread());
70 state_ = state; 64 state_ = state;
71 } 65 }
72 66
73 void AvPipelineImpl::SetCodedFrameProvider( 67 void AvPipelineImpl::SetCodedFrameProvider(
74 scoped_ptr<CodedFrameProvider> frame_provider, 68 scoped_ptr<CodedFrameProvider> frame_provider,
75 size_t max_buffer_size, 69 size_t max_buffer_size,
76 size_t max_frame_size) { 70 size_t max_frame_size) {
77 DCHECK_EQ(state_, kUninitialized); 71 DCHECK_EQ(state_, kUninitialized);
78 DCHECK(frame_provider); 72 DCHECK(frame_provider);
79 73
80 // Wrap the incoming frame provider to add some buffering capabilities. 74 // Wrap the incoming frame provider to add some buffering capabilities.
81 frame_provider_.reset( 75 frame_provider_.reset(
82 new BufferingFrameProvider( 76 new BufferingFrameProvider(
83 frame_provider.Pass(), 77 frame_provider.Pass(),
84 max_buffer_size, 78 max_buffer_size,
85 max_frame_size, 79 max_frame_size,
86 base::Bind(&AvPipelineImpl::OnFrameBuffered, weak_this_))); 80 base::Bind(&AvPipelineImpl::OnFrameBuffered, weak_this_)));
87 } 81 }
88 82
89 void AvPipelineImpl::SetClient(const AvPipelineClient& client) {
90 DCHECK(thread_checker_.CalledOnValidThread());
91 DCHECK_EQ(state_, kUninitialized);
92 client_ = client;
93 }
94
95 bool AvPipelineImpl::Initialize() {
96 DCHECK(thread_checker_.CalledOnValidThread());
97 DCHECK_EQ(state_, kUninitialized);
98
99 media_component_device_->SetClient(new MediaComponentDeviceClientImpl(
100 base::Bind(&AvPipelineImpl::OnEos, weak_this_)));
101 if (!media_component_device_->SetState(MediaComponentDevice::kStateIdle))
102 return false;
103
104 return true;
105 }
106
107 bool AvPipelineImpl::StartPlayingFrom( 83 bool AvPipelineImpl::StartPlayingFrom(
108 base::TimeDelta time, 84 base::TimeDelta time,
109 const scoped_refptr<BufferingState>& buffering_state) { 85 const scoped_refptr<BufferingState>& buffering_state) {
110 DCHECK(thread_checker_.CalledOnValidThread()); 86 DCHECK(thread_checker_.CalledOnValidThread());
111 DCHECK_EQ(state_, kFlushed); 87 DCHECK_EQ(state_, kFlushed);
112 88
113 // Media time where rendering should start
114 // and switch to a state where the audio device accepts incoming buffers.
115 if (!media_component_device_->SetStartPts(time.InMicroseconds()) ||
116 !media_component_device_->SetState(MediaComponentDevice::kStatePaused)) {
117 return false;
118 }
119
120 // Buffering related initialization. 89 // Buffering related initialization.
121 DCHECK(frame_provider_); 90 DCHECK(frame_provider_);
122 buffering_state_ = buffering_state; 91 buffering_state_ = buffering_state;
123 if (buffering_state_.get()) 92 if (buffering_state_.get())
124 buffering_state_->SetMediaTime(time); 93 buffering_state_->SetMediaTime(time);
125 94
126 if (!media_component_device_->SetState(MediaComponentDevice::kStateRunning))
127 return false;
128
129 // Start feeding the pipeline. 95 // Start feeding the pipeline.
130 enable_feeding_ = true; 96 enable_feeding_ = true;
131 base::ThreadTaskRunnerHandle::Get()->PostTask( 97 base::ThreadTaskRunnerHandle::Get()->PostTask(
132 FROM_HERE, base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, weak_this_)); 98 FROM_HERE, base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, weak_this_));
133 99
134 return true; 100 return true;
135 } 101 }
136 102
137 void AvPipelineImpl::Flush(const base::Closure& done_cb) { 103 void AvPipelineImpl::Flush(const base::Closure& done_cb) {
138 DCHECK(thread_checker_.CalledOnValidThread()); 104 DCHECK(thread_checker_.CalledOnValidThread());
139 DCHECK_EQ(state_, kFlushing); 105 DCHECK_EQ(state_, kFlushing);
140 DCHECK_EQ( 106
141 media_component_device_->GetState(), MediaComponentDevice::kStateRunning);
142 // Note: returning to idle state aborts any pending frame push. 107 // Note: returning to idle state aborts any pending frame push.
143 media_component_device_->SetState(MediaComponentDevice::kStateIdle); 108 pushed_buffer_.reset();
144 pending_push_ = false;
145 109
146 // Break the feeding loop. 110 // Break the feeding loop.
147 enable_feeding_ = false; 111 enable_feeding_ = false;
148 112
149 // Remove any pending buffer. 113 // Remove any pending buffer.
150 pending_buffer_ = scoped_refptr<DecoderBufferBase>(); 114 pending_buffer_ = scoped_refptr<DecoderBufferBase>();
151 115
152 // Finally, remove any frames left in the frame provider. 116 // Finally, remove any frames left in the frame provider.
153 pending_read_ = false; 117 pending_read_ = false;
154 buffered_time_ = ::media::kNoTimestamp(); 118 buffered_time_ = ::media::kNoTimestamp();
155 playable_buffered_time_ = ::media::kNoTimestamp(); 119 playable_buffered_time_ = ::media::kNoTimestamp();
156 non_playable_frames_.clear(); 120 non_playable_frames_.clear();
157 frame_provider_->Flush(done_cb); 121 frame_provider_->Flush(done_cb);
158 } 122 }
159 123
160 void AvPipelineImpl::Stop() { 124 void AvPipelineImpl::Stop() {
161 DCHECK(thread_checker_.CalledOnValidThread()); 125 DCHECK(thread_checker_.CalledOnValidThread());
162 126
163 // Stop can be called from any state. 127 // Stop can be called from any state.
164 if (state_ == kUninitialized || state_ == kStopped) 128 if (state_ == kUninitialized || state_ == kStopped)
165 return; 129 return;
166 130
167 // Stop feeding the pipeline. 131 // Stop feeding the pipeline.
168 enable_feeding_ = false; 132 enable_feeding_ = false;
169
170 // Release hardware resources on Stop.
171 if (media_component_device_->GetState() ==
172 MediaComponentDevice::kStatePaused ||
173 media_component_device_->GetState() ==
174 MediaComponentDevice::kStateRunning) {
175 media_component_device_->SetState(MediaComponentDevice::kStateIdle);
176 }
177 if (media_component_device_->GetState() == MediaComponentDevice::kStateIdle) {
178 media_component_device_->SetState(
179 MediaComponentDevice::kStateUninitialized);
180 }
181 } 133 }
182 134
183 void AvPipelineImpl::SetCdm(BrowserCdmCast* media_keys) { 135 void AvPipelineImpl::SetCdm(BrowserCdmCast* media_keys) {
184 DCHECK(thread_checker_.CalledOnValidThread()); 136 DCHECK(thread_checker_.CalledOnValidThread());
185 DCHECK(media_keys); 137 DCHECK(media_keys);
186 138
187 if (media_keys_ && media_keys_callback_id_ != kNoCallbackId) 139 if (media_keys_ && media_keys_callback_id_ != kNoCallbackId)
188 media_keys_->UnregisterPlayer(media_keys_callback_id_); 140 media_keys_->UnregisterPlayer(media_keys_callback_id_);
189 141
190 media_keys_ = media_keys; 142 media_keys_ = media_keys;
191 media_keys_callback_id_ = media_keys_->RegisterPlayer( 143 media_keys_callback_id_ = media_keys_->RegisterPlayer(
192 base::Bind(&AvPipelineImpl::OnCdmStateChanged, weak_this_), 144 base::Bind(&AvPipelineImpl::OnCdmStateChanged, weak_this_),
193 base::Bind(&AvPipelineImpl::OnCdmDestroyed, weak_this_)); 145 base::Bind(&AvPipelineImpl::OnCdmDestroyed, weak_this_));
194 } 146 }
195 147
196 void AvPipelineImpl::OnEos() {
197 DCHECK(thread_checker_.CalledOnValidThread());
198 CMALOG(kLogControl) << __FUNCTION__;
199 if (state_ != kPlaying)
200 return;
201
202 if (!client_.eos_cb.is_null())
203 client_.eos_cb.Run();
204 }
205
206 void AvPipelineImpl::FetchBufferIfNeeded() { 148 void AvPipelineImpl::FetchBufferIfNeeded() {
207 DCHECK(thread_checker_.CalledOnValidThread()); 149 DCHECK(thread_checker_.CalledOnValidThread());
208 if (!enable_feeding_) 150 if (!enable_feeding_)
209 return; 151 return;
210 152
211 if (pending_read_ || pending_buffer_.get()) 153 if (pending_read_ || pending_buffer_.get())
212 return; 154 return;
213 155
214 pending_read_ = true; 156 pending_read_ = true;
215 frame_provider_->Read( 157 frame_provider_->Read(
(...skipping 22 matching lines...) Expand all
238 return; 180 return;
239 181
240 // Initiate a read if there isn't already one. 182 // Initiate a read if there isn't already one.
241 if (!pending_buffer_.get() && !pending_read_) { 183 if (!pending_buffer_.get() && !pending_read_) {
242 base::ThreadTaskRunnerHandle::Get()->PostTask( 184 base::ThreadTaskRunnerHandle::Get()->PostTask(
243 FROM_HERE, 185 FROM_HERE,
244 base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, weak_this_)); 186 base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, weak_this_));
245 return; 187 return;
246 } 188 }
247 189
248 if (!pending_buffer_.get() || pending_push_) 190 if (!pending_buffer_.get() || pushed_buffer_)
249 return; 191 return;
250 192
251 // Break the feeding loop when the end of stream is reached. 193 // Break the feeding loop when the end of stream is reached.
252 if (pending_buffer_->end_of_stream()) { 194 if (pending_buffer_->end_of_stream()) {
253 CMALOG(kLogControl) << __FUNCTION__ << ": EOS reached, stopped feeding"; 195 CMALOG(kLogControl) << __FUNCTION__ << ": EOS reached, stopped feeding";
254 enable_feeding_ = false; 196 enable_feeding_ = false;
255 } 197 }
256 198
257 scoped_ptr<DecryptContextImpl> decrypt_context; 199 scoped_ptr<DecryptContextImpl> decrypt_context;
258 if (!pending_buffer_->end_of_stream() && 200 if (!pending_buffer_->end_of_stream() &&
(...skipping 23 matching lines...) Expand all
282 decrypt_context.reset(); 224 decrypt_context.reset();
283 } 225 }
284 } 226 }
285 227
286 if (!pending_buffer_->end_of_stream() && buffering_state_.get()) { 228 if (!pending_buffer_->end_of_stream() && buffering_state_.get()) {
287 base::TimeDelta timestamp = pending_buffer_->timestamp(); 229 base::TimeDelta timestamp = pending_buffer_->timestamp();
288 if (timestamp != ::media::kNoTimestamp()) 230 if (timestamp != ::media::kNoTimestamp())
289 buffering_state_->SetMaxRenderingTime(timestamp); 231 buffering_state_->SetMaxRenderingTime(timestamp);
290 } 232 }
291 233
292 MediaComponentDevice::FrameStatus status = media_component_device_->PushFrame( 234 DCHECK(!pushed_buffer_);
293 decrypt_context.release(), new CastDecoderBufferImpl(pending_buffer_), 235 pushed_buffer_.reset(new CastDecoderBufferImpl(pending_buffer_));
294 new FrameStatusCBImpl( 236 MediaPipelineBackend::BufferStatus status =
295 base::Bind(&AvPipelineImpl::OnFramePushed, weak_this_))); 237 decoder_->PushBuffer(decrypt_context.release(), pushed_buffer_.get());
296 pending_buffer_ = scoped_refptr<DecoderBufferBase>(); 238 pending_buffer_ = scoped_refptr<DecoderBufferBase>();
297 239
298 pending_push_ = (status == MediaComponentDevice::kFramePending); 240 if (status != MediaPipelineBackend::kBufferPending)
299 if (!pending_push_) 241 OnBufferPushed(status);
300 OnFramePushed(status);
301 } 242 }
302 243
303 void AvPipelineImpl::OnFramePushed(MediaComponentDevice::FrameStatus status) { 244 void AvPipelineImpl::OnBufferPushed(MediaPipelineBackend::BufferStatus status) {
304 DCHECK(thread_checker_.CalledOnValidThread()); 245 DCHECK(thread_checker_.CalledOnValidThread());
305 pending_push_ = false; 246 pushed_buffer_.reset();
306 if (status == MediaComponentDevice::kFrameFailed) { 247 if (status == MediaPipelineBackend::kBufferFailed) {
307 LOG(WARNING) << "AvPipelineImpl: PushFrame failed"; 248 LOG(WARNING) << "AvPipelineImpl: PushFrame failed";
308 enable_feeding_ = false; 249 enable_feeding_ = false;
309 state_ = kError; 250 state_ = kError;
310 return; 251 return;
311 } 252 }
312 base::ThreadTaskRunnerHandle::Get()->PostTask( 253 base::ThreadTaskRunnerHandle::Get()->PostTask(
313 FROM_HERE, base::Bind(&AvPipelineImpl::ProcessPendingBuffer, weak_this_)); 254 FROM_HERE, base::Bind(&AvPipelineImpl::ProcessPendingBuffer, weak_this_));
314 } 255 }
315 256
316 void AvPipelineImpl::OnCdmStateChanged() { 257 void AvPipelineImpl::OnCdmStateChanged() {
317 DCHECK(thread_checker_.CalledOnValidThread()); 258 DCHECK(thread_checker_.CalledOnValidThread());
318 259
319 // Update the buffering state if needed. 260 // Update the buffering state if needed.
320 if (buffering_state_.get()) 261 if (buffering_state_.get())
321 UpdatePlayableFrames(); 262 UpdatePlayableFrames();
322 263
323 // Process the pending buffer in case the CDM now has the frame key id. 264 // Process the pending buffer in case the CDM now has the frame key id.
324 ProcessPendingBuffer(); 265 ProcessPendingBuffer();
325 } 266 }
326 267
327 void AvPipelineImpl::OnCdmDestroyed() { 268 void AvPipelineImpl::OnCdmDestroyed() {
328 DCHECK(thread_checker_.CalledOnValidThread()); 269 DCHECK(thread_checker_.CalledOnValidThread());
329 media_keys_ = NULL; 270 media_keys_ = NULL;
330 } 271 }
331 272
332 void AvPipelineImpl::OnFrameBuffered( 273 void AvPipelineImpl::OnFrameBuffered(
slan 2015/10/07 20:56:17 This should be OnBufferBuffered() to maintain cons
kmackay 2015/10/09 20:35:40 Changed to OnDataBuffered().
333 const scoped_refptr<DecoderBufferBase>& buffer, 274 const scoped_refptr<DecoderBufferBase>& buffer,
334 bool is_at_max_capacity) { 275 bool is_at_max_capacity) {
335 DCHECK(thread_checker_.CalledOnValidThread()); 276 DCHECK(thread_checker_.CalledOnValidThread());
336 277
337 if (!buffering_state_.get()) 278 if (!buffering_state_.get())
338 return; 279 return;
339 280
340 if (!buffer->end_of_stream() && (buffered_time_ == ::media::kNoTimestamp() || 281 if (!buffer->end_of_stream() && (buffered_time_ == ::media::kNoTimestamp() ||
341 buffered_time_ < buffer->timestamp())) { 282 buffered_time_ < buffer->timestamp())) {
342 buffered_time_ = buffer->timestamp(); 283 buffered_time_ = buffer->timestamp();
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 } 319 }
379 } 320 }
380 321
381 // The frame is playable: remove it from the list of non playable frames. 322 // The frame is playable: remove it from the list of non playable frames.
382 non_playable_frames_.pop_front(); 323 non_playable_frames_.pop_front();
383 } 324 }
384 } 325 }
385 326
386 } // namespace media 327 } // namespace media
387 } // namespace chromecast 328 } // namespace chromecast
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698