Index: content/renderer/media/webrtc/webrtc_video_track_adapter.cc |
diff --git a/content/renderer/media/webrtc/webrtc_video_track_adapter.cc b/content/renderer/media/webrtc/webrtc_video_track_adapter.cc |
index 810f8bad7e5ea650ba793ff20b0ed75917623279..1d9920f1b205f3f680d6b5fe8b671ce2c7566586 100644 |
--- a/content/renderer/media/webrtc/webrtc_video_track_adapter.cc |
+++ b/content/renderer/media/webrtc/webrtc_video_track_adapter.cc |
@@ -5,6 +5,7 @@ |
#include "content/renderer/media/webrtc/webrtc_video_track_adapter.h" |
#include "base/strings/utf_string_conversions.h" |
+#include "base/synchronization/lock.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_track.h" |
@@ -18,12 +19,6 @@ bool ConstraintKeyExists(const blink::WebMediaConstraints& constraints, |
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 |
namespace content { |
@@ -40,6 +35,14 @@ class WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter |
const scoped_refptr<webrtc::VideoSourceInterface>& source, |
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, |
const media::VideoCaptureFormat& format); |
@@ -51,6 +54,8 @@ class WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter |
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. |
base::ThreadChecker io_thread_checker_; |
@@ -59,6 +64,12 @@ class WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter |
scoped_refptr<base::MessageLoopProxy> libjingle_worker_thread_; |
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_| |
WebRtcVideoCapturerAdapter* capture_adapter_; |
}; |
@@ -75,18 +86,26 @@ 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 |
// on that thread. However, since |video_source_| was created on the render |
// thread, it should be released on the render thread. |
- if (!render_thread_message_loop_->BelongsToCurrentThread()) { |
- webrtc::VideoSourceInterface* source = video_source_.get(); |
- source->AddRef(); |
- video_source_ = NULL; |
- render_thread_message_loop_->PostTask( |
- FROM_HERE, |
- base::Bind(&ReleaseWebRtcSourceOnMainRenderThread, |
- base::Unretained(source))); |
- } |
+ base::AutoLock auto_lock(capture_adapter_stop_lock_); |
+ // |video_source| owns |capture_adapter_|. |
+ capture_adapter_ = NULL; |
+ video_source_ = NULL; |
} |
void WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::OnVideoFrameOnIO( |
@@ -104,7 +123,9 @@ WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::OnVideoFrameOnWorkerThread( |
const scoped_refptr<media::VideoFrame>& frame, |
const media::VideoCaptureFormat& format) { |
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( |
@@ -148,6 +169,7 @@ WebRtcVideoTrackAdapter::~WebRtcVideoTrackAdapter() { |
DCHECK(thread_checker_.CalledOnValidThread()); |
DVLOG(3) << "WebRtcVideoTrackAdapter dtor()."; |
RemoveFromVideoTrack(this, web_track_); |
+ source_adapter_->ReleaseSourceOnMainThread(); |
} |
void WebRtcVideoTrackAdapter::OnEnabledChanged(bool enabled) { |