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

Side by Side Diff: content/renderer/media/webmediaplayer_ms.cc

Issue 1320183003: Preliminary change for new rtc rendering algorithm (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Consider capture buffer contention Created 5 years, 3 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "content/renderer/media/webmediaplayer_ms.h" 5 #include "content/renderer/media/webmediaplayer_ms.h"
6 6
7 #include <limits> 7 #include <limits>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/callback.h" 10 #include "base/callback.h"
11 #include "base/message_loop/message_loop.h" 11 #include "base/message_loop/message_loop.h"
12 #include "base/metrics/histogram.h" 12 #include "base/metrics/histogram.h"
13 #include "cc/blink/context_provider_web_context.h" 13 #include "cc/blink/context_provider_web_context.h"
14 #include "cc/blink/web_layer_impl.h" 14 #include "cc/blink/web_layer_impl.h"
15 #include "cc/layers/video_frame_provider_client_impl.h"
15 #include "cc/layers/video_layer.h" 16 #include "cc/layers/video_layer.h"
16 #include "content/public/renderer/media_stream_audio_renderer.h" 17 #include "content/public/renderer/media_stream_audio_renderer.h"
17 #include "content/public/renderer/media_stream_renderer_factory.h" 18 #include "content/public/renderer/media_stream_renderer_factory.h"
18 #include "content/public/renderer/render_view.h" 19 #include "content/public/renderer/render_view.h"
19 #include "content/public/renderer/video_frame_provider.h" 20 #include "content/public/renderer/video_frame_provider.h"
20 #include "content/renderer/render_frame_impl.h" 21 #include "content/renderer/render_frame_impl.h"
21 #include "content/renderer/render_thread_impl.h" 22 #include "content/renderer/render_thread_impl.h"
22 #include "gpu/blink/webgraphicscontext3d_impl.h" 23 #include "gpu/blink/webgraphicscontext3d_impl.h"
23 #include "media/base/media_log.h" 24 #include "media/base/media_log.h"
24 #include "media/base/video_frame.h" 25 #include "media/base/video_frame.h"
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 return new_frame; 87 return new_frame;
87 } 88 }
88 89
89 } // anonymous namespace 90 } // anonymous namespace
90 91
91 WebMediaPlayerMS::WebMediaPlayerMS( 92 WebMediaPlayerMS::WebMediaPlayerMS(
92 blink::WebFrame* frame, 93 blink::WebFrame* frame,
93 blink::WebMediaPlayerClient* client, 94 blink::WebMediaPlayerClient* client,
94 base::WeakPtr<media::WebMediaPlayerDelegate> delegate, 95 base::WeakPtr<media::WebMediaPlayerDelegate> delegate,
95 media::MediaLog* media_log, 96 media::MediaLog* media_log,
96 scoped_ptr<MediaStreamRendererFactory> factory) 97 scoped_ptr<MediaStreamRendererFactory> factory,
98 const scoped_refptr<base::SingleThreadTaskRunner>& compositor_task_runner)
97 : frame_(frame), 99 : frame_(frame),
98 network_state_(WebMediaPlayer::NetworkStateEmpty), 100 network_state_(WebMediaPlayer::NetworkStateEmpty),
99 ready_state_(WebMediaPlayer::ReadyStateHaveNothing), 101 ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
100 buffered_(static_cast<size_t>(0)), 102 buffered_(static_cast<size_t>(0)),
101 volume_(1.0f), 103 volume_(1.0f),
102 client_(client), 104 client_(client),
103 delegate_(delegate), 105 delegate_(delegate),
104 paused_(true), 106 paused_(true),
105 current_frame_used_(false),
106 video_frame_provider_client_(NULL),
107 received_first_frame_(false), 107 received_first_frame_(false),
108 total_frame_count_(0),
109 dropped_frame_count_(0),
110 media_log_(media_log), 108 media_log_(media_log),
111 renderer_factory_(factory.Pass()) { 109 renderer_factory_(factory.Pass()),
110 compositor_(new Compositor(compositor_task_runner)),
111 compositor_task_runner_(compositor_task_runner) {
112 DVLOG(1) << "WebMediaPlayerMS::ctor"; 112 DVLOG(1) << "WebMediaPlayerMS::ctor";
113 media_log_->AddEvent( 113 media_log_->AddEvent(
114 media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_CREATED)); 114 media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_CREATED));
115 } 115 }
116 116
117 WebMediaPlayerMS::~WebMediaPlayerMS() { 117 WebMediaPlayerMS::~WebMediaPlayerMS() {
118 DVLOG(1) << "WebMediaPlayerMS::dtor"; 118 DVLOG(1) << "WebMediaPlayerMS::dtor";
119 DCHECK(thread_checker_.CalledOnValidThread()); 119 DCHECK(thread_checker_.CalledOnValidThread());
120 120
121 SetVideoFrameProviderClient(NULL); 121 compositor_task_runner_->DeleteSoon(FROM_HERE, compositor_.release());
122
122 GetClient()->setWebLayer(NULL); 123 GetClient()->setWebLayer(NULL);
123 124
124 if (video_frame_provider_.get()) 125 if (video_frame_provider_.get())
125 video_frame_provider_->Stop(); 126 video_frame_provider_->Stop();
126 127
127 if (audio_renderer_.get()) 128 if (audio_renderer_.get())
128 audio_renderer_->Stop(); 129 audio_renderer_->Stop();
129 130
130 media_log_->AddEvent( 131 media_log_->AddEvent(
131 media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_DESTROYED)); 132 media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_DESTROYED));
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 } 180 }
180 181
181 void WebMediaPlayerMS::play() { 182 void WebMediaPlayerMS::play() {
182 DVLOG(1) << "WebMediaPlayerMS::play"; 183 DVLOG(1) << "WebMediaPlayerMS::play";
183 DCHECK(thread_checker_.CalledOnValidThread()); 184 DCHECK(thread_checker_.CalledOnValidThread());
184 185
185 if (paused_) { 186 if (paused_) {
186 if (video_frame_provider_.get()) 187 if (video_frame_provider_.get())
187 video_frame_provider_->Play(); 188 video_frame_provider_->Play();
188 189
190 compositor_task_runner_->PostTask(
191 FROM_HERE, base::Bind(&WebMediaPlayerMS::Compositor::StartRendering,
192 base::Unretained(compositor_.get())));
193
189 if (audio_renderer_.get()) 194 if (audio_renderer_.get())
190 audio_renderer_->Play(); 195 audio_renderer_->Play();
191 196
192 if (delegate_.get()) 197 if (delegate_.get())
193 delegate_->DidPlay(this); 198 delegate_->DidPlay(this);
194 } 199 }
195 200
196 paused_ = false; 201 paused_ = false;
197 202
198 media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PLAY)); 203 media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PLAY));
199 } 204 }
200 205
201 void WebMediaPlayerMS::pause() { 206 void WebMediaPlayerMS::pause() {
202 DVLOG(1) << "WebMediaPlayerMS::pause"; 207 DVLOG(1) << "WebMediaPlayerMS::pause";
203 DCHECK(thread_checker_.CalledOnValidThread()); 208 DCHECK(thread_checker_.CalledOnValidThread());
204 209
205 if (video_frame_provider_.get()) 210 if (video_frame_provider_.get())
206 video_frame_provider_->Pause(); 211 video_frame_provider_->Pause();
207 212
213 compositor_task_runner_->PostTask(
214 FROM_HERE, base::Bind(&WebMediaPlayerMS::Compositor::StopRendering,
215 base::Unretained(compositor_.get())));
216 compositor_->ReplaceCurrentFrameWithACopy(&video_renderer_);
217
208 if (!paused_) { 218 if (!paused_) {
209 if (audio_renderer_.get()) 219 if (audio_renderer_.get())
210 audio_renderer_->Pause(); 220 audio_renderer_->Pause();
211 221
212 if (delegate_.get()) 222 if (delegate_.get())
213 delegate_->DidPause(this); 223 delegate_->DidPause(this);
214 } 224 }
215 225
216 paused_ = true; 226 paused_ = true;
217 227
218 media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PAUSE)); 228 media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PAUSE));
219
220 if (!current_frame_.get())
221 return;
222
223 // Copy the frame so that rendering can show the last received frame.
224 // The original frame must not be referenced when the player is paused since
225 // there might be a finite number of available buffers. E.g, video that
226 // originates from a video camera.
227 scoped_refptr<media::VideoFrame> new_frame =
228 CopyFrameToYV12(current_frame_, &video_renderer_);
229
230 base::AutoLock auto_lock(current_frame_lock_);
231 current_frame_ = new_frame;
232 } 229 }
233 230
234 bool WebMediaPlayerMS::supportsSave() const { 231 bool WebMediaPlayerMS::supportsSave() const {
235 DCHECK(thread_checker_.CalledOnValidThread()); 232 DCHECK(thread_checker_.CalledOnValidThread());
236 return false; 233 return false;
237 } 234 }
238 235
239 void WebMediaPlayerMS::seek(double seconds) { 236 void WebMediaPlayerMS::seek(double seconds) {
240 DCHECK(thread_checker_.CalledOnValidThread()); 237 DCHECK(thread_checker_.CalledOnValidThread());
241 } 238 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
281 } 278 }
282 279
283 bool WebMediaPlayerMS::hasAudio() const { 280 bool WebMediaPlayerMS::hasAudio() const {
284 DCHECK(thread_checker_.CalledOnValidThread()); 281 DCHECK(thread_checker_.CalledOnValidThread());
285 return (audio_renderer_.get() != NULL); 282 return (audio_renderer_.get() != NULL);
286 } 283 }
287 284
288 blink::WebSize WebMediaPlayerMS::naturalSize() const { 285 blink::WebSize WebMediaPlayerMS::naturalSize() const {
289 DCHECK(thread_checker_.CalledOnValidThread()); 286 DCHECK(thread_checker_.CalledOnValidThread());
290 287
291 if (!current_frame_.get()) 288 gfx::Size size = compositor_->GetCurrentSize();
292 return blink::WebSize();
293 289
294 const gfx::Size& size = current_frame_->natural_size();
295 DVLOG(3) << "WebMediaPlayerMS::naturalSize, " << size.ToString(); 290 DVLOG(3) << "WebMediaPlayerMS::naturalSize, " << size.ToString();
296 return blink::WebSize(size); 291 return blink::WebSize(size);
297 } 292 }
298 293
299 bool WebMediaPlayerMS::paused() const { 294 bool WebMediaPlayerMS::paused() const {
300 DCHECK(thread_checker_.CalledOnValidThread()); 295 DCHECK(thread_checker_.CalledOnValidThread());
301 return paused_; 296 return paused_;
302 } 297 }
303 298
304 bool WebMediaPlayerMS::seeking() const { 299 bool WebMediaPlayerMS::seeking() const {
305 DCHECK(thread_checker_.CalledOnValidThread()); 300 DCHECK(thread_checker_.CalledOnValidThread());
306 return false; 301 return false;
307 } 302 }
308 303
309 double WebMediaPlayerMS::duration() const { 304 double WebMediaPlayerMS::duration() const {
310 DCHECK(thread_checker_.CalledOnValidThread()); 305 DCHECK(thread_checker_.CalledOnValidThread());
311 return std::numeric_limits<double>::infinity(); 306 return std::numeric_limits<double>::infinity();
312 } 307 }
313 308
314 double WebMediaPlayerMS::currentTime() const { 309 double WebMediaPlayerMS::currentTime() const {
315 DCHECK(thread_checker_.CalledOnValidThread()); 310 DCHECK(thread_checker_.CalledOnValidThread());
316 if (current_time_.ToInternalValue() != 0) { 311 base::TimeDelta current_time = compositor_->GetCurrentTime();
317 return current_time_.InSecondsF(); 312 if (current_time.ToInternalValue() != 0) {
313 return current_time.InSecondsF();
318 } else if (audio_renderer_.get()) { 314 } else if (audio_renderer_.get()) {
319 return audio_renderer_->GetCurrentRenderTime().InSecondsF(); 315 return audio_renderer_->GetCurrentRenderTime().InSecondsF();
320 } 316 }
321 return 0.0; 317 return 0.0;
322 } 318 }
323 319
324 WebMediaPlayer::NetworkState WebMediaPlayerMS::networkState() const { 320 WebMediaPlayer::NetworkState WebMediaPlayerMS::networkState() const {
325 DCHECK(thread_checker_.CalledOnValidThread()); 321 DCHECK(thread_checker_.CalledOnValidThread());
326 DVLOG(1) << "WebMediaPlayerMS::networkState, state:" << network_state_; 322 DVLOG(1) << "WebMediaPlayerMS::networkState, state:" << network_state_;
327 return network_state_; 323 return network_state_;
(...skipping 20 matching lines...) Expand all
348 return true; 344 return true;
349 } 345 }
350 346
351 void WebMediaPlayerMS::paint(blink::WebCanvas* canvas, 347 void WebMediaPlayerMS::paint(blink::WebCanvas* canvas,
352 const blink::WebRect& rect, 348 const blink::WebRect& rect,
353 unsigned char alpha, 349 unsigned char alpha,
354 SkXfermode::Mode mode) { 350 SkXfermode::Mode mode) {
355 DVLOG(3) << "WebMediaPlayerMS::paint"; 351 DVLOG(3) << "WebMediaPlayerMS::paint";
356 DCHECK(thread_checker_.CalledOnValidThread()); 352 DCHECK(thread_checker_.CalledOnValidThread());
357 353
354 scoped_refptr<media::VideoFrame> frame = compositor_->GetCurrentFrame();
355
358 media::Context3D context_3d; 356 media::Context3D context_3d;
359 if (current_frame_.get() && current_frame_->HasTextures()) { 357 if (frame.get() && frame->HasTextures()) {
360 cc::ContextProvider* provider = 358 cc::ContextProvider* provider =
361 RenderThreadImpl::current()->SharedMainThreadContextProvider().get(); 359 RenderThreadImpl::current()->SharedMainThreadContextProvider().get();
362 // GPU Process crashed. 360 // GPU Process crashed.
363 if (!provider) 361 if (!provider)
364 return; 362 return;
365 context_3d = media::Context3D(provider->ContextGL(), provider->GrContext()); 363 context_3d = media::Context3D(provider->ContextGL(), provider->GrContext());
366 DCHECK(context_3d.gl); 364 DCHECK(context_3d.gl);
367 } 365 }
368 gfx::RectF dest_rect(rect.x, rect.y, rect.width, rect.height); 366 gfx::RectF dest_rect(rect.x, rect.y, rect.width, rect.height);
369 video_renderer_.Paint(current_frame_, canvas, dest_rect, alpha, mode, 367 video_renderer_.Paint(frame, canvas, dest_rect, alpha, mode,
370 media::VIDEO_ROTATION_0, context_3d); 368 media::VIDEO_ROTATION_0, context_3d);
371
372 {
373 base::AutoLock auto_lock(current_frame_lock_);
374 if (current_frame_.get())
375 current_frame_used_ = true;
376 }
377 } 369 }
378 370
379 bool WebMediaPlayerMS::hasSingleSecurityOrigin() const { 371 bool WebMediaPlayerMS::hasSingleSecurityOrigin() const {
380 DCHECK(thread_checker_.CalledOnValidThread()); 372 DCHECK(thread_checker_.CalledOnValidThread());
381 return true; 373 return true;
382 } 374 }
383 375
384 bool WebMediaPlayerMS::didPassCORSAccessCheck() const { 376 bool WebMediaPlayerMS::didPassCORSAccessCheck() const {
385 DCHECK(thread_checker_.CalledOnValidThread()); 377 DCHECK(thread_checker_.CalledOnValidThread());
386 return true; 378 return true;
387 } 379 }
388 380
389 double WebMediaPlayerMS::mediaTimeForTimeValue(double timeValue) const { 381 double WebMediaPlayerMS::mediaTimeForTimeValue(double timeValue) const {
390 return base::TimeDelta::FromSecondsD(timeValue).InSecondsF(); 382 return base::TimeDelta::FromSecondsD(timeValue).InSecondsF();
391 } 383 }
392 384
393 unsigned WebMediaPlayerMS::decodedFrameCount() const { 385 unsigned WebMediaPlayerMS::decodedFrameCount() const {
394 DCHECK(thread_checker_.CalledOnValidThread()); 386 DCHECK(thread_checker_.CalledOnValidThread());
395 DVLOG(1) << "WebMediaPlayerMS::decodedFrameCount, " << total_frame_count_; 387 unsigned total_frame_count = compositor_->GetTotalFrameCount();
396 return total_frame_count_; 388 DVLOG(1) << "WebMediaPlayerMS::decodedFrameCount, " << total_frame_count;
389 return total_frame_count;
397 } 390 }
398 391
399 unsigned WebMediaPlayerMS::droppedFrameCount() const { 392 unsigned WebMediaPlayerMS::droppedFrameCount() const {
400 DCHECK(thread_checker_.CalledOnValidThread()); 393 DCHECK(thread_checker_.CalledOnValidThread());
401 DVLOG(1) << "WebMediaPlayerMS::droppedFrameCount, " << dropped_frame_count_; 394 unsigned dropped_frame_count = compositor_->GetDroppedFrameCount();
402 return dropped_frame_count_; 395 DVLOG(1) << "WebMediaPlayerMS::droppedFrameCount, " << dropped_frame_count;
396 return dropped_frame_count;
403 } 397 }
404 398
405 unsigned WebMediaPlayerMS::audioDecodedByteCount() const { 399 unsigned WebMediaPlayerMS::audioDecodedByteCount() const {
406 DCHECK(thread_checker_.CalledOnValidThread()); 400 DCHECK(thread_checker_.CalledOnValidThread());
407 NOTIMPLEMENTED(); 401 NOTIMPLEMENTED();
408 return 0; 402 return 0;
409 } 403 }
410 404
411 unsigned WebMediaPlayerMS::videoDecodedByteCount() const { 405 unsigned WebMediaPlayerMS::videoDecodedByteCount() const {
412 DCHECK(thread_checker_.CalledOnValidThread()); 406 DCHECK(thread_checker_.CalledOnValidThread());
413 NOTIMPLEMENTED(); 407 NOTIMPLEMENTED();
414 return 0; 408 return 0;
415 } 409 }
416 410
417 bool WebMediaPlayerMS::copyVideoTextureToPlatformTexture( 411 bool WebMediaPlayerMS::copyVideoTextureToPlatformTexture(
418 blink::WebGraphicsContext3D* web_graphics_context, 412 blink::WebGraphicsContext3D* web_graphics_context,
419 unsigned int texture, 413 unsigned int texture,
420 unsigned int internal_format, 414 unsigned int internal_format,
421 unsigned int type, 415 unsigned int type,
422 bool premultiply_alpha, 416 bool premultiply_alpha,
423 bool flip_y) { 417 bool flip_y) {
424 TRACE_EVENT0("media", "WebMediaPlayerMS:copyVideoTextureToPlatformTexture"); 418 TRACE_EVENT0("media", "WebMediaPlayerMS:copyVideoTextureToPlatformTexture");
425 DCHECK(thread_checker_.CalledOnValidThread()); 419 DCHECK(thread_checker_.CalledOnValidThread());
426 420
427 scoped_refptr<media::VideoFrame> video_frame; 421 scoped_refptr<media::VideoFrame> video_frame = compositor_->GetCurrentFrame();
428 {
429 base::AutoLock auto_lock(current_frame_lock_);
430 video_frame = current_frame_;
431 }
432 422
433 if (!video_frame.get() || video_frame->HasTextures() || 423 if (!video_frame.get() || video_frame->HasTextures() ||
434 media::VideoFrame::NumPlanes(video_frame->format()) != 1) { 424 media::VideoFrame::NumPlanes(video_frame->format()) != 1) {
435 return false; 425 return false;
436 } 426 }
437 427
438 // TODO(dshwang): need more elegant way to convert WebGraphicsContext3D to 428 // TODO(dshwang): need more elegant way to convert WebGraphicsContext3D to
439 // GLES2Interface. 429 // GLES2Interface.
440 gpu::gles2::GLES2Interface* const gl = 430 gpu::gles2::GLES2Interface* const gl =
441 static_cast<gpu_blink::WebGraphicsContext3DImpl*>(web_graphics_context) 431 static_cast<gpu_blink::WebGraphicsContext3DImpl*>(web_graphics_context)
442 ->GetGLInterface(); 432 ->GetGLInterface();
443 media::SkCanvasVideoRenderer::CopyVideoFrameSingleTextureToGLTexture( 433 media::SkCanvasVideoRenderer::CopyVideoFrameSingleTextureToGLTexture(
444 gl, video_frame.get(), texture, internal_format, type, premultiply_alpha, 434 gl, video_frame.get(), texture, internal_format, type, premultiply_alpha,
445 flip_y); 435 flip_y);
446 return true; 436 return true;
447 } 437 }
448 438
449 void WebMediaPlayerMS::SetVideoFrameProviderClient(
450 cc::VideoFrameProvider::Client* client) {
451 // This is called from both the main renderer thread and the compositor
452 // thread (when the main thread is blocked).
453 if (video_frame_provider_client_)
454 video_frame_provider_client_->StopUsingProvider();
455 video_frame_provider_client_ = client;
456 }
457
458 bool WebMediaPlayerMS::UpdateCurrentFrame(base::TimeTicks deadline_min,
459 base::TimeTicks deadline_max) {
460 // TODO(dalecurtis): This should make use of the deadline interval to ensure
461 // the painted frame is correct for the given interval.
462 NOTREACHED();
463 return false;
464 }
465
466 bool WebMediaPlayerMS::HasCurrentFrame() {
467 base::AutoLock auto_lock(current_frame_lock_);
468 return current_frame_;
469 }
470
471 scoped_refptr<media::VideoFrame> WebMediaPlayerMS::GetCurrentFrame() {
472 DVLOG(3) << "WebMediaPlayerMS::GetCurrentFrame";
473 base::AutoLock auto_lock(current_frame_lock_);
474 if (!current_frame_.get())
475 return NULL;
476 current_frame_used_ = true;
477 return current_frame_;
478 }
479
480 void WebMediaPlayerMS::PutCurrentFrame() {
481 DVLOG(3) << "WebMediaPlayerMS::PutCurrentFrame";
482 }
483
484 void WebMediaPlayerMS::OnFrameAvailable( 439 void WebMediaPlayerMS::OnFrameAvailable(
485 const scoped_refptr<media::VideoFrame>& frame) { 440 const scoped_refptr<media::VideoFrame>& frame) {
486 DVLOG(3) << "WebMediaPlayerMS::OnFrameAvailable"; 441 DVLOG(3) << "WebMediaPlayerMS::OnFrameAvailable";
487 DCHECK(thread_checker_.CalledOnValidThread()); 442 DCHECK(thread_checker_.CalledOnValidThread());
488 ++total_frame_count_; 443
444 base::TimeTicks render_time;
445 if (!frame->metadata()->GetTimeTicks(
446 media::VideoFrameMetadata::REFERENCE_TIME, &render_time)) {
447 render_time = base::TimeTicks();
448 }
449 TRACE_EVENT1("webrtc", "WebMediaPlayerMS::OnFrameAvailable",
450 "Ideal Render Instant", render_time.ToInternalValue());
451
489 if (!received_first_frame_) { 452 if (!received_first_frame_) {
490 received_first_frame_ = true; 453 received_first_frame_ = true;
491 {
492 base::AutoLock auto_lock(current_frame_lock_);
493 DCHECK(!current_frame_used_);
494 current_frame_ = frame;
495 }
496 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata); 454 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
497 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); 455 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
498 GetClient()->sizeChanged();
499 456
500 if (video_frame_provider_.get()) { 457 if (video_frame_provider_.get()) {
501 video_weblayer_.reset(new cc_blink::WebLayerImpl( 458 video_weblayer_.reset(new cc_blink::WebLayerImpl(
502 cc::VideoLayer::Create(cc_blink::WebLayerImpl::LayerSettings(), this, 459 cc::VideoLayer::Create(cc_blink::WebLayerImpl::LayerSettings(),
503 media::VIDEO_ROTATION_0))); 460 compositor_.get(), media::VIDEO_ROTATION_0)));
504 video_weblayer_->setOpaque(true); 461 video_weblayer_->setOpaque(true);
505 GetClient()->setWebLayer(video_weblayer_.get()); 462 GetClient()->setWebLayer(video_weblayer_.get());
506 } 463 }
507 } 464 }
508 465
509 // Do not update |current_frame_| when paused. 466 bool size_changed = compositor_->GetCurrentSize() != frame->natural_size();
510 if (paused_)
511 return;
512 467
513 const bool size_changed = 468 compositor_->EnqueueFrame(frame);
514 !current_frame_.get() ||
515 current_frame_->natural_size() != frame->natural_size();
516
517 {
518 base::AutoLock auto_lock(current_frame_lock_);
519 if (!current_frame_used_ && current_frame_.get())
520 ++dropped_frame_count_;
521 current_frame_ = frame;
522 current_time_ = frame->timestamp();
523 current_frame_used_ = false;
524 }
525 469
526 if (size_changed) 470 if (size_changed)
527 GetClient()->sizeChanged(); 471 GetClient()->sizeChanged();
528
529 GetClient()->repaint();
530 } 472 }
531 473
532 void WebMediaPlayerMS::RepaintInternal() { 474 void WebMediaPlayerMS::RepaintInternal() {
533 DVLOG(1) << "WebMediaPlayerMS::RepaintInternal"; 475 DVLOG(1) << "WebMediaPlayerMS::RepaintInternal";
534 DCHECK(thread_checker_.CalledOnValidThread()); 476 DCHECK(thread_checker_.CalledOnValidThread());
535 GetClient()->repaint(); 477 GetClient()->repaint();
536 } 478 }
537 479
538 void WebMediaPlayerMS::OnSourceError() { 480 void WebMediaPlayerMS::OnSourceError() {
539 DVLOG(1) << "WebMediaPlayerMS::OnSourceError"; 481 DVLOG(1) << "WebMediaPlayerMS::OnSourceError";
(...skipping 15 matching lines...) Expand all
555 // Always notify to ensure client has the latest value. 497 // Always notify to ensure client has the latest value.
556 GetClient()->readyStateChanged(); 498 GetClient()->readyStateChanged();
557 } 499 }
558 500
559 blink::WebMediaPlayerClient* WebMediaPlayerMS::GetClient() { 501 blink::WebMediaPlayerClient* WebMediaPlayerMS::GetClient() {
560 DCHECK(thread_checker_.CalledOnValidThread()); 502 DCHECK(thread_checker_.CalledOnValidThread());
561 DCHECK(client_); 503 DCHECK(client_);
562 return client_; 504 return client_;
563 } 505 }
564 506
507 WebMediaPlayerMS::Compositor::Compositor(
508 const scoped_refptr<base::SingleThreadTaskRunner>& compositor_task_runner)
509 : compositor_task_runner_(compositor_task_runner),
510 video_frame_provider_client_(NULL),
511 current_frame_used_(false),
512 last_deadline_max_(base::TimeTicks()),
513 total_frame_count_(0),
514 dropped_frame_count_(0),
515 paused_(false) {}
516
517 WebMediaPlayerMS::Compositor::~Compositor() {
518 DCHECK(compositor_task_runner_->BelongsToCurrentThread());
519 if (video_frame_provider_client_)
520 video_frame_provider_client_->StopUsingProvider();
521 }
522
523 void WebMediaPlayerMS::Compositor::EnqueueFrame(
524 scoped_refptr<media::VideoFrame> const& frame) {
525 base::AutoLock auto_lock(current_frame_lock_);
526 ++total_frame_count_;
527
528 if (base::TimeTicks::Now() > last_deadline_max_) {
529 // TODO(qiangchen): This shows vsyncs stops rendering frames. A probable
530 // cause is that the tab is not in the front. But we still have to let
531 // old frames go. Call VRA::RemoveExpiredFrames.
532
533 }
534
535 if (!current_frame_used_) {
536 ++dropped_frame_count_;
537 }
538
539 // TODO(qiangchen): Instead of using one variable to hold one frame, use
540 // VideoRendererAlgorithm.
541 current_frame_ = frame;
542 current_frame_used_ = false;
543 }
544
545 bool WebMediaPlayerMS::Compositor::UpdateCurrentFrame(
546 base::TimeTicks deadline_min,
547 base::TimeTicks deadline_max) {
548 DCHECK(compositor_task_runner_->BelongsToCurrentThread());
549 base::AutoLock auto_lock(current_frame_lock_);
550 TRACE_EVENT_BEGIN2("webrtc", "WebMediaPlayerMS::UpdateCurrentFrame",
551 "Actual Render Begin", deadline_min.ToInternalValue(),
552 "Actual Render End", deadline_max.ToInternalValue());
553 last_deadline_max_ = deadline_max;
554
555 // TODO(dalecurtis): This should make use of the deadline interval to ensure
556 // the painted frame is correct for the given interval.
557
558 if (paused_)
559 return false;
560
561
562 base::TimeTicks render_time;
563 if (!current_frame_->metadata()->GetTimeTicks(
564 media::VideoFrameMetadata::REFERENCE_TIME, &render_time)) {
565 render_time = base::TimeTicks();
566 }
567 TRACE_EVENT_END1("webrtc", "WebMediaPlayerMS::UpdateCurrentFrame",
568 "Ideal Render Instant", render_time.ToInternalValue());
569 return !current_frame_used_;
570 }
571
572 bool WebMediaPlayerMS::Compositor::HasCurrentFrame() {
573 base::AutoLock auto_lock(current_frame_lock_);
574 return !!current_frame_.get();
575 }
576
577 scoped_refptr<media::VideoFrame>
578 WebMediaPlayerMS::Compositor::GetCurrentFrame() {
579 DVLOG(3) << "WebMediaPlayerMS::Compositor::GetCurrentFrame";
580 base::AutoLock auto_lock(current_frame_lock_);
581 if (!current_frame_.get())
582 return NULL;
583 return current_frame_;
584 }
585
586 void WebMediaPlayerMS::Compositor::PutCurrentFrame() {
587 DVLOG(3) << "WebMediaPlayerMS::PutCurrentFrame";
588 current_frame_used_ = true;
589 }
590
591 void WebMediaPlayerMS::Compositor::SetVideoFrameProviderClient(
592 cc::VideoFrameProvider::Client* client) {
593 DCHECK(compositor_task_runner_->BelongsToCurrentThread());
594 if (video_frame_provider_client_)
595 video_frame_provider_client_->StopUsingProvider();
596
597 video_frame_provider_client_ = client;
598 if (video_frame_provider_client_)
599 video_frame_provider_client_->StartRendering();
600 }
601
602 void WebMediaPlayerMS::Compositor::StartRendering() {
603 DCHECK(compositor_task_runner_->BelongsToCurrentThread());
604 paused_ = false;
605 if (video_frame_provider_client_)
606 video_frame_provider_client_->StartRendering();
607 }
608
609 void WebMediaPlayerMS::Compositor::StopRendering() {
610 DCHECK(compositor_task_runner_->BelongsToCurrentThread());
611 paused_ = true;
612 if (video_frame_provider_client_)
613 video_frame_provider_client_->StopRendering();
614 }
615
616 void WebMediaPlayerMS::Compositor::ReplaceCurrentFrameWithACopy(
617 media::SkCanvasVideoRenderer* renderer) {
618 base::AutoLock auto_lock(current_frame_lock_);
619 if (!current_frame_.get())
620 return;
621
622 // Copy the frame so that rendering can show the last received frame.
623 // The original frame must not be referenced when the player is paused since
624 // there might be a finite number of available buffers. E.g, video that
625 // originates from a video camera.
626 scoped_refptr<media::VideoFrame> new_frame =
627 CopyFrameToYV12(current_frame_, renderer);
628
629 current_frame_ = new_frame;
630 }
631
632 gfx::Size WebMediaPlayerMS::Compositor::GetCurrentSize() {
633 base::AutoLock auto_lock(current_frame_lock_);
634 return current_frame_.get() ? current_frame_->natural_size() : gfx::Size();
635 }
636
637 base::TimeDelta WebMediaPlayerMS::Compositor::GetCurrentTime() {
638 base::AutoLock auto_lock(current_frame_lock_);
639 return current_frame_.get() ? current_frame_->timestamp() : base::TimeDelta();
640 }
641
642 unsigned WebMediaPlayerMS::Compositor::GetTotalFrameCount() {
643 return total_frame_count_;
644 }
645
646 unsigned WebMediaPlayerMS::Compositor::GetDroppedFrameCount() {
647 return dropped_frame_count_;
648 }
565 } // namespace content 649 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/media/webmediaplayer_ms.h ('k') | content/renderer/media/webrtc/media_stream_remote_video_source.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698