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

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

Issue 1265433003: Preliminary change for new rtc rendering algorithm (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Style Created 5 years, 4 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 scoped_refptr<base::SingleThreadTaskRunner> compositor_thread)
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_thread)),
111 compositor_thread_(compositor_thread) {
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_thread_->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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 } 181 }
181 182
182 void WebMediaPlayerMS::play() { 183 void WebMediaPlayerMS::play() {
183 DVLOG(1) << "WebMediaPlayerMS::play"; 184 DVLOG(1) << "WebMediaPlayerMS::play";
184 DCHECK(thread_checker_.CalledOnValidThread()); 185 DCHECK(thread_checker_.CalledOnValidThread());
185 186
186 if (paused_) { 187 if (paused_) {
187 if (video_frame_provider_.get()) 188 if (video_frame_provider_.get())
188 video_frame_provider_->Play(); 189 video_frame_provider_->Play();
189 190
191 compositor_thread_->PostTask(
192 FROM_HERE, base::Bind(&WebMediaPlayerMS::Compositor::StartRendering,
193 base::Unretained(compositor_.get())));
194
190 if (audio_renderer_.get()) 195 if (audio_renderer_.get())
191 audio_renderer_->Play(); 196 audio_renderer_->Play();
192 197
193 if (delegate_.get()) 198 if (delegate_.get())
194 delegate_->DidPlay(this); 199 delegate_->DidPlay(this);
195 } 200 }
196 201
197 paused_ = false; 202 paused_ = false;
198 203
199 media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PLAY)); 204 media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PLAY));
200 } 205 }
201 206
202 void WebMediaPlayerMS::pause() { 207 void WebMediaPlayerMS::pause() {
203 DVLOG(1) << "WebMediaPlayerMS::pause"; 208 DVLOG(1) << "WebMediaPlayerMS::pause";
204 DCHECK(thread_checker_.CalledOnValidThread()); 209 DCHECK(thread_checker_.CalledOnValidThread());
205 210
206 if (video_frame_provider_.get()) 211 if (video_frame_provider_.get())
207 video_frame_provider_->Pause(); 212 video_frame_provider_->Pause();
208 213
214 compositor_thread_->PostTask(
215 FROM_HERE, base::Bind(&WebMediaPlayerMS::Compositor::StopRendering,
216 base::Unretained(compositor_.get())));
217
209 if (!paused_) { 218 if (!paused_) {
210 if (audio_renderer_.get()) 219 if (audio_renderer_.get())
211 audio_renderer_->Pause(); 220 audio_renderer_->Pause();
212 221
213 if (delegate_.get()) 222 if (delegate_.get())
214 delegate_->DidPause(this); 223 delegate_->DidPause(this);
215 } 224 }
216 225
217 paused_ = true; 226 paused_ = true;
218 227
219 media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PAUSE)); 228 media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PAUSE));
220
221 if (!current_frame_.get())
222 return;
223
224 // Copy the frame so that rendering can show the last received frame.
225 // The original frame must not be referenced when the player is paused since
226 // there might be a finite number of available buffers. E.g, video that
227 // originates from a video camera.
228 scoped_refptr<media::VideoFrame> new_frame =
229 CopyFrameToYV12(current_frame_, &video_renderer_);
230
231 base::AutoLock auto_lock(current_frame_lock_);
232 current_frame_ = new_frame;
233 } 229 }
234 230
235 bool WebMediaPlayerMS::supportsSave() const { 231 bool WebMediaPlayerMS::supportsSave() const {
236 DCHECK(thread_checker_.CalledOnValidThread()); 232 DCHECK(thread_checker_.CalledOnValidThread());
237 return false; 233 return false;
238 } 234 }
239 235
240 void WebMediaPlayerMS::seek(double seconds) { 236 void WebMediaPlayerMS::seek(double seconds) {
241 DCHECK(thread_checker_.CalledOnValidThread()); 237 DCHECK(thread_checker_.CalledOnValidThread());
242 } 238 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
280 } 276 }
281 277
282 bool WebMediaPlayerMS::hasAudio() const { 278 bool WebMediaPlayerMS::hasAudio() const {
283 DCHECK(thread_checker_.CalledOnValidThread()); 279 DCHECK(thread_checker_.CalledOnValidThread());
284 return (audio_renderer_.get() != NULL); 280 return (audio_renderer_.get() != NULL);
285 } 281 }
286 282
287 blink::WebSize WebMediaPlayerMS::naturalSize() const { 283 blink::WebSize WebMediaPlayerMS::naturalSize() const {
288 DCHECK(thread_checker_.CalledOnValidThread()); 284 DCHECK(thread_checker_.CalledOnValidThread());
289 285
290 gfx::Size size; 286 gfx::Size size = compositor_->CurrentFrameSize();
291 if (current_frame_.get()) 287
292 size = current_frame_->natural_size();
293 DVLOG(3) << "WebMediaPlayerMS::naturalSize, " << size.ToString(); 288 DVLOG(3) << "WebMediaPlayerMS::naturalSize, " << size.ToString();
294 return blink::WebSize(size); 289 return blink::WebSize(size);
295 } 290 }
296 291
297 bool WebMediaPlayerMS::paused() const { 292 bool WebMediaPlayerMS::paused() const {
298 DCHECK(thread_checker_.CalledOnValidThread()); 293 DCHECK(thread_checker_.CalledOnValidThread());
299 return paused_; 294 return paused_;
300 } 295 }
301 296
302 bool WebMediaPlayerMS::seeking() const { 297 bool WebMediaPlayerMS::seeking() const {
303 DCHECK(thread_checker_.CalledOnValidThread()); 298 DCHECK(thread_checker_.CalledOnValidThread());
304 return false; 299 return false;
305 } 300 }
306 301
307 double WebMediaPlayerMS::duration() const { 302 double WebMediaPlayerMS::duration() const {
308 DCHECK(thread_checker_.CalledOnValidThread()); 303 DCHECK(thread_checker_.CalledOnValidThread());
309 return std::numeric_limits<double>::infinity(); 304 return std::numeric_limits<double>::infinity();
310 } 305 }
311 306
312 double WebMediaPlayerMS::currentTime() const { 307 double WebMediaPlayerMS::currentTime() const {
313 DCHECK(thread_checker_.CalledOnValidThread()); 308 DCHECK(thread_checker_.CalledOnValidThread());
314 if (current_time_.ToInternalValue() != 0) { 309 base::TimeDelta current_time = compositor_->CurrentFrameTimestamp();
315 return current_time_.InSecondsF(); 310 if (current_time.ToInternalValue() != 0) {
311 return current_time.InSecondsF();
316 } else if (audio_renderer_.get()) { 312 } else if (audio_renderer_.get()) {
317 return audio_renderer_->GetCurrentRenderTime().InSecondsF(); 313 return audio_renderer_->GetCurrentRenderTime().InSecondsF();
318 } 314 }
319 return 0.0; 315 return 0.0;
320 } 316 }
321 317
322 WebMediaPlayer::NetworkState WebMediaPlayerMS::networkState() const { 318 WebMediaPlayer::NetworkState WebMediaPlayerMS::networkState() const {
323 DCHECK(thread_checker_.CalledOnValidThread()); 319 DCHECK(thread_checker_.CalledOnValidThread());
324 DVLOG(1) << "WebMediaPlayerMS::networkState, state:" << network_state_; 320 DVLOG(1) << "WebMediaPlayerMS::networkState, state:" << network_state_;
325 return network_state_; 321 return network_state_;
(...skipping 20 matching lines...) Expand all
346 return true; 342 return true;
347 } 343 }
348 344
349 void WebMediaPlayerMS::paint(blink::WebCanvas* canvas, 345 void WebMediaPlayerMS::paint(blink::WebCanvas* canvas,
350 const blink::WebRect& rect, 346 const blink::WebRect& rect,
351 unsigned char alpha, 347 unsigned char alpha,
352 SkXfermode::Mode mode) { 348 SkXfermode::Mode mode) {
353 DVLOG(3) << "WebMediaPlayerMS::paint"; 349 DVLOG(3) << "WebMediaPlayerMS::paint";
354 DCHECK(thread_checker_.CalledOnValidThread()); 350 DCHECK(thread_checker_.CalledOnValidThread());
355 351
352 auto frame = compositor_->GetCurrentFrame();
DaleCurtis 2015/08/17 21:31:29 Inconistent use of auto. Use scoped_refptr<VideoFr
qiangchen 2015/08/18 01:21:49 Done.
353
356 media::Context3D context_3d; 354 media::Context3D context_3d;
357 if (current_frame_.get() && current_frame_->HasTextures()) { 355 if (frame.get() && frame->HasTextures()) {
358 cc::ContextProvider* provider = 356 cc::ContextProvider* provider =
359 RenderThreadImpl::current()->SharedMainThreadContextProvider().get(); 357 RenderThreadImpl::current()->SharedMainThreadContextProvider().get();
360 // GPU Process crashed. 358 // GPU Process crashed.
361 if (!provider) 359 if (!provider)
362 return; 360 return;
363 context_3d = media::Context3D(provider->ContextGL(), provider->GrContext()); 361 context_3d = media::Context3D(provider->ContextGL(), provider->GrContext());
364 DCHECK(context_3d.gl); 362 DCHECK(context_3d.gl);
365 } 363 }
366 gfx::RectF dest_rect(rect.x, rect.y, rect.width, rect.height); 364 gfx::RectF dest_rect(rect.x, rect.y, rect.width, rect.height);
367 video_renderer_.Paint(current_frame_, canvas, dest_rect, alpha, mode, 365 compositor_->VideoRenderer()->Paint(frame, canvas, dest_rect, alpha, mode,
368 media::VIDEO_ROTATION_0, context_3d); 366 media::VIDEO_ROTATION_0, context_3d);
369
370 {
371 base::AutoLock auto_lock(current_frame_lock_);
372 if (current_frame_.get())
373 current_frame_used_ = true;
374 }
375 } 367 }
376 368
377 bool WebMediaPlayerMS::hasSingleSecurityOrigin() const { 369 bool WebMediaPlayerMS::hasSingleSecurityOrigin() const {
378 DCHECK(thread_checker_.CalledOnValidThread()); 370 DCHECK(thread_checker_.CalledOnValidThread());
379 return true; 371 return true;
380 } 372 }
381 373
382 bool WebMediaPlayerMS::didPassCORSAccessCheck() const { 374 bool WebMediaPlayerMS::didPassCORSAccessCheck() const {
383 DCHECK(thread_checker_.CalledOnValidThread()); 375 DCHECK(thread_checker_.CalledOnValidThread());
384 return true; 376 return true;
385 } 377 }
386 378
387 double WebMediaPlayerMS::mediaTimeForTimeValue(double timeValue) const { 379 double WebMediaPlayerMS::mediaTimeForTimeValue(double timeValue) const {
388 return media::ConvertSecondsToTimestamp(timeValue).InSecondsF(); 380 return media::ConvertSecondsToTimestamp(timeValue).InSecondsF();
389 } 381 }
390 382
391 unsigned WebMediaPlayerMS::decodedFrameCount() const { 383 unsigned WebMediaPlayerMS::decodedFrameCount() const {
392 DCHECK(thread_checker_.CalledOnValidThread()); 384 DCHECK(thread_checker_.CalledOnValidThread());
393 DVLOG(1) << "WebMediaPlayerMS::decodedFrameCount, " << total_frame_count_; 385 unsigned total_frame_count = compositor_->TotalFrameCount();
394 return total_frame_count_; 386 DVLOG(1) << "WebMediaPlayerMS::decodedFrameCount, " << total_frame_count;
387 return total_frame_count;
395 } 388 }
396 389
397 unsigned WebMediaPlayerMS::droppedFrameCount() const { 390 unsigned WebMediaPlayerMS::droppedFrameCount() const {
398 DCHECK(thread_checker_.CalledOnValidThread()); 391 DCHECK(thread_checker_.CalledOnValidThread());
399 DVLOG(1) << "WebMediaPlayerMS::droppedFrameCount, " << dropped_frame_count_; 392 unsigned dropped_frame_count = compositor_->DroppedFrameCount();
400 return dropped_frame_count_; 393 DVLOG(1) << "WebMediaPlayerMS::droppedFrameCount, " << dropped_frame_count;
394 return dropped_frame_count;
401 } 395 }
402 396
403 unsigned WebMediaPlayerMS::audioDecodedByteCount() const { 397 unsigned WebMediaPlayerMS::audioDecodedByteCount() const {
404 DCHECK(thread_checker_.CalledOnValidThread()); 398 DCHECK(thread_checker_.CalledOnValidThread());
405 NOTIMPLEMENTED(); 399 NOTIMPLEMENTED();
406 return 0; 400 return 0;
407 } 401 }
408 402
409 unsigned WebMediaPlayerMS::videoDecodedByteCount() const { 403 unsigned WebMediaPlayerMS::videoDecodedByteCount() const {
410 DCHECK(thread_checker_.CalledOnValidThread()); 404 DCHECK(thread_checker_.CalledOnValidThread());
411 NOTIMPLEMENTED(); 405 NOTIMPLEMENTED();
412 return 0; 406 return 0;
413 } 407 }
414 408
415 bool WebMediaPlayerMS::copyVideoTextureToPlatformTexture( 409 bool WebMediaPlayerMS::copyVideoTextureToPlatformTexture(
416 blink::WebGraphicsContext3D* web_graphics_context, 410 blink::WebGraphicsContext3D* web_graphics_context,
417 unsigned int texture, 411 unsigned int texture,
418 unsigned int internal_format, 412 unsigned int internal_format,
419 unsigned int type, 413 unsigned int type,
420 bool premultiply_alpha, 414 bool premultiply_alpha,
421 bool flip_y) { 415 bool flip_y) {
422 TRACE_EVENT0("media", "WebMediaPlayerMS:copyVideoTextureToPlatformTexture"); 416 TRACE_EVENT0("media", "WebMediaPlayerMS:copyVideoTextureToPlatformTexture");
423 DCHECK(thread_checker_.CalledOnValidThread()); 417 DCHECK(thread_checker_.CalledOnValidThread());
424 418
425 scoped_refptr<media::VideoFrame> video_frame; 419 scoped_refptr<media::VideoFrame> video_frame = compositor_->CurrentFrame();
426 {
427 base::AutoLock auto_lock(current_frame_lock_);
428 video_frame = current_frame_;
429 }
430 420
431 if (!video_frame.get() || video_frame->HasTextures() || 421 if (!video_frame.get() || video_frame->HasTextures() ||
432 media::VideoFrame::NumPlanes(video_frame->format()) != 1) { 422 media::VideoFrame::NumPlanes(video_frame->format()) != 1) {
433 return false; 423 return false;
434 } 424 }
435 425
436 // TODO(dshwang): need more elegant way to convert WebGraphicsContext3D to 426 // TODO(dshwang): need more elegant way to convert WebGraphicsContext3D to
437 // GLES2Interface. 427 // GLES2Interface.
438 gpu::gles2::GLES2Interface* gl = 428 gpu::gles2::GLES2Interface* gl =
439 static_cast<gpu_blink::WebGraphicsContext3DImpl*>(web_graphics_context) 429 static_cast<gpu_blink::WebGraphicsContext3DImpl*>(web_graphics_context)
440 ->GetGLInterface(); 430 ->GetGLInterface();
441 media::SkCanvasVideoRenderer::CopyVideoFrameSingleTextureToGLTexture( 431 media::SkCanvasVideoRenderer::CopyVideoFrameSingleTextureToGLTexture(
442 gl, video_frame.get(), texture, internal_format, type, premultiply_alpha, 432 gl, video_frame.get(), texture, internal_format, type, premultiply_alpha,
443 flip_y); 433 flip_y);
444 return true; 434 return true;
445 } 435 }
446 436
447 void WebMediaPlayerMS::SetVideoFrameProviderClient(
448 cc::VideoFrameProvider::Client* client) {
449 // This is called from both the main renderer thread and the compositor
450 // thread (when the main thread is blocked).
451 if (video_frame_provider_client_)
452 video_frame_provider_client_->StopUsingProvider();
453 video_frame_provider_client_ = client;
454 }
455
456 bool WebMediaPlayerMS::UpdateCurrentFrame(base::TimeTicks deadline_min,
457 base::TimeTicks deadline_max) {
458 // TODO(dalecurtis): This should make use of the deadline interval to ensure
459 // the painted frame is correct for the given interval.
460 NOTREACHED();
461 return false;
462 }
463
464 bool WebMediaPlayerMS::HasCurrentFrame() {
465 base::AutoLock auto_lock(current_frame_lock_);
466 return current_frame_;
467 }
468
469 scoped_refptr<media::VideoFrame> WebMediaPlayerMS::GetCurrentFrame() {
470 DVLOG(3) << "WebMediaPlayerMS::GetCurrentFrame";
471 base::AutoLock auto_lock(current_frame_lock_);
472 if (!current_frame_.get())
473 return NULL;
474 current_frame_used_ = true;
475 return current_frame_;
476 }
477
478 void WebMediaPlayerMS::PutCurrentFrame() {
479 DVLOG(3) << "WebMediaPlayerMS::PutCurrentFrame";
480 }
481
482 void WebMediaPlayerMS::OnFrameAvailable( 437 void WebMediaPlayerMS::OnFrameAvailable(
483 const scoped_refptr<media::VideoFrame>& frame) { 438 const scoped_refptr<media::VideoFrame>& frame) {
484 DVLOG(3) << "WebMediaPlayerMS::OnFrameAvailable"; 439 DVLOG(3) << "WebMediaPlayerMS::OnFrameAvailable";
485 DCHECK(thread_checker_.CalledOnValidThread()); 440 DCHECK(thread_checker_.CalledOnValidThread());
486 ++total_frame_count_; 441
442 base::TimeTicks render_time;
443 if (!frame->metadata()->GetTimeTicks(
444 media::VideoFrameMetadata::REFERENCE_TIME, &render_time)) {
445 render_time = base::TimeTicks();
446 }
447 TRACE_EVENT1("webrtc", "WebMediaPlayerMS::OnFrameAvailable",
448 "Ideal Render Instant", render_time.ToInternalValue());
449
487 if (!received_first_frame_) { 450 if (!received_first_frame_) {
488 received_first_frame_ = true; 451 received_first_frame_ = true;
489 {
490 base::AutoLock auto_lock(current_frame_lock_);
491 DCHECK(!current_frame_used_);
492 current_frame_ = frame;
493 }
494 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata); 452 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
495 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); 453 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
496 GetClient()->sizeChanged();
497 454
498 if (video_frame_provider_.get()) { 455 if (video_frame_provider_.get()) {
499 video_weblayer_.reset(new cc_blink::WebLayerImpl( 456 video_weblayer_.reset(new cc_blink::WebLayerImpl(
500 cc::VideoLayer::Create(cc_blink::WebLayerImpl::LayerSettings(), this, 457 cc::VideoLayer::Create(cc_blink::WebLayerImpl::LayerSettings(),
501 media::VIDEO_ROTATION_0))); 458 compositor_.get(), media::VIDEO_ROTATION_0)));
502 video_weblayer_->setOpaque(true); 459 video_weblayer_->setOpaque(true);
503 GetClient()->setWebLayer(video_weblayer_.get()); 460 GetClient()->setWebLayer(video_weblayer_.get());
504 } 461 }
505 } 462 }
506 463
507 // Do not update |current_frame_| when paused. 464 bool size_changed = !compositor_->HasCurrentFrame() ||
DaleCurtis 2015/08/17 21:31:29 No need for check since CurrentFrameSize returns g
qiangchen 2015/08/18 01:21:49 Done.
508 if (paused_) 465 compositor_->CurrentFrameSize() != frame->natural_size();
509 return;
510 466
511 bool size_changed = !current_frame_.get() || 467 compositor_->EnqueueFrame(frame);
512 current_frame_->natural_size() != frame->natural_size();
513
514 {
515 base::AutoLock auto_lock(current_frame_lock_);
516 if (!current_frame_used_ && current_frame_.get())
517 ++dropped_frame_count_;
518 current_frame_ = frame;
519 current_time_ = frame->timestamp();
520 current_frame_used_ = false;
521 }
522 468
523 if (size_changed) 469 if (size_changed)
524 GetClient()->sizeChanged(); 470 GetClient()->sizeChanged();
525
526 GetClient()->repaint();
527 } 471 }
528 472
529 void WebMediaPlayerMS::RepaintInternal() { 473 void WebMediaPlayerMS::RepaintInternal() {
530 DVLOG(1) << "WebMediaPlayerMS::RepaintInternal"; 474 DVLOG(1) << "WebMediaPlayerMS::RepaintInternal";
531 DCHECK(thread_checker_.CalledOnValidThread()); 475 DCHECK(thread_checker_.CalledOnValidThread());
532 GetClient()->repaint(); 476 GetClient()->repaint();
533 } 477 }
534 478
535 void WebMediaPlayerMS::OnSourceError() { 479 void WebMediaPlayerMS::OnSourceError() {
536 DVLOG(1) << "WebMediaPlayerMS::OnSourceError"; 480 DVLOG(1) << "WebMediaPlayerMS::OnSourceError";
(...skipping 15 matching lines...) Expand all
552 // Always notify to ensure client has the latest value. 496 // Always notify to ensure client has the latest value.
553 GetClient()->readyStateChanged(); 497 GetClient()->readyStateChanged();
554 } 498 }
555 499
556 blink::WebMediaPlayerClient* WebMediaPlayerMS::GetClient() { 500 blink::WebMediaPlayerClient* WebMediaPlayerMS::GetClient() {
557 DCHECK(thread_checker_.CalledOnValidThread()); 501 DCHECK(thread_checker_.CalledOnValidThread());
558 DCHECK(client_); 502 DCHECK(client_);
559 return client_; 503 return client_;
560 } 504 }
561 505
506 WebMediaPlayerMS::Compositor::Compositor(
507 scoped_refptr<base::SingleThreadTaskRunner> const& compositor_thread)
508 : compositor_thread_(compositor_thread),
509 video_frame_provider_client_(NULL),
510 current_frame_used_(false),
511 total_frame_count_(0),
512 dropped_frame_count_(0),
513 paused_(false) {}
514
515 WebMediaPlayerMS::Compositor::~Compositor() {
516 DCHECK(compositor_thread_->BelongsToCurrentThread());
517 if (video_frame_provider_client_)
518 video_frame_provider_client_->StopUsingProvider();
519 }
520
521 void WebMediaPlayerMS::Compositor::EnqueueFrame(
522 scoped_refptr<media::VideoFrame> const& frame) {
523 base::AutoLock auto_lock(current_frame_lock_);
524 ++total_frame_count_;
525 if (!current_frame_used_)
526 ++dropped_frame_count_;
527
528 // When paused, do not update current_frame;
529 // TODO(qiangchen): After applying VRA, this check should move to
530 // UpdateCurrentFrame. During pause, we have to let frames go through VRA and
531 // then be thrown away, otherwise VRA will think there is a very long frame.
532 if (paused_)
533 return;
534
535 if (base::TimeTicks::Now() > last_deadline_max_) {
536 // TODO(qiangchen): This shows vsyncs stops rendering frames. A probable
537 // cause is that the tab is not in the front. But we still have to let
538 // old frames go. Call VRA::RemoveExpiredFrames.
539 }
540
541 // TODO(qiangchen): Instead of using one variable to hold one frame, use
542 // VideoRendererAlgorithm.
543 current_frame_ = frame;
544 current_frame_used_ = false;
545 current_time_ = frame->timestamp();
546 }
547
548 bool WebMediaPlayerMS::Compositor::UpdateCurrentFrame(
549 base::TimeTicks deadline_min,
550 base::TimeTicks deadline_max) {
551 DCHECK(compositor_thread_->BelongsToCurrentThread());
552 base::AutoLock auto_lock(current_frame_lock_);
553 TRACE_EVENT_BEGIN2("webrtc", "WebMediaPlayerMS::UpdateCurrentFrame",
554 "Actual Render Begin", deadline_min.ToInternalValue(),
555 "Actual Render End", deadline_max.ToInternalValue());
556 last_deadline_max_ = deadline_max;
557
558 // TODO(dalecurtis): This should make use of the deadline interval to ensure
559 // the painted frame is correct for the given interval.
560
561 base::TimeTicks render_time;
562 if (!current_frame_->metadata()->GetTimeTicks(
563 media::VideoFrameMetadata::REFERENCE_TIME, &render_time)) {
564 render_time = base::TimeTicks();
565 }
566 TRACE_EVENT_END1("webrtc", "WebMediaPlayerMS::UpdateCurrentFrame",
567 "Ideal Render Instant", render_time.ToInternalValue());
568 return !current_frame_used_;
569 }
570
571 bool WebMediaPlayerMS::Compositor::HasCurrentFrame() {
572 base::AutoLock auto_lock(current_frame_lock_);
573 return current_frame_;
DaleCurtis 2015/08/17 21:31:29 Might need !! to avoid compilation errors on windo
qiangchen 2015/08/18 01:21:49 Done.
574 }
575
576 scoped_refptr<media::VideoFrame>
577 WebMediaPlayerMS::Compositor::GetCurrentFrame() {
578 DVLOG(3) << "WebMediaPlayerMS::Compositor::GetCurrentFrame";
579 base::AutoLock auto_lock(current_frame_lock_);
580 if (!current_frame_.get())
DaleCurtis 2015/08/17 21:31:29 Conditional necessary? If current frame is null, d
qiangchen 2015/08/18 01:21:49 N/A
581 return NULL;
582 current_frame_used_ = true;
583 return current_frame_;
584 }
585
586 void WebMediaPlayerMS::Compositor::PutCurrentFrame() {
587 DVLOG(3) << "WebMediaPlayerMS::PutCurrentFrame";
588 }
589
590 void WebMediaPlayerMS::Compositor::SetVideoFrameProviderClient(
591 cc::VideoFrameProvider::Client* client) {
592 DCHECK(compositor_thread_->BelongsToCurrentThread());
593 if (video_frame_provider_client_)
594 video_frame_provider_client_->StopUsingProvider();
595
596 video_frame_provider_client_ = client;
597 if (video_frame_provider_client_)
598 video_frame_provider_client_->StartRendering();
599 }
600
601 void WebMediaPlayerMS::Compositor::StartRendering() {
602 DCHECK(compositor_thread_->BelongsToCurrentThread());
603 paused_ = false;
604 if (video_frame_provider_client_)
605 video_frame_provider_client_->StartRendering();
606 }
607
608 void WebMediaPlayerMS::Compositor::StopRendering() {
609 DCHECK(compositor_thread_->BelongsToCurrentThread());
610 paused_ = true;
611 if (video_frame_provider_client_)
612 video_frame_provider_client_->StopRendering();
613
614 base::AutoLock auto_lock(current_frame_lock_);
615 if (!current_frame_.get())
616 return;
617
618 // Copy the frame so that rendering can show the last received frame.
619 // The original frame must not be referenced when the player is paused since
620 // there might be a finite number of available buffers. E.g, video that
621 // originates from a video camera.
622 scoped_refptr<media::VideoFrame> new_frame =
623 CopyFrameToYV12(current_frame_, &video_renderer_);
624
625 current_frame_ = new_frame;
626 }
627
628 gfx::Size WebMediaPlayerMS::Compositor::CurrentFrameSize() {
629 base::AutoLock auto_lock(current_frame_lock_);
630 if (current_frame_.get())
DaleCurtis 2015/08/17 21:31:29 Ternary would be cleaner.
qiangchen 2015/08/18 01:21:49 Done.
631 return current_frame_->natural_size();
632 return gfx::Size();
633 }
634
635 base::TimeDelta WebMediaPlayerMS::Compositor::CurrentFrameTimestamp() {
636 return current_time_;
637 }
638
639 unsigned WebMediaPlayerMS::Compositor::TotalFrameCount() {
640 return total_frame_count_;
641 }
642
643 unsigned WebMediaPlayerMS::Compositor::DroppedFrameCount() {
644 return dropped_frame_count_;
645 }
646
647 scoped_refptr<media::VideoFrame> WebMediaPlayerMS::Compositor::CurrentFrame() {
648 base::AutoLock auto_lock(current_frame_lock_);
649 if (!current_frame_.get())
DaleCurtis 2015/08/17 21:31:29 Should just delete this method after switching to
qiangchen 2015/08/18 01:21:49 Done.
650 return NULL;
651 return current_frame_;
652 }
653
654 media::SkCanvasVideoRenderer* WebMediaPlayerMS::Compositor::VideoRenderer() {
655 return &video_renderer_;
656 }
562 } // namespace content 657 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698