OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |