Enable right clicking on the applist doodle web contents and log the data.
[chromium-blink-merge.git] / content / renderer / media / webrtc / media_stream_remote_video_source.cc
blobb75272126ec13263c5201ba0f5db6324b75a01d2
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
3 // found in the LICENSE file.
5 #include "content/renderer/media/webrtc/media_stream_remote_video_source.h"
7 #include "base/bind.h"
8 #include "base/callback_helpers.h"
9 #include "base/location.h"
10 #include "base/message_loop/message_loop_proxy.h"
11 #include "base/threading/thread_checker.h"
12 #include "base/trace_event/trace_event.h"
13 #include "content/renderer/media/native_handle_impl.h"
14 #include "content/renderer/media/webrtc/track_observer.h"
15 #include "media/base/bind_to_current_loop.h"
16 #include "media/base/video_frame.h"
17 #include "media/base/video_frame_pool.h"
18 #include "media/base/video_util.h"
19 #include "third_party/libjingle/source/talk/media/base/videoframe.h"
21 namespace content {
23 // Internal class used for receiving frames from the webrtc track on a
24 // libjingle thread and forward it to the IO-thread.
25 class MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate
26 : public base::RefCountedThreadSafe<RemoteVideoSourceDelegate>,
27 public webrtc::VideoRendererInterface {
28 public:
29 RemoteVideoSourceDelegate(
30 const scoped_refptr<base::MessageLoopProxy>& io_message_loop,
31 const VideoCaptureDeliverFrameCB& new_frame_callback);
33 protected:
34 friend class base::RefCountedThreadSafe<RemoteVideoSourceDelegate>;
35 ~RemoteVideoSourceDelegate() override;
37 // Implements webrtc::VideoRendererInterface used for receiving video frames
38 // from the PeerConnection video track. May be called on a libjingle internal
39 // thread.
40 void SetSize(int width, int height) override;
41 void RenderFrame(const cricket::VideoFrame* frame) override;
43 void DoRenderFrameOnIOThread(scoped_refptr<media::VideoFrame> video_frame,
44 const media::VideoCaptureFormat& format);
45 private:
46 // Bound to the render thread.
47 base::ThreadChecker thread_checker_;
49 scoped_refptr<base::MessageLoopProxy> io_message_loop_;
50 // |frame_pool_| is only accessed on whatever
51 // thread webrtc::VideoRendererInterface::RenderFrame is called on.
52 media::VideoFramePool frame_pool_;
54 // |frame_callback_| is accessed on the IO thread.
55 VideoCaptureDeliverFrameCB frame_callback_;
58 MediaStreamRemoteVideoSource::
59 RemoteVideoSourceDelegate::RemoteVideoSourceDelegate(
60 const scoped_refptr<base::MessageLoopProxy>& io_message_loop,
61 const VideoCaptureDeliverFrameCB& new_frame_callback)
62 : io_message_loop_(io_message_loop),
63 frame_callback_(new_frame_callback) {
66 MediaStreamRemoteVideoSource::
67 RemoteVideoSourceDelegate::~RemoteVideoSourceDelegate() {
70 void MediaStreamRemoteVideoSource::
71 RemoteVideoSourceDelegate::SetSize(int width, int height) {
74 void MediaStreamRemoteVideoSource::
75 RemoteVideoSourceDelegate::RenderFrame(
76 const cricket::VideoFrame* frame) {
77 TRACE_EVENT0("webrtc", "RemoteVideoSourceDelegate::RenderFrame");
78 base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds(
79 frame->GetElapsedTime() / rtc::kNumNanosecsPerMicrosec);
81 scoped_refptr<media::VideoFrame> video_frame;
82 if (frame->GetNativeHandle() != NULL) {
83 NativeHandleImpl* handle =
84 static_cast<NativeHandleImpl*>(frame->GetNativeHandle());
85 video_frame = static_cast<media::VideoFrame*>(handle->GetHandle());
86 video_frame->set_timestamp(timestamp);
87 } else {
88 gfx::Size size(frame->GetWidth(), frame->GetHeight());
89 video_frame = frame_pool_.CreateFrame(
90 media::VideoFrame::YV12, size, gfx::Rect(size), size, timestamp);
92 // Non-square pixels are unsupported.
93 DCHECK_EQ(frame->GetPixelWidth(), 1u);
94 DCHECK_EQ(frame->GetPixelHeight(), 1u);
96 int y_rows = frame->GetHeight();
97 int uv_rows = frame->GetChromaHeight();
98 CopyYPlane(
99 frame->GetYPlane(), frame->GetYPitch(), y_rows, video_frame.get());
100 CopyUPlane(
101 frame->GetUPlane(), frame->GetUPitch(), uv_rows, video_frame.get());
102 CopyVPlane(
103 frame->GetVPlane(), frame->GetVPitch(), uv_rows, video_frame.get());
106 media::VideoPixelFormat pixel_format =
107 (video_frame->format() == media::VideoFrame::YV12) ?
108 media::PIXEL_FORMAT_YV12 : media::PIXEL_FORMAT_TEXTURE;
110 media::VideoCaptureFormat format(
111 gfx::Size(video_frame->natural_size().width(),
112 video_frame->natural_size().height()),
113 MediaStreamVideoSource::kUnknownFrameRate,
114 pixel_format);
116 io_message_loop_->PostTask(
117 FROM_HERE,
118 base::Bind(&RemoteVideoSourceDelegate::DoRenderFrameOnIOThread,
119 this, video_frame, format));
122 void MediaStreamRemoteVideoSource::
123 RemoteVideoSourceDelegate::DoRenderFrameOnIOThread(
124 scoped_refptr<media::VideoFrame> video_frame,
125 const media::VideoCaptureFormat& format) {
126 DCHECK(io_message_loop_->BelongsToCurrentThread());
127 TRACE_EVENT0("webrtc", "RemoteVideoSourceDelegate::DoRenderFrameOnIOThread");
128 // TODO(hclam): Give the estimated capture time.
129 frame_callback_.Run(video_frame, format, base::TimeTicks());
132 MediaStreamRemoteVideoSource::MediaStreamRemoteVideoSource(
133 scoped_ptr<TrackObserver> observer)
134 : observer_(observer.Pass()) {
135 // The callback will be automatically cleared when 'observer_' goes out of
136 // scope and no further callbacks will occur.
137 observer_->SetCallback(base::Bind(&MediaStreamRemoteVideoSource::OnChanged,
138 base::Unretained(this)));
141 MediaStreamRemoteVideoSource::~MediaStreamRemoteVideoSource() {
142 DCHECK(CalledOnValidThread());
145 void MediaStreamRemoteVideoSource::GetCurrentSupportedFormats(
146 int max_requested_width,
147 int max_requested_height,
148 double max_requested_frame_rate,
149 const VideoCaptureDeviceFormatsCB& callback) {
150 DCHECK(CalledOnValidThread());
151 media::VideoCaptureFormats formats;
152 // Since the remote end is free to change the resolution at any point in time
153 // the supported formats are unknown.
154 callback.Run(formats);
157 void MediaStreamRemoteVideoSource::StartSourceImpl(
158 const media::VideoCaptureFormat& format,
159 const VideoCaptureDeliverFrameCB& frame_callback) {
160 DCHECK(CalledOnValidThread());
161 DCHECK(!delegate_.get());
162 delegate_ = new RemoteVideoSourceDelegate(io_message_loop(), frame_callback);
163 scoped_refptr<webrtc::VideoTrackInterface> video_track(
164 static_cast<webrtc::VideoTrackInterface*>(observer_->track().get()));
165 video_track->AddRenderer(delegate_.get());
166 OnStartDone(MEDIA_DEVICE_OK);
169 void MediaStreamRemoteVideoSource::StopSourceImpl() {
170 DCHECK(CalledOnValidThread());
171 DCHECK(state() != MediaStreamVideoSource::ENDED);
172 scoped_refptr<webrtc::VideoTrackInterface> video_track(
173 static_cast<webrtc::VideoTrackInterface*>(observer_->track().get()));
174 video_track->RemoveRenderer(delegate_.get());
177 webrtc::VideoRendererInterface*
178 MediaStreamRemoteVideoSource::RenderInterfaceForTest() {
179 return delegate_.get();
182 void MediaStreamRemoteVideoSource::OnChanged(
183 webrtc::MediaStreamTrackInterface::TrackState state) {
184 DCHECK(CalledOnValidThread());
185 switch (state) {
186 case webrtc::MediaStreamTrackInterface::kInitializing:
187 // Ignore the kInitializing state since there is no match in
188 // WebMediaStreamSource::ReadyState.
189 break;
190 case webrtc::MediaStreamTrackInterface::kLive:
191 SetReadyState(blink::WebMediaStreamSource::ReadyStateLive);
192 break;
193 case webrtc::MediaStreamTrackInterface::kEnded:
194 SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded);
195 break;
196 default:
197 NOTREACHED();
198 break;
202 } // namespace content