Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/webrtc/webrtc_video_track_adapter.h" | 5 #include "content/renderer/media/webrtc/webrtc_video_track_adapter.h" |
| 6 | 6 |
| 7 #include "base/strings/utf_string_conversions.h" | 7 #include "base/strings/utf_string_conversions.h" |
| 8 #include "content/common/media/media_stream_options.h" | 8 #include "content/common/media/media_stream_options.h" |
| 9 #include "content/renderer/media/media_stream_video_source.h" | 9 #include "content/renderer/media/media_stream_video_source.h" |
| 10 #include "content/renderer/media/media_stream_video_track.h" | 10 #include "content/renderer/media/media_stream_video_track.h" |
| 11 | 11 |
| 12 namespace { | 12 namespace { |
| 13 | 13 |
| 14 bool ConstraintKeyExists(const blink::WebMediaConstraints& constraints, | 14 bool ConstraintKeyExists(const blink::WebMediaConstraints& constraints, |
| 15 const blink::WebString& name) { | 15 const blink::WebString& name) { |
| 16 blink::WebString value_str; | 16 blink::WebString value_str; |
| 17 return constraints.getMandatoryConstraintValue(name, value_str) || | 17 return constraints.getMandatoryConstraintValue(name, value_str) || |
| 18 constraints.getOptionalConstraintValue(name, value_str); | 18 constraints.getOptionalConstraintValue(name, value_str); |
| 19 } | 19 } |
| 20 | 20 |
| 21 // Used to make sure |source| is released on the main render thread. | |
| 22 void ReleaseWebRtcSourceOnMainRenderThread( | |
| 23 webrtc::VideoSourceInterface* source) { | |
| 24 source->Release(); | |
| 25 } | |
| 26 | |
| 21 } // anonymouse namespace | 27 } // anonymouse namespace |
| 22 | 28 |
| 23 namespace content { | 29 namespace content { |
| 24 | 30 |
| 25 // Simple help class used for receiving video frames on the IO-thread from | 31 // Simple help class used for receiving video frames on the IO-thread from |
| 26 // a MediaStreamVideoTrack and forward the frames to a | 32 // a MediaStreamVideoTrack and forward the frames to a |
| 27 // WebRtcVideoCapturerAdapter that implements a video capturer for libjingle. | 33 // WebRtcVideoCapturerAdapter that implements a video capturer for libjingle. |
| 28 class WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter | 34 class WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter |
| 29 : public base::RefCountedThreadSafe<WebRtcVideoSourceAdapter> { | 35 : public base::RefCountedThreadSafe<WebRtcVideoSourceAdapter> { |
| 30 public: | 36 public: |
| 31 WebRtcVideoSourceAdapter( | 37 WebRtcVideoSourceAdapter( |
| 38 const scoped_refptr<base::MessageLoopProxy>& libjingle_worker_thread, | |
| 32 const scoped_refptr<webrtc::VideoSourceInterface>& source, | 39 const scoped_refptr<webrtc::VideoSourceInterface>& source, |
| 33 WebRtcVideoCapturerAdapter* capture_adapter); | 40 WebRtcVideoCapturerAdapter* capture_adapter); |
| 34 | 41 |
| 35 void OnVideoFrameOnIO(const scoped_refptr<media::VideoFrame>& frame, | 42 void OnVideoFrameOnIO(const scoped_refptr<media::VideoFrame>& frame, |
| 36 const media::VideoCaptureFormat& format); | 43 const media::VideoCaptureFormat& format); |
| 37 | 44 |
| 38 private: | 45 private: |
| 46 void OnVideoFrameOnWt(const scoped_refptr<media::VideoFrame>& frame, | |
|
tommi (sloooow) - chröme
2014/05/12 14:20:41
OnVideoFrameOnWorkerThread
perkj_chrome
2014/05/12 15:39:51
Done.
| |
| 47 const media::VideoCaptureFormat& format); | |
| 39 friend class base::RefCountedThreadSafe<WebRtcVideoSourceAdapter>; | 48 friend class base::RefCountedThreadSafe<WebRtcVideoSourceAdapter>; |
| 40 virtual ~WebRtcVideoSourceAdapter(); | 49 virtual ~WebRtcVideoSourceAdapter(); |
| 41 | 50 |
| 51 scoped_refptr<base::MessageLoopProxy> render_thread_message_loop_; | |
| 52 | |
| 42 // Used to DCHECK that frames are called on the IO-thread. | 53 // Used to DCHECK that frames are called on the IO-thread. |
| 43 base::ThreadChecker io_thread_checker_; | 54 base::ThreadChecker io_thread_checker_; |
| 55 | |
| 56 // Used for posting frames to libjingles worker thread. Accessed on the | |
|
tommi (sloooow) - chröme
2014/05/12 14:20:41
libjingle's
perkj_chrome
2014/05/12 15:39:51
Done.
| |
| 57 // IO-thread. | |
| 58 scoped_refptr<base::MessageLoopProxy> libjingle_worker_thread_; | |
| 59 | |
| 44 scoped_refptr<webrtc::VideoSourceInterface> video_source_; | 60 scoped_refptr<webrtc::VideoSourceInterface> video_source_; |
| 45 // |capture_adapter_| is owned by |video_source_| | 61 // |capture_adapter_| is owned by |video_source_| |
| 46 WebRtcVideoCapturerAdapter* capture_adapter_; | 62 WebRtcVideoCapturerAdapter* capture_adapter_; |
| 47 }; | 63 }; |
| 48 | 64 |
| 49 WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::WebRtcVideoSourceAdapter( | 65 WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::WebRtcVideoSourceAdapter( |
| 66 const scoped_refptr<base::MessageLoopProxy>& libjingle_worker_thread, | |
| 50 const scoped_refptr<webrtc::VideoSourceInterface>& source, | 67 const scoped_refptr<webrtc::VideoSourceInterface>& source, |
| 51 WebRtcVideoCapturerAdapter* capture_adapter) | 68 WebRtcVideoCapturerAdapter* capture_adapter) |
| 52 : video_source_(source), | 69 : render_thread_message_loop_(base::MessageLoopProxy::current()), |
| 70 libjingle_worker_thread_(libjingle_worker_thread), | |
| 71 video_source_(source), | |
| 53 capture_adapter_(capture_adapter) { | 72 capture_adapter_(capture_adapter) { |
| 54 io_thread_checker_.DetachFromThread(); | 73 io_thread_checker_.DetachFromThread(); |
| 55 } | 74 } |
| 56 | 75 |
| 57 WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::~WebRtcVideoSourceAdapter() { | 76 WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::~WebRtcVideoSourceAdapter() { |
| 77 // Since frames are posted to the worker thread, this object might be deleted | |
| 78 // on that thread. However, since |video_source_| was created on the render | |
| 79 // thread, we should release our reference on the render thread. This is not | |
|
tommi (sloooow) - chröme
2014/05/12 14:20:41
nit: s/should/must
| |
| 80 // strictly necessary since both the main render thread and the worker thread | |
| 81 // implements libjingle's thread Send method. | |
|
tommi (sloooow) - chröme
2014/05/12 14:20:41
nit: implement
(no s)
After reading why this isn'
perkj_chrome
2014/05/12 15:39:51
ok- I removed the whole comment instead since we d
| |
| 82 if (!render_thread_message_loop_->BelongsToCurrentThread()) { | |
|
tommi (sloooow) - chröme
2014/05/12 14:20:41
I think that if at all possible to avoid this, we
perkj_chrome
2014/05/12 15:39:51
Suggestions? We have 3 - threads here. Render thre
| |
| 83 webrtc::VideoSourceInterface* source = video_source_.get(); | |
| 84 source->AddRef(); | |
| 85 video_source_ = NULL; | |
| 86 render_thread_message_loop_->PostTask( | |
| 87 FROM_HERE, | |
| 88 base::Bind(&ReleaseWebRtcSourceOnMainRenderThread, | |
| 89 base::Unretained(source))); | |
| 90 } | |
| 58 } | 91 } |
| 59 | 92 |
| 60 void WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::OnVideoFrameOnIO( | 93 void WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::OnVideoFrameOnIO( |
| 61 const scoped_refptr<media::VideoFrame>& frame, | 94 const scoped_refptr<media::VideoFrame>& frame, |
| 62 const media::VideoCaptureFormat& format) { | 95 const media::VideoCaptureFormat& format) { |
| 63 DCHECK(io_thread_checker_.CalledOnValidThread()); | 96 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 97 libjingle_worker_thread_->PostTask( | |
|
perkj_chrome
2014/05/12 15:39:51
This is what might cause WebRtcVideoTrackAdapter::
| |
| 98 FROM_HERE, | |
| 99 base::Bind(&WebRtcVideoSourceAdapter::OnVideoFrameOnWt, | |
| 100 this, frame, format)); | |
| 101 } | |
| 102 | |
| 103 void WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::OnVideoFrameOnWt( | |
| 104 const scoped_refptr<media::VideoFrame>& frame, | |
| 105 const media::VideoCaptureFormat& format) { | |
| 106 DCHECK(libjingle_worker_thread_->BelongsToCurrentThread()); | |
| 64 capture_adapter_->OnFrameCaptured(frame); | 107 capture_adapter_->OnFrameCaptured(frame); |
| 65 } | 108 } |
| 66 | 109 |
| 67 WebRtcVideoTrackAdapter::WebRtcVideoTrackAdapter( | 110 WebRtcVideoTrackAdapter::WebRtcVideoTrackAdapter( |
| 68 const blink::WebMediaStreamTrack& track, | 111 const blink::WebMediaStreamTrack& track, |
| 69 MediaStreamDependencyFactory* factory) | 112 MediaStreamDependencyFactory* factory) |
| 70 : web_track_(track) { | 113 : web_track_(track) { |
| 71 const blink::WebMediaConstraints& constraints = | 114 const blink::WebMediaConstraints& constraints = |
| 72 MediaStreamVideoTrack::GetVideoTrack(track)->constraints(); | 115 MediaStreamVideoTrack::GetVideoTrack(track)->constraints(); |
| 73 | 116 |
| 74 bool is_screencast = ConstraintKeyExists( | 117 bool is_screencast = ConstraintKeyExists( |
| 75 constraints, base::UTF8ToUTF16(kMediaStreamSource)); | 118 constraints, base::UTF8ToUTF16(kMediaStreamSource)); |
| 76 WebRtcVideoCapturerAdapter* capture_adapter = | 119 WebRtcVideoCapturerAdapter* capture_adapter = |
| 77 factory->CreateVideoCapturer(is_screencast); | 120 factory->CreateVideoCapturer(is_screencast); |
| 78 | 121 |
| 79 // |video_source| owns |capture_adapter| | 122 // |video_source| owns |capture_adapter| |
| 80 scoped_refptr<webrtc::VideoSourceInterface> video_source( | 123 scoped_refptr<webrtc::VideoSourceInterface> video_source( |
| 81 factory->CreateVideoSource(capture_adapter, | 124 factory->CreateVideoSource(capture_adapter, |
| 82 track.source().constraints())); | 125 track.source().constraints())); |
| 83 | 126 |
| 84 video_track_ = factory->CreateLocalVideoTrack(web_track_.id().utf8(), | 127 video_track_ = factory->CreateLocalVideoTrack(web_track_.id().utf8(), |
| 85 video_source.get()); | 128 video_source.get()); |
| 86 | 129 |
| 87 video_track_->set_enabled(web_track_.isEnabled()); | 130 video_track_->set_enabled(web_track_.isEnabled()); |
| 88 | 131 |
| 89 source_adapter_ = new WebRtcVideoSourceAdapter(video_source, | 132 source_adapter_ = new WebRtcVideoSourceAdapter( |
| 90 capture_adapter); | 133 factory->worker_thread_proxy(), |
| 134 video_source, | |
| 135 capture_adapter); | |
| 91 | 136 |
| 92 AddToVideoTrack( | 137 AddToVideoTrack( |
| 93 this, | 138 this, |
| 94 base::Bind(&WebRtcVideoSourceAdapter::OnVideoFrameOnIO, | 139 base::Bind(&WebRtcVideoSourceAdapter::OnVideoFrameOnIO, |
| 95 source_adapter_), | 140 source_adapter_), |
| 96 web_track_); | 141 web_track_); |
| 97 | 142 |
| 98 DVLOG(3) << "WebRtcVideoTrackAdapter ctor() : is_screencast " | 143 DVLOG(3) << "WebRtcVideoTrackAdapter ctor() : is_screencast " |
| 99 << is_screencast; | 144 << is_screencast; |
| 100 } | 145 } |
| 101 | 146 |
| 102 WebRtcVideoTrackAdapter::~WebRtcVideoTrackAdapter() { | 147 WebRtcVideoTrackAdapter::~WebRtcVideoTrackAdapter() { |
| 103 DCHECK(thread_checker_.CalledOnValidThread()); | 148 DCHECK(thread_checker_.CalledOnValidThread()); |
| 104 DVLOG(3) << "WebRtcVideoTrackAdapter dtor()."; | 149 DVLOG(3) << "WebRtcVideoTrackAdapter dtor()."; |
| 105 RemoveFromVideoTrack(this, web_track_); | 150 RemoveFromVideoTrack(this, web_track_); |
| 106 } | 151 } |
| 107 | 152 |
| 108 void WebRtcVideoTrackAdapter::OnEnabledChanged(bool enabled) { | 153 void WebRtcVideoTrackAdapter::OnEnabledChanged(bool enabled) { |
| 109 DCHECK(thread_checker_.CalledOnValidThread()); | 154 DCHECK(thread_checker_.CalledOnValidThread()); |
| 110 video_track_->set_enabled(enabled); | 155 video_track_->set_enabled(enabled); |
| 111 } | 156 } |
| 112 | 157 |
| 113 } // namespace content | 158 } // namespace content |
| OLD | NEW |