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