Commit f73e1ca0 authored by perkj@chromium.org's avatar perkj@chromium.org

Deliver video frames on libjingle worker thread to WebRtcVideoCapturerAdapter.

This change so that WebRtcVideoCapturerAdapter receives video frames on libjingle worker thread instead of the IO-thread.

BUG= 371711, 350111

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@270048 0039d316-1c4b-4281-b951-d872f2087c98
parent 18e80f7b
...@@ -601,6 +601,12 @@ void MediaStreamDependencyFactory::AddNativeAudioTrackToBlinkTrack( ...@@ -601,6 +601,12 @@ void MediaStreamDependencyFactory::AddNativeAudioTrackToBlinkTrack(
is_local_track)); is_local_track));
} }
scoped_refptr<base::MessageLoopProxy>
MediaStreamDependencyFactory::GetWebRtcWorkerThread() const {
DCHECK(CalledOnValidThread());
return chrome_worker_thread_.message_loop_proxy();
}
bool MediaStreamDependencyFactory::OnControlMessageReceived( bool MediaStreamDependencyFactory::OnControlMessageReceived(
const IPC::Message& message) { const IPC::Message& message) {
bool handled = true; bool handled = true;
......
...@@ -131,6 +131,8 @@ class CONTENT_EXPORT MediaStreamDependencyFactory ...@@ -131,6 +131,8 @@ class CONTENT_EXPORT MediaStreamDependencyFactory
const blink::WebMediaStreamTrack& webkit_track, const blink::WebMediaStreamTrack& webkit_track,
bool is_local_track); bool is_local_track);
scoped_refptr<base::MessageLoopProxy> GetWebRtcWorkerThread() const;
protected: protected:
// Asks the PeerConnection factory to create a Local Audio Source. // Asks the PeerConnection factory to create a Local Audio Source.
virtual scoped_refptr<webrtc::AudioSourceInterface> virtual scoped_refptr<webrtc::AudioSourceInterface>
......
...@@ -17,6 +17,7 @@ WebRtcVideoCapturerAdapter::WebRtcVideoCapturerAdapter(bool is_screencast) ...@@ -17,6 +17,7 @@ WebRtcVideoCapturerAdapter::WebRtcVideoCapturerAdapter(bool is_screencast)
running_(false), running_(false),
buffer_(NULL), buffer_(NULL),
buffer_size_(0) { buffer_size_(0) {
thread_checker_.DetachFromThread();
} }
WebRtcVideoCapturerAdapter::~WebRtcVideoCapturerAdapter() { WebRtcVideoCapturerAdapter::~WebRtcVideoCapturerAdapter() {
...@@ -26,6 +27,7 @@ WebRtcVideoCapturerAdapter::~WebRtcVideoCapturerAdapter() { ...@@ -26,6 +27,7 @@ WebRtcVideoCapturerAdapter::~WebRtcVideoCapturerAdapter() {
cricket::CaptureState WebRtcVideoCapturerAdapter::Start( cricket::CaptureState WebRtcVideoCapturerAdapter::Start(
const cricket::VideoFormat& capture_format) { const cricket::VideoFormat& capture_format) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!running_); DCHECK(!running_);
DVLOG(3) << " WebRtcVideoCapturerAdapter::Start w = " << capture_format.width DVLOG(3) << " WebRtcVideoCapturerAdapter::Start w = " << capture_format.width
<< " h = " << capture_format.height; << " h = " << capture_format.height;
...@@ -35,6 +37,7 @@ cricket::CaptureState WebRtcVideoCapturerAdapter::Start( ...@@ -35,6 +37,7 @@ cricket::CaptureState WebRtcVideoCapturerAdapter::Start(
} }
void WebRtcVideoCapturerAdapter::Stop() { void WebRtcVideoCapturerAdapter::Stop() {
DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(3) << " WebRtcVideoCapturerAdapter::Stop "; DVLOG(3) << " WebRtcVideoCapturerAdapter::Stop ";
DCHECK(running_); DCHECK(running_);
running_ = false; running_ = false;
...@@ -43,11 +46,13 @@ void WebRtcVideoCapturerAdapter::Stop() { ...@@ -43,11 +46,13 @@ void WebRtcVideoCapturerAdapter::Stop() {
} }
bool WebRtcVideoCapturerAdapter::IsRunning() { bool WebRtcVideoCapturerAdapter::IsRunning() {
DCHECK(thread_checker_.CalledOnValidThread());
return running_; return running_;
} }
bool WebRtcVideoCapturerAdapter::GetPreferredFourccs( bool WebRtcVideoCapturerAdapter::GetPreferredFourccs(
std::vector<uint32>* fourccs) { std::vector<uint32>* fourccs) {
DCHECK(thread_checker_.CalledOnValidThread());
if (!fourccs) if (!fourccs)
return false; return false;
fourccs->push_back(cricket::FOURCC_I420); fourccs->push_back(cricket::FOURCC_I420);
...@@ -61,6 +66,7 @@ bool WebRtcVideoCapturerAdapter::IsScreencast() const { ...@@ -61,6 +66,7 @@ bool WebRtcVideoCapturerAdapter::IsScreencast() const {
bool WebRtcVideoCapturerAdapter::GetBestCaptureFormat( bool WebRtcVideoCapturerAdapter::GetBestCaptureFormat(
const cricket::VideoFormat& desired, const cricket::VideoFormat& desired,
cricket::VideoFormat* best_format) { cricket::VideoFormat* best_format) {
DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(3) << " GetBestCaptureFormat:: " DVLOG(3) << " GetBestCaptureFormat:: "
<< " w = " << desired.width << " w = " << desired.width
<< " h = " << desired.height; << " h = " << desired.height;
...@@ -77,6 +83,7 @@ bool WebRtcVideoCapturerAdapter::GetBestCaptureFormat( ...@@ -77,6 +83,7 @@ bool WebRtcVideoCapturerAdapter::GetBestCaptureFormat(
void WebRtcVideoCapturerAdapter::OnFrameCaptured( void WebRtcVideoCapturerAdapter::OnFrameCaptured(
const scoped_refptr<media::VideoFrame>& frame) { const scoped_refptr<media::VideoFrame>& frame) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(media::VideoFrame::I420 == frame->format() || DCHECK(media::VideoFrame::I420 == frame->format() ||
media::VideoFrame::YV12 == frame->format()); media::VideoFrame::YV12 == frame->format());
if (first_frame_timestamp_ == media::kNoTimestamp()) if (first_frame_timestamp_ == media::kNoTimestamp())
...@@ -120,6 +127,7 @@ void WebRtcVideoCapturerAdapter::OnFrameCaptured( ...@@ -120,6 +127,7 @@ void WebRtcVideoCapturerAdapter::OnFrameCaptured(
void WebRtcVideoCapturerAdapter::UpdateI420Buffer( void WebRtcVideoCapturerAdapter::UpdateI420Buffer(
const scoped_refptr<media::VideoFrame>& src) { const scoped_refptr<media::VideoFrame>& src) {
DCHECK(thread_checker_.CalledOnValidThread());
const int src_width = src->coded_size().width(); const int src_width = src->coded_size().width();
const int src_height = src->coded_size().height(); const int src_height = src->coded_size().height();
const int dst_width = src->visible_rect().width(); const int dst_width = src->visible_rect().width();
......
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include <vector> #include <vector>
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/threading/thread_checker.h"
#include "content/common/content_export.h" #include "content/common/content_export.h"
#include "media/base/video_frame.h" #include "media/base/video_frame.h"
#include "media/video/capture/video_capture_types.h" #include "media/video/capture/video_capture_types.h"
...@@ -19,12 +21,18 @@ namespace content { ...@@ -19,12 +21,18 @@ namespace content {
// used for VideoCapturing in libJingle and especially in PeerConnections. // used for VideoCapturing in libJingle and especially in PeerConnections.
// The class is created and destroyed on the main render thread. // The class is created and destroyed on the main render thread.
// PeerConnection access cricket::VideoCapturer from a libJingle worker thread. // PeerConnection access cricket::VideoCapturer from a libJingle worker thread.
// An instance of WebRtcVideoCapturerAdapter is owned by an instance of
// webrtc::VideoSourceInterface in libJingle. The implementation of
// webrtc::VideoSourceInterface guarantees that this object is not deleted
// while it is still used in libJingle.
class CONTENT_EXPORT WebRtcVideoCapturerAdapter class CONTENT_EXPORT WebRtcVideoCapturerAdapter
: NON_EXPORTED_BASE(public cricket::VideoCapturer) { : NON_EXPORTED_BASE(public cricket::VideoCapturer) {
public: public:
explicit WebRtcVideoCapturerAdapter(bool is_screencast); explicit WebRtcVideoCapturerAdapter(bool is_screencast);
virtual ~WebRtcVideoCapturerAdapter(); virtual ~WebRtcVideoCapturerAdapter();
// OnFrameCaptured delivers video frames to libjingle. It must be called on
// libjingles worker thread.
// This method is virtual for testing purposes. // This method is virtual for testing purposes.
virtual void OnFrameCaptured(const scoped_refptr<media::VideoFrame>& frame); virtual void OnFrameCaptured(const scoped_refptr<media::VideoFrame>& frame);
...@@ -42,7 +50,9 @@ class CONTENT_EXPORT WebRtcVideoCapturerAdapter ...@@ -42,7 +50,9 @@ class CONTENT_EXPORT WebRtcVideoCapturerAdapter
void UpdateI420Buffer(const scoped_refptr<media::VideoFrame>& src); void UpdateI420Buffer(const scoped_refptr<media::VideoFrame>& src);
private: // |thread_checker_| is bound to the libjingle worker thread.
base::ThreadChecker thread_checker_;
const bool is_screencast_; const bool is_screencast_;
bool running_; bool running_;
base::TimeDelta first_frame_timestamp_; base::TimeDelta first_frame_timestamp_;
......
...@@ -18,17 +18,25 @@ bool ConstraintKeyExists(const blink::WebMediaConstraints& constraints, ...@@ -18,17 +18,25 @@ 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 {
// Simple help class used for receiving video frames on the IO-thread from // Simple help class used for receiving video frames on the IO-thread from
// a MediaStreamVideoTrack and forward the frames to a // a MediaStreamVideoTrack and forward the frames to a
// WebRtcVideoCapturerAdapter that implements a video capturer for libjingle. // WebRtcVideoCapturerAdapter on libjingle's worker thread.
// WebRtcVideoCapturerAdapter implements a video capturer for libjingle.
class WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter class WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter
: public base::RefCountedThreadSafe<WebRtcVideoSourceAdapter> { : public base::RefCountedThreadSafe<WebRtcVideoSourceAdapter> {
public: public:
WebRtcVideoSourceAdapter( WebRtcVideoSourceAdapter(
const scoped_refptr<base::MessageLoopProxy>& libjingle_worker_thread,
const scoped_refptr<webrtc::VideoSourceInterface>& source, const scoped_refptr<webrtc::VideoSourceInterface>& source,
WebRtcVideoCapturerAdapter* capture_adapter); WebRtcVideoCapturerAdapter* capture_adapter);
...@@ -36,31 +44,66 @@ class WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter ...@@ -36,31 +44,66 @@ class WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter
const media::VideoCaptureFormat& format); const media::VideoCaptureFormat& format);
private: private:
void OnVideoFrameOnWorkerThread(const scoped_refptr<media::VideoFrame>& frame,
const media::VideoCaptureFormat& format);
friend class base::RefCountedThreadSafe<WebRtcVideoSourceAdapter>; friend class base::RefCountedThreadSafe<WebRtcVideoSourceAdapter>;
virtual ~WebRtcVideoSourceAdapter(); virtual ~WebRtcVideoSourceAdapter();
scoped_refptr<base::MessageLoopProxy> render_thread_message_loop_;
// 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_;
// Used for posting frames to libjingle's worker thread. Accessed on the
// IO-thread.
scoped_refptr<base::MessageLoopProxy> libjingle_worker_thread_;
scoped_refptr<webrtc::VideoSourceInterface> video_source_; scoped_refptr<webrtc::VideoSourceInterface> video_source_;
// |capture_adapter_| is owned by |video_source_| // |capture_adapter_| is owned by |video_source_|
WebRtcVideoCapturerAdapter* capture_adapter_; WebRtcVideoCapturerAdapter* capture_adapter_;
}; };
WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::WebRtcVideoSourceAdapter( WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::WebRtcVideoSourceAdapter(
const scoped_refptr<base::MessageLoopProxy>& libjingle_worker_thread,
const scoped_refptr<webrtc::VideoSourceInterface>& source, const scoped_refptr<webrtc::VideoSourceInterface>& source,
WebRtcVideoCapturerAdapter* capture_adapter) WebRtcVideoCapturerAdapter* capture_adapter)
: video_source_(source), : render_thread_message_loop_(base::MessageLoopProxy::current()),
libjingle_worker_thread_(libjingle_worker_thread),
video_source_(source),
capture_adapter_(capture_adapter) { capture_adapter_(capture_adapter) {
io_thread_checker_.DetachFromThread(); io_thread_checker_.DetachFromThread();
} }
WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::~WebRtcVideoSourceAdapter() { WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::~WebRtcVideoSourceAdapter() {
// 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)));
}
} }
void WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::OnVideoFrameOnIO( void WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::OnVideoFrameOnIO(
const scoped_refptr<media::VideoFrame>& frame, const scoped_refptr<media::VideoFrame>& frame,
const media::VideoCaptureFormat& format) { const media::VideoCaptureFormat& format) {
DCHECK(io_thread_checker_.CalledOnValidThread()); DCHECK(io_thread_checker_.CalledOnValidThread());
libjingle_worker_thread_->PostTask(
FROM_HERE,
base::Bind(&WebRtcVideoSourceAdapter::OnVideoFrameOnWorkerThread,
this, frame, format));
}
void
WebRtcVideoTrackAdapter::WebRtcVideoSourceAdapter::OnVideoFrameOnWorkerThread(
const scoped_refptr<media::VideoFrame>& frame,
const media::VideoCaptureFormat& format) {
DCHECK(libjingle_worker_thread_->BelongsToCurrentThread());
capture_adapter_->OnFrameCaptured(frame); capture_adapter_->OnFrameCaptured(frame);
} }
...@@ -86,8 +129,10 @@ WebRtcVideoTrackAdapter::WebRtcVideoTrackAdapter( ...@@ -86,8 +129,10 @@ WebRtcVideoTrackAdapter::WebRtcVideoTrackAdapter(
video_track_->set_enabled(web_track_.isEnabled()); video_track_->set_enabled(web_track_.isEnabled());
source_adapter_ = new WebRtcVideoSourceAdapter(video_source, source_adapter_ = new WebRtcVideoSourceAdapter(
capture_adapter); factory->GetWebRtcWorkerThread(),
video_source,
capture_adapter);
AddToVideoTrack( AddToVideoTrack(
this, this,
......
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