Index: content/renderer/media/webmediaplayer_ms.cc |
diff --git a/content/renderer/media/webmediaplayer_ms.cc b/content/renderer/media/webmediaplayer_ms.cc |
index 80bd723099090ab737278b2bbc21ffd751554805..96aff406716c6b4f2997a14f674d3103e84f58fd 100644 |
--- a/content/renderer/media/webmediaplayer_ms.cc |
+++ b/content/renderer/media/webmediaplayer_ms.cc |
@@ -12,6 +12,7 @@ |
#include "base/metrics/histogram.h" |
#include "cc/blink/context_provider_web_context.h" |
#include "cc/blink/web_layer_impl.h" |
+#include "cc/layers/video_frame_provider_client_impl.h" |
#include "cc/layers/video_layer.h" |
#include "content/public/renderer/media_stream_audio_renderer.h" |
#include "content/public/renderer/media_stream_renderer_factory.h" |
@@ -93,7 +94,8 @@ WebMediaPlayerMS::WebMediaPlayerMS( |
blink::WebMediaPlayerClient* client, |
base::WeakPtr<media::WebMediaPlayerDelegate> delegate, |
media::MediaLog* media_log, |
- scoped_ptr<MediaStreamRendererFactory> factory) |
+ scoped_ptr<MediaStreamRendererFactory> factory, |
+ scoped_refptr<base::SingleThreadTaskRunner> compositor_thread) |
: frame_(frame), |
network_state_(WebMediaPlayer::NetworkStateEmpty), |
ready_state_(WebMediaPlayer::ReadyStateHaveNothing), |
@@ -108,7 +110,9 @@ WebMediaPlayerMS::WebMediaPlayerMS( |
total_frame_count_(0), |
dropped_frame_count_(0), |
media_log_(media_log), |
- renderer_factory_(factory.Pass()) { |
+ renderer_factory_(factory.Pass()), |
+ compositor_thread_(compositor_thread), |
+ wait_event_(false,false) { |
DVLOG(1) << "WebMediaPlayerMS::ctor"; |
media_log_->AddEvent( |
media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_CREATED)); |
@@ -118,7 +122,20 @@ WebMediaPlayerMS::~WebMediaPlayerMS() { |
DVLOG(1) << "WebMediaPlayerMS::dtor"; |
DCHECK(thread_checker_.CalledOnValidThread()); |
- SetVideoFrameProviderClient(NULL); |
+ // Wait till stop procedure finishes to avoid the case that after |
+ // WebMediaPlayerMS is destroyed, VideoFrameProvider is still trying to access |
+ // it. |
+ |
+ if (video_frame_provider_client_){ |
+ compositor_thread_->PostTask( |
+ FROM_HERE, |
+ base::Bind( |
+ &WebMediaPlayerMS::StopVideoFrameProviderAndWakeUpHelper, |
+ video_frame_provider_client_, |
+ &wait_event_)); |
+ wait_event_.Wait(); |
DaleCurtis
2015/08/13 18:06:53
Hmm, this is unfortunate. Typically you'd use Comp
qiangchen
2015/08/14 16:52:50
Done.
|
+ } |
+ |
GetClient()->setWebLayer(NULL); |
if (video_frame_provider_.get()) |
@@ -187,6 +204,13 @@ void WebMediaPlayerMS::play() { |
if (video_frame_provider_.get()) |
video_frame_provider_->Play(); |
+ if (video_frame_provider_client_){ |
+ compositor_thread_->PostTask( |
+ FROM_HERE, |
+ base::Bind(&WebMediaPlayerMS::StartRenderingHelper, |
+ video_frame_provider_client_)); |
+ } |
+ |
if (audio_renderer_.get()) |
audio_renderer_->Play(); |
@@ -206,6 +230,13 @@ void WebMediaPlayerMS::pause() { |
if (video_frame_provider_.get()) |
video_frame_provider_->Pause(); |
+ if (video_frame_provider_client_){ |
+ compositor_thread_->PostTask( |
+ FROM_HERE, |
+ base::Bind(&WebMediaPlayerMS::StopRenderingHelper, |
+ video_frame_provider_client_)); |
+ } |
+ |
if (!paused_) { |
if (audio_renderer_.get()) |
audio_renderer_->Pause(); |
@@ -449,16 +480,60 @@ void WebMediaPlayerMS::SetVideoFrameProviderClient( |
// This is called from both the main renderer thread and the compositor |
// thread (when the main thread is blocked). |
if (video_frame_provider_client_) |
- video_frame_provider_client_->StopUsingProvider(); |
+ compositor_thread_->PostTask( |
+ FROM_HERE, |
+ base::Bind( |
+ &WebMediaPlayerMS::StopVideoFrameProviderHelper, |
+ video_frame_provider_client_)); |
+ |
video_frame_provider_client_ = client; |
+ if (client && !paused_) |
+ compositor_thread_->PostTask( |
+ FROM_HERE, |
+ base::Bind(&WebMediaPlayerMS::StartRenderingHelper, |
+ video_frame_provider_client_)); |
+} |
+ |
+void WebMediaPlayerMS::StopVideoFrameProviderAndWakeUpHelper( |
+ cc::VideoFrameProvider::Client* client, |
+ base::WaitableEvent* event) { |
+ client->StopUsingProvider(); |
+ event->Signal(); |
+} |
+ |
+void WebMediaPlayerMS::StopVideoFrameProviderHelper( |
+ cc::VideoFrameProvider::Client* client) { |
+ client->StopUsingProvider(); |
+} |
+ |
+void WebMediaPlayerMS::StartRenderingHelper( |
+ cc::VideoFrameProvider::Client* client) { |
+ client->StartRendering(); |
+} |
+ |
+void WebMediaPlayerMS::StopRenderingHelper( |
+ cc::VideoFrameProvider::Client* client) { |
+ client->StopRendering(); |
} |
bool WebMediaPlayerMS::UpdateCurrentFrame(base::TimeTicks deadline_min, |
base::TimeTicks deadline_max) { |
+ TRACE_EVENT_BEGIN2("webrtc", "WebMediaPlayerMS::UpdateCurrentFrame", |
+ "Actual Render Begin", deadline_min.ToInternalValue(), |
+ "Actual Render End", deadline_max.ToInternalValue()); |
+ last_deadline_max_ = deadline_max; |
+ |
// TODO(dalecurtis): This should make use of the deadline interval to ensure |
// the painted frame is correct for the given interval. |
- NOTREACHED(); |
- return false; |
+ |
+ base::TimeTicks render_time; |
+ if (!current_frame_->metadata()->GetTimeTicks( |
+ media::VideoFrameMetadata::REFERENCE_TIME, &render_time)) { |
+ render_time = base::TimeTicks(); |
+ } |
+ TRACE_EVENT_END1("webrtc", "WebMediaPlayerMS::UpdateCurrentFrame", |
+ "Ideal Render Instant", render_time.ToInternalValue()); |
+ return !current_frame_used_; |
} |
bool WebMediaPlayerMS::HasCurrentFrame() { |
@@ -483,6 +558,15 @@ void WebMediaPlayerMS::OnFrameAvailable( |
const scoped_refptr<media::VideoFrame>& frame) { |
DVLOG(3) << "WebMediaPlayerMS::OnFrameAvailable"; |
DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ base::TimeTicks render_time; |
+ if (!frame->metadata()->GetTimeTicks( |
+ media::VideoFrameMetadata::REFERENCE_TIME, &render_time)) { |
+ render_time = base::TimeTicks(); |
+ } |
+ TRACE_EVENT1("webrtc", "WebMediaPlayerMS::OnFrameAvailable", |
+ "Ideal Render Instant", render_time.ToInternalValue()); |
+ |
++total_frame_count_; |
if (!received_first_frame_) { |
received_first_frame_ = true; |
@@ -508,6 +592,16 @@ void WebMediaPlayerMS::OnFrameAvailable( |
if (paused_) |
return; |
+ if (base::TimeTicks::Now() > last_deadline_max_){ |
+ // TODO(qiangchen): Theoretically Now is between |
+ // [last_deadline_min_ - vsync_duration, last_deadline_min]. If Now is later |
+ // than last_deadline_max, it means UpdateCurrentFrame does not get called |
+ // for 2 vsyncs. A probable cause is that the video tag is invisible, but we |
+ // have to let old frames go (VRA::RemoveExpiredFrames), otherwise frames |
+ // will pile up, and when we use up all frame buffers, decoder will be |
+ // stuck. |
+ } |
+ |
bool size_changed = !current_frame_.get() || |
current_frame_->natural_size() != frame->natural_size(); |
@@ -522,8 +616,6 @@ void WebMediaPlayerMS::OnFrameAvailable( |
if (size_changed) |
GetClient()->sizeChanged(); |
- |
- GetClient()->repaint(); |
} |
void WebMediaPlayerMS::RepaintInternal() { |