summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-10 19:18:42 +0000
committerhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-10 19:18:42 +0000
commit7a4f405ceecdb788fa22fd8bea1c5738c32d278d (patch)
tree11e921401a9357c7da5115aa03633c57214bb65a
parente80ccef9d9946368d44463eda0bf49e4fa1279a1 (diff)
downloadchromium_src-7a4f405ceecdb788fa22fd8bea1c5738c32d278d.zip
chromium_src-7a4f405ceecdb788fa22fd8bea1c5738c32d278d.tar.gz
chromium_src-7a4f405ceecdb788fa22fd8bea1c5738c32d278d.tar.bz2
Cast: deliver video frames on the IO thread
This is the last change to deliver video frames to Cast streaming API on the IO thread. It will no longer be blocked by Javascript events. This needs a change in the MediaStreamVideoSink interface. Also getting rid of the interface of MediaStreamVideoTrack that delivers frames on the render thread. All clients now handle the thread hopping directly. BUG=335327, 371775 Review URL: https://codereview.chromium.org/264363005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@269616 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/renderer/media/cast_rtp_stream.cc54
-rw-r--r--content/public/renderer/media_stream_video_sink.cc3
-rw-r--r--content/public/renderer/media_stream_video_sink.h16
-rw-r--r--content/renderer/media/media_stream_impl_unittest.cc2
-rw-r--r--content/renderer/media/media_stream_video_source_unittest.cc7
-rw-r--r--content/renderer/media/media_stream_video_track.cc49
-rw-r--r--content/renderer/media/media_stream_video_track.h29
-rw-r--r--content/renderer/media/media_stream_video_track_unittest.cc64
-rw-r--r--content/renderer/media/mock_media_stream_video_sink.cc18
-rw-r--r--content/renderer/media/mock_media_stream_video_sink.h15
-rw-r--r--content/renderer/media/rtc_peer_connection_handler_unittest.cc1
-rw-r--r--content/renderer/media/rtc_video_renderer.cc18
-rw-r--r--content/renderer/media/rtc_video_renderer.h8
-rw-r--r--content/renderer/media/video_frame_deliverer.cc21
-rw-r--r--content/renderer/media/video_frame_deliverer.h8
-rw-r--r--content/renderer/media/video_source_handler.cc59
-rw-r--r--content/renderer/media/video_source_handler.h14
-rw-r--r--content/renderer/media/video_source_handler_unittest.cc7
-rw-r--r--content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc8
-rw-r--r--content/renderer/media/webrtc/video_destination_handler_unittest.cc24
-rw-r--r--content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc2
-rw-r--r--content/renderer/media/webrtc/webrtc_video_track_adapter.cc11
-rw-r--r--content/renderer/media/webrtc/webrtc_video_track_adapter.h4
-rw-r--r--content/renderer/pepper/pepper_media_stream_video_track_host.cc25
-rw-r--r--content/renderer/pepper/pepper_media_stream_video_track_host.h8
25 files changed, 313 insertions, 162 deletions
diff --git a/chrome/renderer/media/cast_rtp_stream.cc b/chrome/renderer/media/cast_rtp_stream.cc
index 5557582..31dd2a7 100644
--- a/chrome/renderer/media/cast_rtp_stream.cc
+++ b/chrome/renderer/media/cast_rtp_stream.cc
@@ -200,9 +200,11 @@ bool ToVideoSenderConfig(const CastRtpParams& params,
} // namespace
// This class receives MediaStreamTrack events and video frames from a
-// MediaStreamTrack. Video frames are submitted to media::cast::FrameInput.
+// MediaStreamTrack.
//
-// Threading: Video frames are received on the render thread.
+// Threading: Video frames are received on the IO thread and then
+// forwarded to media::cast::VideoFrameInput through a static method.
+// Member variables of this class are only accessed on the render thread.
class CastVideoSink : public base::SupportsWeakPtr<CastVideoSink>,
public content::MediaStreamVideoSink {
public:
@@ -222,11 +224,17 @@ class CastVideoSink : public base::SupportsWeakPtr<CastVideoSink>,
RemoveFromVideoTrack(this, track_);
}
- // content::MediaStreamVideoSink implementation.
- virtual void OnVideoFrame(const scoped_refptr<media::VideoFrame>& frame)
- OVERRIDE {
- if (frame->coded_size() != expected_coded_size_) {
- error_callback_.Run("Video frame resolution does not match config.");
+ // This static method is used to forward video frames to |frame_input|.
+ static void OnVideoFrame(
+ // These parameters are already bound when callback is created.
+ const gfx::Size& expected_coded_size,
+ const CastRtpStream::ErrorCallback& error_callback,
+ const scoped_refptr<media::cast::VideoFrameInput> frame_input,
+ // These parameters are passed for each frame.
+ const scoped_refptr<media::VideoFrame>& frame,
+ const media::VideoCaptureFormat& format) {
+ if (frame->coded_size() != expected_coded_size) {
+ error_callback.Run("Video frame resolution does not match config.");
return;
}
@@ -234,11 +242,11 @@ class CastVideoSink : public base::SupportsWeakPtr<CastVideoSink>,
// Used by chrome/browser/extension/api/cast_streaming/performance_test.cc
TRACE_EVENT_INSTANT2(
- "mirroring", "MediaStreamVideoSink::OnVideoFrame",
+ "cast_perf_test", "MediaStreamVideoSink::OnVideoFrame",
TRACE_EVENT_SCOPE_THREAD,
"timestamp", now.ToInternalValue(),
"time_delta", frame->timestamp().ToInternalValue());
- frame_input_->InsertRawVideoFrame(frame, now);
+ frame_input->InsertRawVideoFrame(frame, now);
}
// Attach this sink to a video track represented by |track_|.
@@ -247,14 +255,18 @@ class CastVideoSink : public base::SupportsWeakPtr<CastVideoSink>,
const scoped_refptr<media::cast::VideoFrameInput>& frame_input) {
DCHECK(!sink_added_);
sink_added_ = true;
-
- frame_input_ = frame_input;
- AddToVideoTrack(this, track_);
+ AddToVideoTrack(
+ this,
+ base::Bind(
+ &CastVideoSink::OnVideoFrame,
+ expected_coded_size_,
+ error_callback_,
+ frame_input),
+ track_);
}
private:
blink::WebMediaStreamTrack track_;
- scoped_refptr<media::cast::VideoFrameInput> frame_input_;
bool sink_added_;
gfx::Size expected_coded_size_;
CastRtpStream::ErrorCallback error_callback_;
@@ -266,6 +278,8 @@ class CastVideoSink : public base::SupportsWeakPtr<CastVideoSink>,
// media::cast::FrameInput.
//
// Threading: Audio frames are received on the real-time audio thread.
+// Note that RemoveFromAudioTrack() is synchronous and we have
+// gurantee that there will be no more audio data after calling it.
class CastAudioSink : public base::SupportsWeakPtr<CastAudioSink>,
public content::MediaStreamAudioSink {
public:
@@ -279,9 +293,9 @@ class CastAudioSink : public base::SupportsWeakPtr<CastAudioSink>,
sink_added_(false),
error_callback_(error_callback),
weak_factory_(this),
- input_preroll_(0),
output_channels_(output_channels),
- output_sample_rate_(output_sample_rate) {}
+ output_sample_rate_(output_sample_rate),
+ input_preroll_(0) {}
virtual ~CastAudioSink() {
if (sink_added_)
@@ -389,15 +403,15 @@ class CastAudioSink : public base::SupportsWeakPtr<CastAudioSink>,
CastRtpStream::ErrorCallback error_callback_;
base::WeakPtrFactory<CastAudioSink> weak_factory_;
- scoped_ptr<media::MultiChannelResampler> resampler_;
- scoped_ptr<media::AudioFifo> fifo_;
- scoped_ptr<media::AudioBus> fifo_input_bus_;
- int input_preroll_;
const int output_channels_;
const int output_sample_rate_;
- // This member is accessed on the real-time audio time.
+ // These member are accessed on the real-time audio time only.
scoped_refptr<media::cast::AudioFrameInput> frame_input_;
+ scoped_ptr<media::MultiChannelResampler> resampler_;
+ scoped_ptr<media::AudioFifo> fifo_;
+ scoped_ptr<media::AudioBus> fifo_input_bus_;
+ int input_preroll_;
DISALLOW_COPY_AND_ASSIGN(CastAudioSink);
};
diff --git a/content/public/renderer/media_stream_video_sink.cc b/content/public/renderer/media_stream_video_sink.cc
index c658036..af874e2 100644
--- a/content/public/renderer/media_stream_video_sink.cc
+++ b/content/public/renderer/media_stream_video_sink.cc
@@ -12,11 +12,12 @@ namespace content {
void MediaStreamVideoSink::AddToVideoTrack(
MediaStreamVideoSink* sink,
+ const VideoSinkDeliverFrameCB& callback,
const blink::WebMediaStreamTrack& track) {
DCHECK_EQ(blink::WebMediaStreamSource::TypeVideo, track.source().type());
MediaStreamVideoTrack* video_track =
static_cast<MediaStreamVideoTrack*>(track.extraData());
- video_track->AddSink(sink);
+ video_track->AddSink(sink, callback);
}
void MediaStreamVideoSink::RemoveFromVideoTrack(
diff --git a/content/public/renderer/media_stream_video_sink.h b/content/public/renderer/media_stream_video_sink.h
index 48a3719..663f3a8 100644
--- a/content/public/renderer/media_stream_video_sink.h
+++ b/content/public/renderer/media_stream_video_sink.h
@@ -5,12 +5,14 @@
#ifndef CONTENT_PUBLIC_RENDERER_MEDIA_STREAM_VIDEO_SINK_H_
#define CONTENT_PUBLIC_RENDERER_MEDIA_STREAM_VIDEO_SINK_H_
+#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
#include "content/public/renderer/media_stream_sink.h"
namespace media {
+class VideoCaptureFormat;
class VideoFrame;
}
@@ -20,6 +22,11 @@ class WebMediaStreamTrack;
namespace content {
+typedef base::Callback<
+ void(const scoped_refptr<media::VideoFrame>&,
+ const media::VideoCaptureFormat&)>
+ VideoSinkDeliverFrameCB;
+
// MediaStreamVideoSink is an interface used for receiving video frames from a
// Video Stream Track or a Video Source.
// http://dev.w3.org/2011/webrtc/editor/getusermedia.html
@@ -29,14 +36,19 @@ class CONTENT_EXPORT MediaStreamVideoSink : public MediaStreamSink {
// An implementation of MediaStreamVideoSink should call AddToVideoTrack when
// it is ready to receive data from a video track. Before the implementation
// is destroyed, RemoveFromVideoTrack must be called.
+ //
// Calls to these methods must be done on the main render thread.
+ // Note that |callback| for frame delivery happens on the IO thread.
+ //
+ // Calling RemoveFromVideoTrack also not stop frame delivery through the
+ // callback immediately because it may happen on another thread.
+ // The added callback will be reset on the render thread.
static void AddToVideoTrack(MediaStreamVideoSink* sink,
+ const VideoSinkDeliverFrameCB& callback,
const blink::WebMediaStreamTrack& track);
static void RemoveFromVideoTrack(MediaStreamVideoSink* sink,
const blink::WebMediaStreamTrack& track);
- virtual void OnVideoFrame(const scoped_refptr<media::VideoFrame>& frame) = 0;
-
protected:
virtual ~MediaStreamVideoSink() {}
};
diff --git a/content/renderer/media/media_stream_impl_unittest.cc b/content/renderer/media/media_stream_impl_unittest.cc
index 2d15fb1..3404ede 100644
--- a/content/renderer/media/media_stream_impl_unittest.cc
+++ b/content/renderer/media/media_stream_impl_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "content/child/child_process.h"
#include "content/renderer/media/media_stream.h"
@@ -167,6 +168,7 @@ class MediaStreamImplTest : public ::testing::Test {
}
protected:
+ base::MessageLoop message_loop_;
scoped_ptr<ChildProcess> child_process_;
scoped_ptr<MockMediaStreamDispatcher> ms_dispatcher_;
scoped_ptr<MediaStreamImplUnderTest> ms_impl_;
diff --git a/content/renderer/media/media_stream_video_source_unittest.cc b/content/renderer/media/media_stream_video_source_unittest.cc
index 1b1f204..d580dd5 100644
--- a/content/renderer/media/media_stream_video_source_unittest.cc
+++ b/content/renderer/media/media_stream_video_source_unittest.cc
@@ -107,8 +107,8 @@ class MediaStreamVideoSourceTest
30);
MockMediaStreamVideoSink sink;
- MediaStreamVideoSink::AddToVideoTrack(&sink, track);
-
+ MediaStreamVideoSink::AddToVideoTrack(
+ &sink, sink.GetDeliverFrameCB(), track);
DeliverVideoFrameAndWaitForRenderer(capture_width, capture_height, &sink);
EXPECT_EQ(1, sink.number_of_frames());
@@ -429,7 +429,8 @@ TEST_F(MediaStreamVideoSourceTest, SourceChangeFrameSize) {
640, 480, 30);
MockMediaStreamVideoSink sink;
- MediaStreamVideoSink::AddToVideoTrack(&sink, track);
+ MediaStreamVideoSink::AddToVideoTrack(
+ &sink, sink.GetDeliverFrameCB(), track);
EXPECT_EQ(0, sink.number_of_frames());
DeliverVideoFrameAndWaitForRenderer(320, 240, &sink);
EXPECT_EQ(1, sink.number_of_frames());
diff --git a/content/renderer/media/media_stream_video_track.cc b/content/renderer/media/media_stream_video_track.cc
index 577c7dc..32c19c9 100644
--- a/content/renderer/media/media_stream_video_track.cc
+++ b/content/renderer/media/media_stream_video_track.cc
@@ -11,7 +11,7 @@
namespace content {
// Helper class used for delivering video frames to MediaStreamSinks on the
-// IO-thread and MediaStreamVideoSinks on the main render thread.
+// IO-thread.
// Frames are delivered to an instance of this class from a
// MediaStreamVideoSource on the IO-thread to the method DeliverFrameOnIO.
// Frames are only delivered to the sinks if the track is enabled.
@@ -24,19 +24,14 @@ class MediaStreamVideoTrack::FrameDeliverer : public VideoFrameDeliverer {
enabled_(enabled) {
}
- // Add |sink| to receive frames and state changes on the main render thread.
- void AddSink(MediaStreamVideoSink* sink) {
+ // Add |sink| to receive state changes on the main render thread.
+ // Video frames will be delivered to |callback| on the IO thread.
+ void AddSink(MediaStreamVideoSink* sink,
+ const VideoCaptureDeliverFrameCB& callback) {
DCHECK(thread_checker().CalledOnValidThread());
DCHECK(std::find(sinks_.begin(), sinks_.end(), sink) == sinks_.end());
- if (sinks_.empty()) {
- VideoCaptureDeliverFrameCB frame_callback = media::BindToCurrentLoop(
- base::Bind(
- &MediaStreamVideoTrack::FrameDeliverer::OnVideoFrameOnMainThread,
- this));
- AddCallback(this, frame_callback);
- }
-
sinks_.push_back(sink);
+ AddCallback(sink, callback);
}
void RemoveSink(MediaStreamVideoSink* sink) {
@@ -45,21 +40,7 @@ class MediaStreamVideoTrack::FrameDeliverer : public VideoFrameDeliverer {
std::find(sinks_.begin(), sinks_.end(), sink);
DCHECK(it != sinks_.end());
sinks_.erase(it);
- if (sinks_.empty()) {
- RemoveCallback(this);
- }
- }
-
- // Called when a video frame is received on the main render thread.
- // It delivers the received frames to the registered MediaStreamVideo sinks.
- void OnVideoFrameOnMainThread(
- const scoped_refptr<media::VideoFrame>& frame,
- const media::VideoCaptureFormat& format) {
- DCHECK(thread_checker().CalledOnValidThread());
- for (std::vector<MediaStreamVideoSink*>::iterator it = sinks_.begin();
- it != sinks_.end(); ++it) {
- (*it)->OnVideoFrame(frame);
- }
+ RemoveCallback(sink);
}
void SetEnabled(bool enabled) {
@@ -145,9 +126,10 @@ MediaStreamVideoTrack::~MediaStreamVideoTrack() {
DVLOG(3) << "~MediaStreamVideoTrack()";
}
-void MediaStreamVideoTrack::AddSink(MediaStreamVideoSink* sink) {
+void MediaStreamVideoTrack::AddSink(
+ MediaStreamVideoSink* sink, const VideoCaptureDeliverFrameCB& callback) {
DCHECK(thread_checker_.CalledOnValidThread());
- frame_deliverer_->AddSink(sink);
+ frame_deliverer_->AddSink(sink, callback);
}
void MediaStreamVideoTrack::RemoveSink(MediaStreamVideoSink* sink) {
@@ -155,17 +137,6 @@ void MediaStreamVideoTrack::RemoveSink(MediaStreamVideoSink* sink) {
frame_deliverer_->RemoveSink(sink);
}
-void MediaStreamVideoTrack::AddSink(
- MediaStreamSink* sink, const VideoCaptureDeliverFrameCB& callback) {
- DCHECK(thread_checker_.CalledOnValidThread());
- frame_deliverer_->AddCallback(sink, callback);
-}
-
-void MediaStreamVideoTrack::RemoveSink(MediaStreamSink* sink) {
- DCHECK(thread_checker_.CalledOnValidThread());
- frame_deliverer_->RemoveCallback(sink);
-}
-
void MediaStreamVideoTrack::SetEnabled(bool enabled) {
DCHECK(thread_checker_.CalledOnValidThread());
MediaStreamTrack::SetEnabled(enabled);
diff --git a/content/renderer/media/media_stream_video_track.h b/content/renderer/media/media_stream_video_track.h
index 9fa8125..040686c 100644
--- a/content/renderer/media/media_stream_video_track.h
+++ b/content/renderer/media/media_stream_video_track.h
@@ -8,6 +8,7 @@
#include <vector>
#include "base/compiler_specific.h"
+#include "base/gtest_prod_util.h"
#include "base/memory/scoped_vector.h"
#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
@@ -48,17 +49,6 @@ class CONTENT_EXPORT MediaStreamVideoTrack : public MediaStreamTrack {
bool enabled);
virtual ~MediaStreamVideoTrack();
- // Add |sink| to receive state changes and video frames on the main render
- // thread.
- virtual void AddSink(MediaStreamVideoSink* sink);
- virtual void RemoveSink(MediaStreamVideoSink* sink);
-
- // Add |sink| to receive state changes on the main render thread and video
- // frames in the |callback| method on the IO-thread.
- virtual void AddSink(MediaStreamSink* sink,
- const VideoCaptureDeliverFrameCB& callback);
- virtual void RemoveSink(MediaStreamSink* sink);
-
virtual void SetEnabled(bool enabled) OVERRIDE;
virtual void Stop() OVERRIDE;
@@ -73,6 +63,23 @@ class CONTENT_EXPORT MediaStreamVideoTrack : public MediaStreamTrack {
base::ThreadChecker thread_checker_;
private:
+ // MediaStreamVideoSink is a friend to allow it to call AddSink() and
+ // RemoveSink().
+ friend class MediaStreamVideoSink;
+ FRIEND_TEST_ALL_PREFIXES(MediaStreamRemoteVideoSourceTest, StartTrack);
+ FRIEND_TEST_ALL_PREFIXES(MediaStreamRemoteVideoSourceTest, RemoteTrackStop);
+ FRIEND_TEST_ALL_PREFIXES(VideoDestinationHandlerTest, PutFrame);
+
+ // Add |sink| to receive state changes on the main render thread and video
+ // frames in the |callback| method on the IO-thread.
+ // |callback| will be reset on the render thread.
+ // These two methods are private such that no subclass can intercept and
+ // store the callback. This is important to ensure that we can release
+ // the callback on render thread without reference to it on the IO-thread.
+ void AddSink(MediaStreamVideoSink* sink,
+ const VideoCaptureDeliverFrameCB& callback);
+ void RemoveSink(MediaStreamVideoSink* sink);
+
// |FrameDeliverer| is an internal helper object used for delivering video
// frames on the IO-thread using callbacks to all registered tracks.
class FrameDeliverer;
diff --git a/content/renderer/media/media_stream_video_track_unittest.cc b/content/renderer/media/media_stream_video_track_unittest.cc
index 758c568..949b017 100644
--- a/content/renderer/media/media_stream_video_track_unittest.cc
+++ b/content/renderer/media/media_stream_video_track_unittest.cc
@@ -2,9 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/threading/thread_checker_impl.h"
#include "content/child/child_process.h"
#include "content/renderer/media/media_stream_video_track.h"
#include "content/renderer/media/mock_media_stream_video_sink.h"
@@ -73,8 +77,8 @@ class MediaStreamVideoTrackTest : public ::testing::Test {
}
private:
- scoped_ptr<ChildProcess> child_process_;
base::MessageLoopForUI message_loop_;
+ scoped_ptr<ChildProcess> child_process_;
blink::WebMediaStreamSource blink_source_;
// |mock_source_| is owned by |webkit_source_|.
MockMediaStreamVideoSource* mock_source_;
@@ -84,7 +88,8 @@ class MediaStreamVideoTrackTest : public ::testing::Test {
TEST_F(MediaStreamVideoTrackTest, AddAndRemoveSink) {
MockMediaStreamVideoSink sink;
blink::WebMediaStreamTrack track = CreateTrack();
- MediaStreamVideoSink::AddToVideoTrack(&sink, track);
+ MediaStreamVideoSink::AddToVideoTrack(
+ &sink, sink.GetDeliverFrameCB(), track);
DeliverVideoFrameAndWaitForRenderer(&sink);
EXPECT_EQ(1, sink.number_of_frames());
@@ -103,10 +108,54 @@ TEST_F(MediaStreamVideoTrackTest, AddAndRemoveSink) {
EXPECT_EQ(2, sink.number_of_frames());
}
+class CheckThreadHelper {
+ public:
+ CheckThreadHelper(base::Closure callback, bool* correct)
+ : callback_(callback),
+ correct_(correct) {
+ }
+
+ ~CheckThreadHelper() {
+ *correct_ = thread_checker_.CalledOnValidThread();
+ callback_.Run();
+ }
+
+ private:
+ base::Closure callback_;
+ bool* correct_;
+ base::ThreadCheckerImpl thread_checker_;
+};
+
+void CheckThreadVideoFrameReceiver(
+ CheckThreadHelper* helper,
+ const scoped_refptr<media::VideoFrame>& frame,
+ const media::VideoCaptureFormat& format) {
+ // Do nothing.
+}
+
+// Checks that the callback given to the track is reset on the right thread.
+TEST_F(MediaStreamVideoTrackTest, ResetCallbackOnThread) {
+ MockMediaStreamVideoSink sink;
+ blink::WebMediaStreamTrack track = CreateTrack();
+
+ base::RunLoop run_loop;
+ bool correct = false;
+ MediaStreamVideoSink::AddToVideoTrack(
+ &sink,
+ base::Bind(
+ &CheckThreadVideoFrameReceiver,
+ base::Owned(new CheckThreadHelper(run_loop.QuitClosure(), &correct))),
+ track);
+ MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
+ run_loop.Run();
+ EXPECT_TRUE(correct) << "Not called on correct thread.";
+}
+
TEST_F(MediaStreamVideoTrackTest, SetEnabled) {
MockMediaStreamVideoSink sink;
blink::WebMediaStreamTrack track = CreateTrack();
- MediaStreamVideoSink::AddToVideoTrack(&sink, track);
+ MediaStreamVideoSink::AddToVideoTrack(
+ &sink, sink.GetDeliverFrameCB(), track);
MediaStreamVideoTrack* video_track =
MediaStreamVideoTrack::GetVideoTrack(track);
@@ -137,7 +186,8 @@ TEST_F(MediaStreamVideoTrackTest, SetEnabled) {
TEST_F(MediaStreamVideoTrackTest, SourceStopped) {
MockMediaStreamVideoSink sink;
blink::WebMediaStreamTrack track = CreateTrack();
- MediaStreamVideoSink::AddToVideoTrack(&sink, track);
+ MediaStreamVideoSink::AddToVideoTrack(
+ &sink, sink.GetDeliverFrameCB(), track);
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive, sink.state());
mock_source()->StopSource();
@@ -148,7 +198,8 @@ TEST_F(MediaStreamVideoTrackTest, SourceStopped) {
TEST_F(MediaStreamVideoTrackTest, StopLastTrack) {
MockMediaStreamVideoSink sink1;
blink::WebMediaStreamTrack track1 = CreateTrack();
- MediaStreamVideoSink::AddToVideoTrack(&sink1, track1);
+ MediaStreamVideoSink::AddToVideoTrack(
+ &sink1, sink1.GetDeliverFrameCB(), track1);
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive, sink1.state());
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive,
@@ -156,7 +207,8 @@ TEST_F(MediaStreamVideoTrackTest, StopLastTrack) {
MockMediaStreamVideoSink sink2;
blink::WebMediaStreamTrack track2 = CreateTrack();
- MediaStreamVideoSink::AddToVideoTrack(&sink2, track2);
+ MediaStreamVideoSink::AddToVideoTrack(
+ &sink2, sink2.GetDeliverFrameCB(), track2);
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive, sink2.state());
MediaStreamVideoTrack* native_track1 =
diff --git a/content/renderer/media/mock_media_stream_video_sink.cc b/content/renderer/media/mock_media_stream_video_sink.cc
index 4246a39..638c897 100644
--- a/content/renderer/media/mock_media_stream_video_sink.cc
+++ b/content/renderer/media/mock_media_stream_video_sink.cc
@@ -4,20 +4,32 @@
#include "content/renderer/media/mock_media_stream_video_sink.h"
+#include "media/base/bind_to_current_loop.h"
+
namespace content {
MockMediaStreamVideoSink::MockMediaStreamVideoSink()
: number_of_frames_(0),
enabled_(true),
format_(media::VideoFrame::UNKNOWN),
- state_(blink::WebMediaStreamSource::ReadyStateLive) {
+ state_(blink::WebMediaStreamSource::ReadyStateLive),
+ weak_factory_(this) {
}
MockMediaStreamVideoSink::~MockMediaStreamVideoSink() {
}
-void MockMediaStreamVideoSink::OnVideoFrame(
- const scoped_refptr<media::VideoFrame>& frame) {
+VideoCaptureDeliverFrameCB
+MockMediaStreamVideoSink::GetDeliverFrameCB() {
+ return media::BindToCurrentLoop(
+ base::Bind(
+ &MockMediaStreamVideoSink::DeliverVideoFrame,
+ weak_factory_.GetWeakPtr()));
+}
+
+void MockMediaStreamVideoSink::DeliverVideoFrame(
+ const scoped_refptr<media::VideoFrame>& frame,
+ const media::VideoCaptureFormat& format) {
++number_of_frames_;
format_ = frame->format();
frame_size_ = frame->natural_size();
diff --git a/content/renderer/media/mock_media_stream_video_sink.h b/content/renderer/media/mock_media_stream_video_sink.h
index 07ec43f..acab871 100644
--- a/content/renderer/media/mock_media_stream_video_sink.h
+++ b/content/renderer/media/mock_media_stream_video_sink.h
@@ -7,6 +7,8 @@
#include "content/public/renderer/media_stream_video_sink.h"
+#include "base/memory/weak_ptr.h"
+#include "content/common/media/video_capture.h"
#include "media/base/video_frame.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -17,15 +19,15 @@ class MockMediaStreamVideoSink : public MediaStreamVideoSink {
MockMediaStreamVideoSink();
virtual ~MockMediaStreamVideoSink();
- virtual void OnVideoFrame(
- const scoped_refptr<media::VideoFrame>& frame) OVERRIDE;
virtual void OnReadyStateChanged(
- blink::WebMediaStreamSource::ReadyState state) OVERRIDE;
+ blink::WebMediaStreamSource::ReadyState state) OVERRIDE;
virtual void OnEnabledChanged(bool enabled) OVERRIDE;
// Triggered when OnVideoFrame(const scoped_refptr<media::VideoFrame>& frame)
// is called.
- MOCK_METHOD0(OnVideoFrame, void());
+ MOCK_METHOD0(OnVideoFrame, void());
+
+ VideoCaptureDeliverFrameCB GetDeliverFrameCB();
int number_of_frames() const { return number_of_frames_; }
media::VideoFrame::Format format() const { return format_; }
@@ -35,11 +37,16 @@ class MockMediaStreamVideoSink : public MediaStreamVideoSink {
blink::WebMediaStreamSource::ReadyState state() const { return state_; }
private:
+ void DeliverVideoFrame(
+ const scoped_refptr<media::VideoFrame>& frame,
+ const media::VideoCaptureFormat& format);
+
int number_of_frames_;
bool enabled_;
media::VideoFrame::Format format_;
blink::WebMediaStreamSource::ReadyState state_;
gfx::Size frame_size_;
+ base::WeakPtrFactory<MockMediaStreamVideoSink> weak_factory_;
};
} // namespace content
diff --git a/content/renderer/media/rtc_peer_connection_handler_unittest.cc b/content/renderer/media/rtc_peer_connection_handler_unittest.cc
index 93e5b23..dae5200 100644
--- a/content/renderer/media/rtc_peer_connection_handler_unittest.cc
+++ b/content/renderer/media/rtc_peer_connection_handler_unittest.cc
@@ -287,6 +287,7 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test {
return stream;
}
+ base::MessageLoop message_loop_;
scoped_ptr<ChildProcess> child_process_;
scoped_ptr<MockWebRTCPeerConnectionHandlerClient> mock_client_;
scoped_ptr<MockMediaStreamDependencyFactory> mock_dependency_factory_;
diff --git a/content/renderer/media/rtc_video_renderer.cc b/content/renderer/media/rtc_video_renderer.cc
index 26cff0d..ba380b9c 100644
--- a/content/renderer/media/rtc_video_renderer.cc
+++ b/content/renderer/media/rtc_video_renderer.cc
@@ -6,6 +6,7 @@
#include "base/debug/trace_event.h"
#include "base/message_loop/message_loop_proxy.h"
+#include "media/base/bind_to_current_loop.h"
#include "media/base/video_frame.h"
#include "media/base/video_util.h"
@@ -22,7 +23,8 @@ RTCVideoRenderer::RTCVideoRenderer(
message_loop_proxy_(base::MessageLoopProxy::current()),
state_(STOPPED),
frame_size_(kMinFrameSize, kMinFrameSize),
- video_track_(video_track) {
+ video_track_(video_track),
+ weak_factory_(this) {
}
RTCVideoRenderer::~RTCVideoRenderer() {
@@ -32,7 +34,13 @@ void RTCVideoRenderer::Start() {
DCHECK(message_loop_proxy_->BelongsToCurrentThread());
DCHECK_EQ(state_, STOPPED);
- AddToVideoTrack(this, video_track_);
+ AddToVideoTrack(
+ this,
+ media::BindToCurrentLoop(
+ base::Bind(
+ &RTCVideoRenderer::OnVideoFrame,
+ weak_factory_.GetWeakPtr())),
+ video_track_);
state_ = STARTED;
if (video_track_.source().readyState() ==
@@ -46,6 +54,7 @@ void RTCVideoRenderer::Stop() {
DCHECK(message_loop_proxy_->BelongsToCurrentThread());
DCHECK(state_ == STARTED || state_ == PAUSED);
RemoveFromVideoTrack(this, video_track_);
+ weak_factory_.InvalidateWeakPtrs();
state_ = STOPPED;
frame_size_.set_width(kMinFrameSize);
frame_size_.set_height(kMinFrameSize);
@@ -79,7 +88,8 @@ void RTCVideoRenderer::OnEnabledChanged(bool enabled) {
}
void RTCVideoRenderer::OnVideoFrame(
- const scoped_refptr<media::VideoFrame>& frame) {
+ const scoped_refptr<media::VideoFrame>& frame,
+ const media::VideoCaptureFormat& format) {
DCHECK(message_loop_proxy_->BelongsToCurrentThread());
if (state_ != STARTED) {
return;
@@ -104,7 +114,7 @@ void RTCVideoRenderer::RenderSignalingFrame() {
// originates from a video camera.
scoped_refptr<media::VideoFrame> video_frame =
media::VideoFrame::CreateBlackFrame(frame_size_);
- OnVideoFrame(video_frame);
+ OnVideoFrame(video_frame, media::VideoCaptureFormat());
}
} // namespace content
diff --git a/content/renderer/media/rtc_video_renderer.h b/content/renderer/media/rtc_video_renderer.h
index 35a8da9..e10686c 100644
--- a/content/renderer/media/rtc_video_renderer.h
+++ b/content/renderer/media/rtc_video_renderer.h
@@ -6,7 +6,9 @@
#define CONTENT_RENDERER_MEDIA_RTC_VIDEO_RENDERER_H_
#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
+#include "content/common/media/video_capture.h"
#include "content/public/renderer/media_stream_video_sink.h"
#include "content/renderer/media/video_frame_provider.h"
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
@@ -52,9 +54,10 @@ class CONTENT_EXPORT RTCVideoRenderer
STOPPED,
};
+ void OnVideoFrame(const scoped_refptr<media::VideoFrame>& frame,
+ const media::VideoCaptureFormat& format);
+
// VideoTrackSink implementation. Called on the main thread.
- virtual void OnVideoFrame(
- const scoped_refptr<media::VideoFrame>& frame) OVERRIDE;
virtual void OnReadyStateChanged(
blink::WebMediaStreamSource::ReadyState state) OVERRIDE;
virtual void OnEnabledChanged(bool enabled) OVERRIDE;
@@ -67,6 +70,7 @@ class CONTENT_EXPORT RTCVideoRenderer
State state_;
gfx::Size frame_size_;
blink::WebMediaStreamTrack video_track_;
+ base::WeakPtrFactory<RTCVideoRenderer> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(RTCVideoRenderer);
};
diff --git a/content/renderer/media/video_frame_deliverer.cc b/content/renderer/media/video_frame_deliverer.cc
index 67b11c4..ad82339 100644
--- a/content/renderer/media/video_frame_deliverer.cc
+++ b/content/renderer/media/video_frame_deliverer.cc
@@ -8,6 +8,11 @@
#include "base/location.h"
namespace content {
+namespace {
+void ResetCallback(scoped_ptr<VideoCaptureDeliverFrameCB> callback) {
+ // |callback| will be deleted when this exits.
+}
+} // namespace
VideoFrameDeliverer::VideoFrameDeliverer(
const scoped_refptr<base::MessageLoopProxy>& io_message_loop)
@@ -41,15 +46,25 @@ void VideoFrameDeliverer::RemoveCallback(void* id) {
io_message_loop_->PostTask(
FROM_HERE,
base::Bind(&VideoFrameDeliverer::RemoveCallbackOnIO,
- this, id));
+ this, id, base::MessageLoopProxy::current()));
}
-void VideoFrameDeliverer::RemoveCallbackOnIO(void* id) {
+void VideoFrameDeliverer::RemoveCallbackOnIO(
+ void* id, const scoped_refptr<base::MessageLoopProxy>& message_loop) {
DCHECK(io_message_loop_->BelongsToCurrentThread());
std::vector<VideoIdCallbackPair>::iterator it = callbacks_.begin();
for (; it != callbacks_.end(); ++it) {
if (it->first == id) {
- callbacks_.erase(it);
+ // Callback is copied to heap and then deleted on the target thread.
+ // The following code ensures that the callback is not referenced on
+ // the stack.
+ scoped_ptr<VideoCaptureDeliverFrameCB> callback;
+ {
+ callback.reset(new VideoCaptureDeliverFrameCB(it->second));
+ callbacks_.erase(it);
+ }
+ message_loop->PostTask(
+ FROM_HERE, base::Bind(&ResetCallback, base::Passed(&callback)));
return;
}
}
diff --git a/content/renderer/media/video_frame_deliverer.h b/content/renderer/media/video_frame_deliverer.h
index f17c588..e8819b4 100644
--- a/content/renderer/media/video_frame_deliverer.h
+++ b/content/renderer/media/video_frame_deliverer.h
@@ -30,9 +30,10 @@ class VideoFrameDeliverer
// Add |callback| to receive video frames on the IO-thread.
// Must be called on the main render thread.
void AddCallback(void* id, const VideoCaptureDeliverFrameCB& callback);
+
// Removes |callback| associated with |id| from receiving video frames if |id|
// has been added. It is ok to call RemoveCallback even if the |id| has not
- // been added.
+ // been added. Note that the added callback will be reset on the main thread.
// Must be called on the main render thread.
void RemoveCallback(void* id);
@@ -48,8 +49,11 @@ class VideoFrameDeliverer
protected:
void AddCallbackOnIO(void* id, const VideoCaptureDeliverFrameCB& callback);
+
+ // Callback will be removed and then reset on the designated message loop.
// It is ok to call RemoveCallback even if |id| has not been added.
- void RemoveCallbackOnIO(void* id);
+ void RemoveCallbackOnIO(
+ void* id, const scoped_refptr<base::MessageLoopProxy>& message_loop);
protected:
virtual ~VideoFrameDeliverer();
diff --git a/content/renderer/media/video_source_handler.cc b/content/renderer/media/video_source_handler.cc
index 9882207..dabc9cc 100644
--- a/content/renderer/media/video_source_handler.cc
+++ b/content/renderer/media/video_source_handler.cc
@@ -7,10 +7,13 @@
#include <string>
#include "base/logging.h"
+#include "base/memory/weak_ptr.h"
#include "base/synchronization/lock.h"
#include "content/public/renderer/media_stream_video_sink.h"
#include "content/renderer/media/media_stream.h"
#include "content/renderer/media/media_stream_registry_interface.h"
+#include "media/base/bind_to_current_loop.h"
+#include "media/video/capture/video_capture_types.h"
#include "third_party/WebKit/public/platform/WebMediaStream.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/web/WebMediaStreamRegistry.h"
@@ -23,26 +26,44 @@ namespace content {
// It can be attached to a FrameReaderInterface to output the received frame.
class PpFrameReceiver : public MediaStreamVideoSink {
public:
- PpFrameReceiver() : reader_(NULL) {}
+ PpFrameReceiver(blink::WebMediaStreamTrack track)
+ : track_(track),
+ reader_(NULL),
+ weak_factory_(this) {
+ }
+
virtual ~PpFrameReceiver() {}
- // Implements MediaStreamVideoSink.
- virtual void OnVideoFrame(
- const scoped_refptr<media::VideoFrame>& frame) OVERRIDE {
- base::AutoLock auto_lock(lock_);
- if (reader_) {
- reader_->GotFrame(frame);
+ void SetReader(FrameReaderInterface* reader) {
+ if (reader) {
+ DCHECK(!reader_);
+ MediaStreamVideoSink::AddToVideoTrack(
+ this,
+ media::BindToCurrentLoop(
+ base::Bind(
+ &PpFrameReceiver::OnVideoFrame,
+ weak_factory_.GetWeakPtr())),
+ track_);
+ } else {
+ DCHECK(reader_);
+ MediaStreamVideoSink::RemoveFromVideoTrack(this, track_);
+ weak_factory_.InvalidateWeakPtrs();
}
+ reader_ = reader;
}
- void SetReader(FrameReaderInterface* reader) {
- base::AutoLock auto_lock(lock_);
- reader_ = reader;
+ void OnVideoFrame(
+ const scoped_refptr<media::VideoFrame>& frame,
+ const media::VideoCaptureFormat& format) {
+ if (reader_) {
+ reader_->GotFrame(frame);
+ }
}
private:
+ blink::WebMediaStreamTrack track_;
FrameReaderInterface* reader_;
- base::Lock lock_;
+ base::WeakPtrFactory<PpFrameReceiver> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(PpFrameReceiver);
};
@@ -109,28 +130,26 @@ blink::WebMediaStreamTrack VideoSourceHandler::GetFirstVideoTrack(
return video_tracks[0];
}
-MediaStreamVideoSink* VideoSourceHandler::GetReceiver(
- FrameReaderInterface* reader) {
+void VideoSourceHandler::DeliverFrameForTesting(
+ FrameReaderInterface* reader,
+ const scoped_refptr<media::VideoFrame>& frame) {
SourceInfoMap::iterator it = reader_to_receiver_.find(reader);
if (it == reader_to_receiver_.end()) {
- return NULL;
+ return;
}
- return it->second->receiver_.get();
+ PpFrameReceiver* receiver = it->second->receiver_.get();
+ receiver->OnVideoFrame(frame, media::VideoCaptureFormat());
}
VideoSourceHandler::SourceInfo::SourceInfo(
const blink::WebMediaStreamTrack& blink_track,
FrameReaderInterface* reader)
- : receiver_(new PpFrameReceiver()),
- track_(blink_track) {
- MediaStreamVideoSink::AddToVideoTrack(receiver_.get(), track_);
+ : receiver_(new PpFrameReceiver(blink_track)) {
receiver_->SetReader(reader);
}
VideoSourceHandler::SourceInfo::~SourceInfo() {
- MediaStreamVideoSink::RemoveFromVideoTrack(receiver_.get(), track_);
receiver_->SetReader(NULL);
}
} // namespace content
-
diff --git a/content/renderer/media/video_source_handler.h b/content/renderer/media/video_source_handler.h
index 7337d80..ead167a 100644
--- a/content/renderer/media/video_source_handler.h
+++ b/content/renderer/media/video_source_handler.h
@@ -9,6 +9,7 @@
#include <string>
#include "base/compiler_specific.h"
+#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/threading/thread_checker.h"
@@ -50,22 +51,24 @@ class CONTENT_EXPORT VideoSourceHandler {
// Returns true on success and false on failure.
bool Close(FrameReaderInterface* reader);
- // Gets the MediaStreamVideoSink associated with |reader|.
- // Made it public only for testing purpose.
- MediaStreamVideoSink* GetReceiver(FrameReaderInterface* reader);
-
private:
+ FRIEND_TEST_ALL_PREFIXES(VideoSourceHandlerTest, OpenClose);
+
struct SourceInfo {
SourceInfo(const blink::WebMediaStreamTrack& blink_track,
FrameReaderInterface* reader);
~SourceInfo();
scoped_ptr<PpFrameReceiver> receiver_;
- blink::WebMediaStreamTrack track_;
};
typedef std::map<FrameReaderInterface*, SourceInfo*> SourceInfoMap;
+ // Deliver VideoFrame to the MediaStreamVideoSink associated with
+ // |reader|. For testing only.
+ void DeliverFrameForTesting(FrameReaderInterface* reader,
+ const scoped_refptr<media::VideoFrame>& frame);
+
blink::WebMediaStreamTrack GetFirstVideoTrack(const std::string& url);
MediaStreamRegistryInterface* registry_;
@@ -79,4 +82,3 @@ class CONTENT_EXPORT VideoSourceHandler {
} // namespace content
#endif // CONTENT_RENDERER_MEDIA_VIDEO_SOURCE_HANDLER_H_
-
diff --git a/content/renderer/media/video_source_handler_unittest.cc b/content/renderer/media/video_source_handler_unittest.cc
index 1d66ca0..94dce46 100644
--- a/content/renderer/media/video_source_handler_unittest.cc
+++ b/content/renderer/media/video_source_handler_unittest.cc
@@ -4,8 +4,10 @@
#include <string>
+#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "content/child/child_process.h"
+#include "content/common/media/video_capture.h"
#include "content/public/renderer/media_stream_video_sink.h"
#include "content/renderer/media/media_stream.h"
#include "content/renderer/media/media_stream_registry_interface.h"
@@ -49,6 +51,7 @@ class VideoSourceHandlerTest : public ::testing::Test {
}
protected:
+ base::MessageLoop message_loop_;
scoped_ptr<ChildProcess> child_process_;
scoped_ptr<VideoSourceHandler> handler_;
MockMediaStreamRegistry registry_;
@@ -70,8 +73,7 @@ TEST_F(VideoSourceHandlerTest, OpenClose) {
captured_frame->set_timestamp(ts);
// The frame is delivered to VideoSourceHandler.
- MediaStreamVideoSink* receiver = handler_->GetReceiver(&reader);
- receiver->OnVideoFrame(captured_frame);
+ handler_->DeliverFrameForTesting(&reader, captured_frame);
// Compare |frame| to |captured_frame|.
const media::VideoFrame* frame = reader.last_frame();
@@ -84,7 +86,6 @@ TEST_F(VideoSourceHandlerTest, OpenClose) {
EXPECT_FALSE(handler_->Close(NULL));
EXPECT_TRUE(handler_->Close(&reader));
- EXPECT_TRUE(handler_->GetReceiver(&reader) == NULL);
}
TEST_F(VideoSourceHandlerTest, OpenWithoutClose) {
diff --git a/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc b/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc
index 16c3687..ce4e1cc 100644
--- a/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc
+++ b/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc
@@ -108,10 +108,7 @@ TEST_F(MediaStreamRemoteVideoSourceTest, StartTrack) {
EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
MockMediaStreamVideoSink sink;
- track->AddSink(&sink);
-
-
-
+ track->AddSink(&sink, sink.GetDeliverFrameCB());
base::RunLoop run_loop;
base::Closure quit_closure = run_loop.QuitClosure();
EXPECT_CALL(sink, OnVideoFrame()).WillOnce(
@@ -129,8 +126,7 @@ TEST_F(MediaStreamRemoteVideoSourceTest, RemoteTrackStop) {
scoped_ptr<MediaStreamVideoTrack> track(CreateTrack());
MockMediaStreamVideoSink sink;
- track->AddSink(&sink);
-
+ track->AddSink(&sink, sink.GetDeliverFrameCB());
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive, sink.state());
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive,
webkit_source().readyState());
diff --git a/content/renderer/media/webrtc/video_destination_handler_unittest.cc b/content/renderer/media/webrtc/video_destination_handler_unittest.cc
index 062c277..49e9cf7 100644
--- a/content/renderer/media/webrtc/video_destination_handler_unittest.cc
+++ b/content/renderer/media/webrtc/video_destination_handler_unittest.cc
@@ -36,8 +36,13 @@ class VideoDestinationHandlerTest : public PpapiUnittest {
public:
VideoDestinationHandlerTest()
: child_process_(new ChildProcess()),
- registry_(MockMediaStreamRegistry()) {
- registry_.Init(kTestStreamUrl);
+ registry_(new MockMediaStreamRegistry()) {
+ registry_->Init(kTestStreamUrl);
+ }
+
+ virtual void TearDown() {
+ registry_.reset();
+ PpapiUnittest::TearDown();
}
base::MessageLoop* io_message_loop() const {
@@ -46,15 +51,15 @@ class VideoDestinationHandlerTest : public PpapiUnittest {
protected:
scoped_ptr<ChildProcess> child_process_;
- MockMediaStreamRegistry registry_;
+ scoped_ptr<MockMediaStreamRegistry> registry_;
};
TEST_F(VideoDestinationHandlerTest, Open) {
FrameWriterInterface* frame_writer = NULL;
// Unknow url will return false.
- EXPECT_FALSE(VideoDestinationHandler::Open(&registry_,
+ EXPECT_FALSE(VideoDestinationHandler::Open(registry_.get(),
kUnknownStreamUrl, &frame_writer));
- EXPECT_TRUE(VideoDestinationHandler::Open(&registry_,
+ EXPECT_TRUE(VideoDestinationHandler::Open(registry_.get(),
kTestStreamUrl, &frame_writer));
// The |frame_writer| is a proxy and is owned by whoever call Open.
delete frame_writer;
@@ -62,12 +67,12 @@ TEST_F(VideoDestinationHandlerTest, Open) {
TEST_F(VideoDestinationHandlerTest, PutFrame) {
FrameWriterInterface* frame_writer = NULL;
- EXPECT_TRUE(VideoDestinationHandler::Open(&registry_,
+ EXPECT_TRUE(VideoDestinationHandler::Open(registry_.get(),
kTestStreamUrl, &frame_writer));
ASSERT_TRUE(frame_writer);
// Verify the video track has been added.
- const blink::WebMediaStream test_stream = registry_.test_stream();
+ const blink::WebMediaStream test_stream = registry_->test_stream();
blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
test_stream.videoTracks(video_tracks);
ASSERT_EQ(1u, video_tracks.size());
@@ -78,9 +83,8 @@ TEST_F(VideoDestinationHandlerTest, PutFrame) {
ASSERT_TRUE(native_track != NULL);
MockMediaStreamVideoSink sink;
- native_track->AddSink(&sink);
-
- scoped_refptr<PPB_ImageData_Impl> image(
+ native_track->AddSink(&sink, sink.GetDeliverFrameCB());
+ scoped_refptr<PPB_ImageData_Impl> image(
new PPB_ImageData_Impl(instance()->pp_instance(),
PPB_ImageData_Impl::ForTest()));
image->Init(PP_IMAGEDATAFORMAT_BGRA_PREMUL, 640, 360, true);
diff --git a/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc b/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc
index 5a5b9bf..0cd769b 100644
--- a/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc
+++ b/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
#include "content/child/child_process.h"
#include "content/renderer/media/media_stream.h"
#include "content/renderer/media/media_stream_audio_source.h"
@@ -91,6 +92,7 @@ class WebRtcMediaStreamAdapterTest : public ::testing::Test {
}
protected:
+ base::MessageLoop message_loop_;
scoped_ptr<ChildProcess> child_process_;
scoped_ptr<MockMediaStreamDependencyFactory> dependency_factory_;
scoped_ptr<WebRtcMediaStreamAdapter> adapter_;
diff --git a/content/renderer/media/webrtc/webrtc_video_track_adapter.cc b/content/renderer/media/webrtc/webrtc_video_track_adapter.cc
index 0fdef64..211013d 100644
--- a/content/renderer/media/webrtc/webrtc_video_track_adapter.cc
+++ b/content/renderer/media/webrtc/webrtc_video_track_adapter.cc
@@ -89,9 +89,11 @@ WebRtcVideoTrackAdapter::WebRtcVideoTrackAdapter(
source_adapter_ = new WebRtcVideoSourceAdapter(video_source,
capture_adapter);
- MediaStreamVideoTrack::GetVideoTrack(track)->AddSink(
- this, base::Bind(&WebRtcVideoSourceAdapter::OnVideoFrameOnIO,
- source_adapter_));
+ AddToVideoTrack(
+ this,
+ base::Bind(&WebRtcVideoSourceAdapter::OnVideoFrameOnIO,
+ source_adapter_),
+ web_track_);
DVLOG(3) << "WebRtcVideoTrackAdapter ctor() : is_screencast "
<< is_screencast;
@@ -100,7 +102,7 @@ WebRtcVideoTrackAdapter::WebRtcVideoTrackAdapter(
WebRtcVideoTrackAdapter::~WebRtcVideoTrackAdapter() {
DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(3) << "WebRtcVideoTrackAdapter dtor().";
- MediaStreamVideoTrack::GetVideoTrack(web_track_)->RemoveSink(this);
+ RemoveFromVideoTrack(this, web_track_);
}
void WebRtcVideoTrackAdapter::OnEnabledChanged(bool enabled) {
@@ -109,4 +111,3 @@ void WebRtcVideoTrackAdapter::OnEnabledChanged(bool enabled) {
}
} // namespace content
-
diff --git a/content/renderer/media/webrtc/webrtc_video_track_adapter.h b/content/renderer/media/webrtc/webrtc_video_track_adapter.h
index 6b649ba..1a9be60 100644
--- a/content/renderer/media/webrtc/webrtc_video_track_adapter.h
+++ b/content/renderer/media/webrtc/webrtc_video_track_adapter.h
@@ -7,7 +7,7 @@
#include "base/macros.h"
#include "base/threading/thread_checker.h"
-#include "content/public/renderer/media_stream_sink.h"
+#include "content/public/renderer/media_stream_video_sink.h"
#include "content/renderer/media/media_stream_dependency_factory.h"
#include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h"
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
@@ -27,7 +27,7 @@ class MediaStreamVideoTrack;
// added to an RTCPeerConnection object.
// Instances of this class is owned by the WebRtcMediaStreamAdapter object that
// created it.
-class WebRtcVideoTrackAdapter : public MediaStreamSink {
+class WebRtcVideoTrackAdapter : public MediaStreamVideoSink {
public:
WebRtcVideoTrackAdapter(const blink::WebMediaStreamTrack& track,
MediaStreamDependencyFactory* factory);
diff --git a/content/renderer/pepper/pepper_media_stream_video_track_host.cc b/content/renderer/pepper/pepper_media_stream_video_track_host.cc
index 7d98e71..6e6a938 100644
--- a/content/renderer/pepper/pepper_media_stream_video_track_host.cc
+++ b/content/renderer/pepper/pepper_media_stream_video_track_host.cc
@@ -9,6 +9,7 @@
#include "base/rand_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/renderer/media/media_stream_video_track.h"
+#include "media/base/bind_to_current_loop.h"
#include "media/base/yuv_convert.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/ppb_media_stream_video_track.h"
@@ -240,7 +241,8 @@ PepperMediaStreamVideoTrackHost::PepperMediaStreamVideoTrackHost(
plugin_frame_format_(PP_VIDEOFRAME_FORMAT_UNKNOWN),
frame_data_size_(0),
type_(kRead),
- output_started_(false) {
+ output_started_(false),
+ weak_factory_(this) {
DCHECK(!track_.isNull());
}
@@ -255,7 +257,8 @@ PepperMediaStreamVideoTrackHost::PepperMediaStreamVideoTrackHost(
plugin_frame_format_(PP_VIDEOFRAME_FORMAT_UNKNOWN),
frame_data_size_(0),
type_(kWrite),
- output_started_(false) {
+ output_started_(false),
+ weak_factory_(this) {
InitBlinkTrack();
DCHECK(!track_.isNull());
}
@@ -312,6 +315,7 @@ void PepperMediaStreamVideoTrackHost::InitBuffers() {
void PepperMediaStreamVideoTrackHost::OnClose() {
if (connected_) {
MediaStreamVideoSink::RemoveFromVideoTrack(this, track_);
+ weak_factory_.InvalidateWeakPtrs();
connected_ = false;
}
}
@@ -376,7 +380,8 @@ int32_t PepperMediaStreamVideoTrackHost::SendFrameToTrack(int32_t index) {
}
void PepperMediaStreamVideoTrackHost::OnVideoFrame(
- const scoped_refptr<VideoFrame>& frame) {
+ const scoped_refptr<VideoFrame>& frame,
+ const media::VideoCaptureFormat& format) {
DCHECK(frame);
// TODO(penghuang): Check |frame->end_of_stream()| and close the track.
PP_VideoFrame_Format ppformat = ToPpapiFormat(frame->format());
@@ -400,18 +405,18 @@ void PepperMediaStreamVideoTrackHost::OnVideoFrame(
CHECK_EQ(ppformat, source_frame_format_) << "Frame format is changed.";
gfx::Size size = GetTargetSize(source_frame_size_, plugin_frame_size_);
- PP_VideoFrame_Format format =
+ ppformat =
GetTargetFormat(source_frame_format_, plugin_frame_format_);
ppapi::MediaStreamBuffer::Video* buffer =
&(buffer_manager()->GetBufferPointer(index)->video);
buffer->header.size = buffer_manager()->buffer_size();
buffer->header.type = ppapi::MediaStreamBuffer::TYPE_VIDEO;
buffer->timestamp = frame->timestamp().InSecondsF();
- buffer->format = format;
+ buffer->format = ppformat;
buffer->size.width = size.width();
buffer->size.height = size.height();
buffer->data_size = frame_data_size_;
- ConvertFromMediaVideoFrame(frame, format, size, buffer->data);
+ ConvertFromMediaVideoFrame(frame, ppformat, size, buffer->data);
SendEnqueueBufferMessageToPlugin(index);
}
@@ -447,7 +452,13 @@ void PepperMediaStreamVideoTrackHost::StopSourceImpl() {
void PepperMediaStreamVideoTrackHost::DidConnectPendingHostToResource() {
if (!connected_) {
- MediaStreamVideoSink::AddToVideoTrack(this, track_);
+ MediaStreamVideoSink::AddToVideoTrack(
+ this,
+ media::BindToCurrentLoop(
+ base::Bind(
+ &PepperMediaStreamVideoTrackHost::OnVideoFrame,
+ weak_factory_.GetWeakPtr())),
+ track_);
connected_ = true;
}
}
diff --git a/content/renderer/pepper/pepper_media_stream_video_track_host.h b/content/renderer/pepper/pepper_media_stream_video_track_host.h
index 3658706..b985b38 100644
--- a/content/renderer/pepper/pepper_media_stream_video_track_host.h
+++ b/content/renderer/pepper/pepper_media_stream_video_track_host.h
@@ -6,6 +6,7 @@
#define CONTENT_RENDERER_PEPPER_PEPPER_MEDIA_STREAM_VIDEO_TRACK_HOST_H_
#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
#include "content/public/renderer/media_stream_video_sink.h"
#include "content/renderer/media/media_stream_video_source.h"
#include "content/renderer/pepper/pepper_media_stream_track_host_base.h"
@@ -54,9 +55,8 @@ class PepperMediaStreamVideoTrackHost : public PepperMediaStreamTrackHostBase,
// Sends frame with |index| to |track_|.
int32_t SendFrameToTrack(int32_t index);
- // MediaStreamVideoSink overrides:
- virtual void OnVideoFrame(const scoped_refptr<media::VideoFrame>& frame)
- OVERRIDE;
+ void OnVideoFrame(const scoped_refptr<media::VideoFrame>& frame,
+ const media::VideoCaptureFormat& format);
// MediaStreamVideoSource overrides:
virtual void GetCurrentSupportedFormats(
@@ -119,6 +119,8 @@ class PepperMediaStreamVideoTrackHost : public PepperMediaStreamTrackHostBase,
class FrameDeliverer;
scoped_refptr<FrameDeliverer> frame_deliverer_;
+ base::WeakPtrFactory<PepperMediaStreamVideoTrackHost> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(PepperMediaStreamVideoTrackHost);
};