Commit 2448e593 authored by perkj@chromium.org's avatar perkj@chromium.org

Make sure webrtc::VideoSource is released when WebRtcVideoTrackAdapter is destroyed.

This is to ensure that the webrtc::VideoSource is destroyed before the PeerConnectionFactory is destroyed in RenderThreadImpl::ShutDown.

COLLABORATOR=tommi@chromium.org
BUG=378179

Review URL: https://codereview.chromium.org/299313011

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@273869 0039d316-1c4b-4281-b951-d872f2087c98
parent a51e8bb6
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "content/renderer/media/webrtc/webrtc_video_track_adapter.h" #include "content/renderer/media/webrtc/webrtc_video_track_adapter.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/synchronization/lock.h"
#include "content/common/media/media_stream_options.h" #include "content/common/media/media_stream_options.h"
#include "content/renderer/media/media_stream_video_source.h" #include "content/renderer/media/media_stream_video_source.h"
#include "content/renderer/media/media_stream_video_track.h" #include "content/renderer/media/media_stream_video_track.h"
...@@ -18,12 +19,6 @@ bool ConstraintKeyExists(const blink::WebMediaConstraints& constraints, ...@@ -18,12 +19,6 @@ bool ConstraintKeyExists(const blink::WebMediaConstraints& constraints,
constraints.getOptionalConstraintValue(name, value_str); constraints.getOptionalConstraintValue(name, value_str);
} }
// Used to make sure |source| is released on the main render thread.
void ReleaseWebRtcSourceOnMainRenderThread(
webrtc::VideoSourceInterface* source) {
source->Release();
}
} // anonymouse namespace } // anonymouse namespace
namespace content { namespace content {
...@@ -40,6 +35,14 @@ class WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter ...@@ -40,6 +35,14 @@ class WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter
const scoped_refptr<webrtc::VideoSourceInterface>& source, const scoped_refptr<webrtc::VideoSourceInterface>& source,
WebRtcVideoCapturerAdapter* capture_adapter); WebRtcVideoCapturerAdapter* capture_adapter);
// WebRtcVideoTrackAdapter can be destroyed on the main render thread or
// libjingles worker thread since it posts video frames on that thread. But
// |video_source_| must be released on the main render thread before the
// PeerConnectionFactory has been destroyed. The only way to ensure that is
// to make sure |video_source_| is released when WebRtcVideoTrackAdapter() is
// destroyed.
void ReleaseSourceOnMainThread();
void OnVideoFrameOnIO(const scoped_refptr<media::VideoFrame>& frame, void OnVideoFrameOnIO(const scoped_refptr<media::VideoFrame>& frame,
const media::VideoCaptureFormat& format); const media::VideoCaptureFormat& format);
...@@ -51,6 +54,8 @@ class WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter ...@@ -51,6 +54,8 @@ class WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter
scoped_refptr<base::MessageLoopProxy> render_thread_message_loop_; scoped_refptr<base::MessageLoopProxy> render_thread_message_loop_;
// |render_thread_checker_| is bound to the main render thread.
base::ThreadChecker render_thread_checker_;
// Used to DCHECK that frames are called on the IO-thread. // Used to DCHECK that frames are called on the IO-thread.
base::ThreadChecker io_thread_checker_; base::ThreadChecker io_thread_checker_;
...@@ -59,6 +64,12 @@ class WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter ...@@ -59,6 +64,12 @@ class WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter
scoped_refptr<base::MessageLoopProxy> libjingle_worker_thread_; scoped_refptr<base::MessageLoopProxy> libjingle_worker_thread_;
scoped_refptr<webrtc::VideoSourceInterface> video_source_; scoped_refptr<webrtc::VideoSourceInterface> video_source_;
// Used to protect |capture_adapter_|. It is taken by libjingle's worker
// thread for each video frame that is delivered but only taken on the
// main render thread in ReleaseSourceOnMainThread() when
// the owning WebRtcVideoTrackAdapter is being destroyed.
base::Lock capture_adapter_stop_lock_;
// |capture_adapter_| is owned by |video_source_| // |capture_adapter_| is owned by |video_source_|
WebRtcVideoCapturerAdapter* capture_adapter_; WebRtcVideoCapturerAdapter* capture_adapter_;
}; };
...@@ -75,18 +86,26 @@ WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::WebRtcVideoSourceAdapter( ...@@ -75,18 +86,26 @@ WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::WebRtcVideoSourceAdapter(
} }
WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::~WebRtcVideoSourceAdapter() { WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::~WebRtcVideoSourceAdapter() {
DVLOG(3) << "~WebRtcVideoSourceAdapter()";
DCHECK(!capture_adapter_);
// This object can be destroyed on the main render thread or libjingles
// worker thread since it posts video frames on that thread. But
// |video_source_| must be released on the main render thread before the
// PeerConnectionFactory has been destroyed. The only way to ensure that is
// to make sure |video_source_| is released when WebRtcVideoTrackAdapter() is
// destroyed.
}
void WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::
ReleaseSourceOnMainThread() {
DCHECK(render_thread_checker_.CalledOnValidThread());
// Since frames are posted to the worker thread, this object might be deleted // Since frames are posted to the worker thread, this object might be deleted
// on that thread. However, since |video_source_| was created on the render // on that thread. However, since |video_source_| was created on the render
// thread, it should be released on the render thread. // thread, it should be released on the render thread.
if (!render_thread_message_loop_->BelongsToCurrentThread()) { base::AutoLock auto_lock(capture_adapter_stop_lock_);
webrtc::VideoSourceInterface* source = video_source_.get(); // |video_source| owns |capture_adapter_|.
source->AddRef(); capture_adapter_ = NULL;
video_source_ = NULL; video_source_ = NULL;
render_thread_message_loop_->PostTask(
FROM_HERE,
base::Bind(&ReleaseWebRtcSourceOnMainRenderThread,
base::Unretained(source)));
}
} }
void WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::OnVideoFrameOnIO( void WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::OnVideoFrameOnIO(
...@@ -104,7 +123,9 @@ WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::OnVideoFrameOnWorkerThread( ...@@ -104,7 +123,9 @@ WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::OnVideoFrameOnWorkerThread(
const scoped_refptr<media::VideoFrame>& frame, const scoped_refptr<media::VideoFrame>& frame,
const media::VideoCaptureFormat& format) { const media::VideoCaptureFormat& format) {
DCHECK(libjingle_worker_thread_->BelongsToCurrentThread()); DCHECK(libjingle_worker_thread_->BelongsToCurrentThread());
capture_adapter_->OnFrameCaptured(frame); base::AutoLock auto_lock(capture_adapter_stop_lock_);
if (capture_adapter_)
capture_adapter_->OnFrameCaptured(frame);
} }
WebRtcVideoTrackAdapter::WebRtcVideoTrackAdapter( WebRtcVideoTrackAdapter::WebRtcVideoTrackAdapter(
...@@ -148,6 +169,7 @@ WebRtcVideoTrackAdapter::~WebRtcVideoTrackAdapter() { ...@@ -148,6 +169,7 @@ WebRtcVideoTrackAdapter::~WebRtcVideoTrackAdapter() {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(3) << "WebRtcVideoTrackAdapter dtor()."; DVLOG(3) << "WebRtcVideoTrackAdapter dtor().";
RemoveFromVideoTrack(this, web_track_); RemoveFromVideoTrack(this, web_track_);
source_adapter_->ReleaseSourceOnMainThread();
} }
void WebRtcVideoTrackAdapter::OnEnabledChanged(bool enabled) { void WebRtcVideoTrackAdapter::OnEnabledChanged(bool enabled) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment