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

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

Issue 1005703002: Chromecast: use weak pointers for AvPipelineImpl callbacks on CMA thread. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 9 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
« no previous file with comments | « chromecast/media/cma/pipeline/av_pipeline_impl.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/message_loop/message_loop_proxy.h" 9 #include "base/message_loop/message_loop_proxy.h"
10 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_number_conversions.h"
(...skipping 27 matching lines...) Expand all
38 media_component_device_(media_component_device), 38 media_component_device_(media_component_device),
39 state_(kUninitialized), 39 state_(kUninitialized),
40 buffered_time_(::media::kNoTimestamp()), 40 buffered_time_(::media::kNoTimestamp()),
41 playable_buffered_time_(::media::kNoTimestamp()), 41 playable_buffered_time_(::media::kNoTimestamp()),
42 enable_feeding_(false), 42 enable_feeding_(false),
43 pending_read_(false), 43 pending_read_(false),
44 pending_push_(false), 44 pending_push_(false),
45 enable_time_update_(false), 45 enable_time_update_(false),
46 pending_time_update_task_(false), 46 pending_time_update_task_(false),
47 media_keys_(NULL), 47 media_keys_(NULL),
48 media_keys_callback_id_(kNoCallbackId) { 48 media_keys_callback_id_(kNoCallbackId),
49 weak_factory_(this) {
49 DCHECK(media_component_device); 50 DCHECK(media_component_device);
51 weak_this_ = weak_factory_.GetWeakPtr();
50 thread_checker_.DetachFromThread(); 52 thread_checker_.DetachFromThread();
51 } 53 }
52 54
53 AvPipelineImpl::~AvPipelineImpl() { 55 AvPipelineImpl::~AvPipelineImpl() {
54 } 56 }
55 57
56 void AvPipelineImpl::TransitionToState(State state) { 58 void AvPipelineImpl::TransitionToState(State state) {
57 DCHECK(thread_checker_.CalledOnValidThread()); 59 DCHECK(thread_checker_.CalledOnValidThread());
58 state_ = state; 60 state_ = state;
59 } 61 }
60 62
61 void AvPipelineImpl::SetCodedFrameProvider( 63 void AvPipelineImpl::SetCodedFrameProvider(
62 scoped_ptr<CodedFrameProvider> frame_provider, 64 scoped_ptr<CodedFrameProvider> frame_provider,
63 size_t max_buffer_size, 65 size_t max_buffer_size,
64 size_t max_frame_size) { 66 size_t max_frame_size) {
65 DCHECK_EQ(state_, kUninitialized); 67 DCHECK_EQ(state_, kUninitialized);
66 DCHECK(frame_provider); 68 DCHECK(frame_provider);
67 69
68 // Wrap the incoming frame provider to add some buffering capabilities. 70 // Wrap the incoming frame provider to add some buffering capabilities.
69 frame_provider_.reset( 71 frame_provider_.reset(
70 new BufferingFrameProvider( 72 new BufferingFrameProvider(
71 frame_provider.Pass(), 73 frame_provider.Pass(),
72 max_buffer_size, 74 max_buffer_size,
73 max_frame_size, 75 max_frame_size,
74 base::Bind(&AvPipelineImpl::OnFrameBuffered, this))); 76 base::Bind(&AvPipelineImpl::OnFrameBuffered, weak_this_)));
75 } 77 }
76 78
77 void AvPipelineImpl::SetClient(const AvPipelineClient& client) { 79 void AvPipelineImpl::SetClient(const AvPipelineClient& client) {
78 DCHECK(thread_checker_.CalledOnValidThread()); 80 DCHECK(thread_checker_.CalledOnValidThread());
79 DCHECK_EQ(state_, kUninitialized); 81 DCHECK_EQ(state_, kUninitialized);
80 client_ = client; 82 client_ = client;
81 } 83 }
82 84
83 bool AvPipelineImpl::Initialize() { 85 bool AvPipelineImpl::Initialize() {
84 DCHECK(thread_checker_.CalledOnValidThread()); 86 DCHECK(thread_checker_.CalledOnValidThread());
85 DCHECK_EQ(state_, kUninitialized); 87 DCHECK_EQ(state_, kUninitialized);
86 88
87 MediaComponentDevice::Client client; 89 MediaComponentDevice::Client client;
88 client.eos_cb = base::Bind(&AvPipelineImpl::OnEos, this); 90 client.eos_cb = base::Bind(&AvPipelineImpl::OnEos, weak_this_);
89 media_component_device_->SetClient(client); 91 media_component_device_->SetClient(client);
90 if (!media_component_device_->SetState(MediaComponentDevice::kStateIdle)) 92 if (!media_component_device_->SetState(MediaComponentDevice::kStateIdle))
91 return false; 93 return false;
92 94
93 return true; 95 return true;
94 } 96 }
95 97
96 void AvPipelineImpl::Finalize() { 98 void AvPipelineImpl::Finalize() {
97 DCHECK(thread_checker_.CalledOnValidThread()); 99 DCHECK(thread_checker_.CalledOnValidThread());
98 media_component_device_->SetClient(MediaComponentDevice::Client()); 100 media_component_device_->SetClient(MediaComponentDevice::Client());
(...skipping 27 matching lines...) Expand all
126 if (buffering_state_.get()) 128 if (buffering_state_.get())
127 buffering_state_->SetMediaTime(time); 129 buffering_state_->SetMediaTime(time);
128 130
129 if (!media_component_device_->SetState(MediaComponentDevice::kStateRunning)) 131 if (!media_component_device_->SetState(MediaComponentDevice::kStateRunning))
130 return false; 132 return false;
131 133
132 // Start feeding the pipeline. 134 // Start feeding the pipeline.
133 enable_feeding_ = true; 135 enable_feeding_ = true;
134 base::MessageLoopProxy::current()->PostTask( 136 base::MessageLoopProxy::current()->PostTask(
135 FROM_HERE, 137 FROM_HERE,
136 base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, this)); 138 base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, weak_this_));
137 139
138 return true; 140 return true;
139 } 141 }
140 142
141 void AvPipelineImpl::Flush(const base::Closure& done_cb) { 143 void AvPipelineImpl::Flush(const base::Closure& done_cb) {
142 DCHECK(thread_checker_.CalledOnValidThread()); 144 DCHECK(thread_checker_.CalledOnValidThread());
143 DCHECK_EQ(state_, kFlushing); 145 DCHECK_EQ(state_, kFlushing);
144 DCHECK_EQ( 146 DCHECK_EQ(
145 media_component_device_->GetState(), MediaComponentDevice::kStateRunning); 147 media_component_device_->GetState(), MediaComponentDevice::kStateRunning);
146 // Note: returning to idle state aborts any pending frame push. 148 // Note: returning to idle state aborts any pending frame push.
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 DCHECK(media_keys); 191 DCHECK(media_keys);
190 192
191 { 193 {
192 base::AutoLock lock(media_keys_lock_); 194 base::AutoLock lock(media_keys_lock_);
193 if (media_keys_ && media_keys_callback_id_ != kNoCallbackId) 195 if (media_keys_ && media_keys_callback_id_ != kNoCallbackId)
194 media_keys_->UnregisterPlayer(media_keys_callback_id_); 196 media_keys_->UnregisterPlayer(media_keys_callback_id_);
195 197
196 media_keys_ = media_keys; 198 media_keys_ = media_keys;
197 media_keys_callback_id_ = media_keys_->RegisterPlayer( 199 media_keys_callback_id_ = media_keys_->RegisterPlayer(
198 ::media::BindToCurrentLoop( 200 ::media::BindToCurrentLoop(
199 base::Bind(&AvPipelineImpl::OnCdmStateChanged, this)), 201 base::Bind(&AvPipelineImpl::OnCdmStateChanged, weak_this_)),
200 // Note: this callback gets invoked in ~BrowserCdmCast. Posting 202 // Note: this callback gets invoked in ~BrowserCdmCast. Posting
201 // OnCdmDestroyed to the media thread results in a race condition 203 // OnCdmDestroyed to the media thread results in a race condition
202 // with media_keys_ accesses. This callback must run synchronously, 204 // with media_keys_ accesses. This callback must run synchronously,
203 // otherwise media_keys_ access might occur after it is deleted. 205 // otherwise media_keys_ access might occur after it is deleted.
206 // It cannot use the weak-ptr reference, since it's invoked on the UI
207 // thread.
204 base::Bind(&AvPipelineImpl::OnCdmDestroyed, this)); 208 base::Bind(&AvPipelineImpl::OnCdmDestroyed, this));
205 } 209 }
206 } 210 }
207 211
208 void AvPipelineImpl::OnEos() { 212 void AvPipelineImpl::OnEos() {
209 DCHECK(thread_checker_.CalledOnValidThread()); 213 DCHECK(thread_checker_.CalledOnValidThread());
210 CMALOG(kLogControl) << __FUNCTION__; 214 CMALOG(kLogControl) << __FUNCTION__;
211 if (state_ != kPlaying) 215 if (state_ != kPlaying)
212 return; 216 return;
213 217
214 if (!client_.eos_cb.is_null()) 218 if (!client_.eos_cb.is_null())
215 client_.eos_cb.Run(); 219 client_.eos_cb.Run();
216 } 220 }
217 221
218 void AvPipelineImpl::FetchBufferIfNeeded() { 222 void AvPipelineImpl::FetchBufferIfNeeded() {
219 DCHECK(thread_checker_.CalledOnValidThread()); 223 DCHECK(thread_checker_.CalledOnValidThread());
220 if (!enable_feeding_) 224 if (!enable_feeding_)
221 return; 225 return;
222 226
223 if (pending_read_ || pending_buffer_.get()) 227 if (pending_read_ || pending_buffer_.get())
224 return; 228 return;
225 229
226 pending_read_ = true; 230 pending_read_ = true;
227 frame_provider_->Read( 231 frame_provider_->Read(
228 base::Bind(&AvPipelineImpl::OnNewFrame, this)); 232 base::Bind(&AvPipelineImpl::OnNewFrame, weak_this_));
229 } 233 }
230 234
231 void AvPipelineImpl::OnNewFrame( 235 void AvPipelineImpl::OnNewFrame(
232 const scoped_refptr<DecoderBufferBase>& buffer, 236 const scoped_refptr<DecoderBufferBase>& buffer,
233 const ::media::AudioDecoderConfig& audio_config, 237 const ::media::AudioDecoderConfig& audio_config,
234 const ::media::VideoDecoderConfig& video_config) { 238 const ::media::VideoDecoderConfig& video_config) {
235 DCHECK(thread_checker_.CalledOnValidThread()); 239 DCHECK(thread_checker_.CalledOnValidThread());
236 pending_read_ = false; 240 pending_read_ = false;
237 241
238 if (audio_config.IsValidConfig() || video_config.IsValidConfig()) 242 if (audio_config.IsValidConfig() || video_config.IsValidConfig())
239 update_config_cb_.Run(audio_config, video_config); 243 update_config_cb_.Run(audio_config, video_config);
240 244
241 pending_buffer_ = buffer; 245 pending_buffer_ = buffer;
242 ProcessPendingBuffer(); 246 ProcessPendingBuffer();
243 247
244 base::MessageLoopProxy::current()->PostTask( 248 base::MessageLoopProxy::current()->PostTask(
245 FROM_HERE, 249 FROM_HERE,
246 base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, this)); 250 base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, weak_this_));
247 } 251 }
248 252
249 void AvPipelineImpl::ProcessPendingBuffer() { 253 void AvPipelineImpl::ProcessPendingBuffer() {
250 if (!enable_feeding_) 254 if (!enable_feeding_)
251 return; 255 return;
252 256
253 // Initiate a read if there isn't already one. 257 // Initiate a read if there isn't already one.
254 if (!pending_buffer_.get() && !pending_read_) { 258 if (!pending_buffer_.get() && !pending_read_) {
255 base::MessageLoopProxy::current()->PostTask( 259 base::MessageLoopProxy::current()->PostTask(
256 FROM_HERE, 260 FROM_HERE,
257 base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, this)); 261 base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, weak_this_));
258 return; 262 return;
259 } 263 }
260 264
261 if (!pending_buffer_.get() || pending_push_) 265 if (!pending_buffer_.get() || pending_push_)
262 return; 266 return;
263 267
264 // Break the feeding loop when the end of stream is reached. 268 // Break the feeding loop when the end of stream is reached.
265 if (pending_buffer_->end_of_stream()) { 269 if (pending_buffer_->end_of_stream()) {
266 CMALOG(kLogControl) << __FUNCTION__ << ": EOS reached, stopped feeding"; 270 CMALOG(kLogControl) << __FUNCTION__ << ": EOS reached, stopped feeding";
267 enable_feeding_ = false; 271 enable_feeding_ = false;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 305
302 if (!pending_buffer_->end_of_stream() && buffering_state_.get()) { 306 if (!pending_buffer_->end_of_stream() && buffering_state_.get()) {
303 base::TimeDelta timestamp = pending_buffer_->timestamp(); 307 base::TimeDelta timestamp = pending_buffer_->timestamp();
304 if (timestamp != ::media::kNoTimestamp()) 308 if (timestamp != ::media::kNoTimestamp())
305 buffering_state_->SetMaxRenderingTime(timestamp); 309 buffering_state_->SetMaxRenderingTime(timestamp);
306 } 310 }
307 311
308 MediaComponentDevice::FrameStatus status = media_component_device_->PushFrame( 312 MediaComponentDevice::FrameStatus status = media_component_device_->PushFrame(
309 decrypt_context, 313 decrypt_context,
310 pending_buffer_, 314 pending_buffer_,
311 base::Bind(&AvPipelineImpl::OnFramePushed, this)); 315 base::Bind(&AvPipelineImpl::OnFramePushed, weak_this_));
312 pending_buffer_ = scoped_refptr<DecoderBufferBase>(); 316 pending_buffer_ = scoped_refptr<DecoderBufferBase>();
313 317
314 pending_push_ = (status == MediaComponentDevice::kFramePending); 318 pending_push_ = (status == MediaComponentDevice::kFramePending);
315 if (!pending_push_) 319 if (!pending_push_)
316 OnFramePushed(status); 320 OnFramePushed(status);
317 } 321 }
318 322
319 void AvPipelineImpl::OnFramePushed(MediaComponentDevice::FrameStatus status) { 323 void AvPipelineImpl::OnFramePushed(MediaComponentDevice::FrameStatus status) {
320 DCHECK(thread_checker_.CalledOnValidThread()); 324 DCHECK(thread_checker_.CalledOnValidThread());
321 pending_push_ = false; 325 pending_push_ = false;
322 if (status == MediaComponentDevice::kFrameFailed) { 326 if (status == MediaComponentDevice::kFrameFailed) {
323 LOG(WARNING) << "AvPipelineImpl: PushFrame failed"; 327 LOG(WARNING) << "AvPipelineImpl: PushFrame failed";
324 enable_feeding_ = false; 328 enable_feeding_ = false;
325 state_ = kError; 329 state_ = kError;
326 return; 330 return;
327 } 331 }
328 base::MessageLoopProxy::current()->PostTask( 332 base::MessageLoopProxy::current()->PostTask(
329 FROM_HERE, 333 FROM_HERE,
330 base::Bind(&AvPipelineImpl::ProcessPendingBuffer, this)); 334 base::Bind(&AvPipelineImpl::ProcessPendingBuffer, weak_this_));
331 } 335 }
332 336
333 void AvPipelineImpl::OnCdmStateChanged() { 337 void AvPipelineImpl::OnCdmStateChanged() {
334 DCHECK(thread_checker_.CalledOnValidThread()); 338 DCHECK(thread_checker_.CalledOnValidThread());
335 339
336 // Update the buffering state if needed. 340 // Update the buffering state if needed.
337 if (buffering_state_.get()) 341 if (buffering_state_.get())
338 UpdatePlayableFrames(); 342 UpdatePlayableFrames();
339 343
340 // Process the pending buffer in case the CDM now has the frame key id. 344 // Process the pending buffer in case the CDM now has the frame key id.
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 } 400 }
397 } 401 }
398 402
399 // The frame is playable: remove it from the list of non playable frames. 403 // The frame is playable: remove it from the list of non playable frames.
400 non_playable_frames_.pop_front(); 404 non_playable_frames_.pop_front();
401 } 405 }
402 } 406 }
403 407
404 } // namespace media 408 } // namespace media
405 } // namespace chromecast 409 } // namespace chromecast
OLDNEW
« no previous file with comments | « chromecast/media/cma/pipeline/av_pipeline_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698