Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(317)

Side by Side Diff: content/renderer/media/webrtc/video_destination_handler.cc

Issue 631903003: Move VideoDestinationHandler processing to the IO-thread. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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/video_destination_handler.h" 5 #include "content/renderer/media/webrtc/video_destination_handler.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/base64.h" 9 #include "base/base64.h"
10 #include "base/debug/trace_event.h" 10 #include "base/debug/trace_event.h"
(...skipping 11 matching lines...) Expand all
22 #include "third_party/WebKit/public/web/WebMediaStreamRegistry.h" 22 #include "third_party/WebKit/public/web/WebMediaStreamRegistry.h"
23 #include "third_party/libyuv/include/libyuv/convert.h" 23 #include "third_party/libyuv/include/libyuv/convert.h"
24 #include "url/gurl.h" 24 #include "url/gurl.h"
25 25
26 namespace content { 26 namespace content {
27 27
28 class PpFrameWriter::FrameWriterDelegate 28 class PpFrameWriter::FrameWriterDelegate
29 : public base::RefCountedThreadSafe<FrameWriterDelegate> { 29 : public base::RefCountedThreadSafe<FrameWriterDelegate> {
30 public: 30 public:
31 FrameWriterDelegate( 31 FrameWriterDelegate(
32 const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy, 32 const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy);
33 const VideoCaptureDeliverFrameCB& new_frame_callback);
34 33
35 void DeliverFrame(const scoped_refptr<media::VideoFrame>& frame, 34 // Starts forwarding frames to |frame_callback| on the IO-thread that are
36 const media::VideoCaptureFormat& format); 35 // delivered to this class by calling DeliverFrame on the main render thread.
36 void StartDeliver(const VideoCaptureDeliverFrameCB& frame_callback);
37 void StopDeliver();
38
39 void DeliverFrame(const scoped_refptr<PPB_ImageData_Impl>& image_data,
40 int64 time_stamp_ns);
41
37 private: 42 private:
38 friend class base::RefCountedThreadSafe<FrameWriterDelegate>; 43 friend class base::RefCountedThreadSafe<FrameWriterDelegate>;
39 virtual ~FrameWriterDelegate(); 44 virtual ~FrameWriterDelegate();
40 45
41 void DeliverFrameOnIO(const scoped_refptr<media::VideoFrame>& frame, 46 void StartDeliverOnIO(const VideoCaptureDeliverFrameCB& frame_callback);
42 const media::VideoCaptureFormat& format); 47 void StopDeliverOnIO();
48
49 void DeliverFrameOnIO(uint8* data, int stride, int width, int height,
50 int64 time_stamp_ns);
51 void FrameDelivered(const scoped_refptr<PPB_ImageData_Impl>& image_data);
43 52
44 scoped_refptr<base::MessageLoopProxy> io_message_loop_; 53 scoped_refptr<base::MessageLoopProxy> io_message_loop_;
54
55 // |frame_pool_| and |new_frame_callback_| are only used on the IO-thread.
56 media::VideoFramePool frame_pool_;
45 VideoCaptureDeliverFrameCB new_frame_callback_; 57 VideoCaptureDeliverFrameCB new_frame_callback_;
58
59 // Used to DCHECK that we are called on the main render thread.
60 base::ThreadChecker thread_checker_;
46 }; 61 };
47 62
48 PpFrameWriter::FrameWriterDelegate::FrameWriterDelegate( 63 PpFrameWriter::FrameWriterDelegate::FrameWriterDelegate(
49 const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy, 64 const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy)
50 const VideoCaptureDeliverFrameCB& new_frame_callback) 65 : io_message_loop_(io_message_loop_proxy) {
51 : io_message_loop_(io_message_loop_proxy),
52 new_frame_callback_(new_frame_callback) {
53 } 66 }
54 67
55 PpFrameWriter::FrameWriterDelegate::~FrameWriterDelegate() { 68 PpFrameWriter::FrameWriterDelegate::~FrameWriterDelegate() {
56 } 69 }
57 70
58 void PpFrameWriter::FrameWriterDelegate::DeliverFrame( 71 void PpFrameWriter::FrameWriterDelegate::StartDeliver(
59 const scoped_refptr<media::VideoFrame>& frame, 72 const VideoCaptureDeliverFrameCB& frame_callback) {
60 const media::VideoCaptureFormat& format) { 73 DCHECK(thread_checker_.CalledOnValidThread());
61 io_message_loop_->PostTask( 74 io_message_loop_->PostTask(
62 FROM_HERE, 75 FROM_HERE,
63 base::Bind(&FrameWriterDelegate::DeliverFrameOnIO, 76 base::Bind(&FrameWriterDelegate::StartDeliverOnIO, this,
64 this, frame, format)); 77 frame_callback));
65 } 78 }
66 79
67 void PpFrameWriter::FrameWriterDelegate::DeliverFrameOnIO( 80 void PpFrameWriter::FrameWriterDelegate::StopDeliver() {
68 const scoped_refptr<media::VideoFrame>& frame, 81 DCHECK(thread_checker_.CalledOnValidThread());
69 const media::VideoCaptureFormat& format) { 82 io_message_loop_->PostTask(
70 DCHECK(io_message_loop_->BelongsToCurrentThread()); 83 FROM_HERE,
71 // The local time when this frame is generated is unknown so give a null 84 base::Bind(&FrameWriterDelegate::StopDeliverOnIO, this));
72 // value to |estimated_capture_time|.
73 new_frame_callback_.Run(frame, format, base::TimeTicks());
74 } 85 }
75 86
76 PpFrameWriter::PpFrameWriter() { 87 void PpFrameWriter::FrameWriterDelegate::DeliverFrame(
77 DVLOG(3) << "PpFrameWriter ctor"; 88 const scoped_refptr<PPB_ImageData_Impl>& image_data,
78 } 89 int64 time_stamp_ns) {
79 90 DCHECK(thread_checker_.CalledOnValidThread());
80 PpFrameWriter::~PpFrameWriter() { 91 TRACE_EVENT0("video", "PpFrameWriter::FrameWriterDelegate::DeliverFrame");
81 DVLOG(3) << "PpFrameWriter dtor"; 92 if (!image_data->Map()) {
82 }
83
84 void PpFrameWriter::GetCurrentSupportedFormats(
85 int max_requested_width,
86 int max_requested_height,
87 double max_requested_frame_rate,
88 const VideoCaptureDeviceFormatsCB& callback) {
89 DCHECK(CalledOnValidThread());
90 DVLOG(3) << "PpFrameWriter::GetCurrentSupportedFormats()";
91 // Since the input is free to change the resolution at any point in time
92 // the supported formats are unknown.
93 media::VideoCaptureFormats formats;
94 callback.Run(formats);
95 }
96
97 void PpFrameWriter::StartSourceImpl(
98 const media::VideoCaptureFormat& format,
99 const VideoCaptureDeliverFrameCB& frame_callback) {
100 DCHECK(CalledOnValidThread());
101 DCHECK(!delegate_.get());
102 DVLOG(3) << "PpFrameWriter::StartSourceImpl()";
103 delegate_ = new FrameWriterDelegate(io_message_loop(), frame_callback);
104 OnStartDone(MEDIA_DEVICE_OK);
105 }
106
107 void PpFrameWriter::StopSourceImpl() {
108 DCHECK(CalledOnValidThread());
109 }
110
111 void PpFrameWriter::PutFrame(PPB_ImageData_Impl* image_data,
112 int64 time_stamp_ns) {
113 DCHECK(CalledOnValidThread());
114 TRACE_EVENT0("video", "PpFrameWriter::PutFrame");
115 DVLOG(3) << "PpFrameWriter::PutFrame()";
116
117 if (!image_data) {
118 LOG(ERROR) << "PpFrameWriter::PutFrame - Called with NULL image_data.";
119 return;
120 }
121 ImageDataAutoMapper mapper(image_data);
122 if (!mapper.is_valid()) {
123 LOG(ERROR) << "PpFrameWriter::PutFrame - " 93 LOG(ERROR) << "PpFrameWriter::PutFrame - "
124 << "The image could not be mapped and is unusable."; 94 << "The image could not be mapped and is unusable.";
125 return; 95 return;
126 } 96 }
97
127 const SkBitmap* bitmap = image_data->GetMappedBitmap(); 98 const SkBitmap* bitmap = image_data->GetMappedBitmap();
128 if (!bitmap) { 99 if (!bitmap) {
129 LOG(ERROR) << "PpFrameWriter::PutFrame - " 100 LOG(ERROR) << "PpFrameWriter::PutFrame - "
130 << "The image_data's mapped bitmap is NULL."; 101 << "The image_data's mapped bitmap is NULL.";
131 return; 102 return;
132 } 103 }
104 io_message_loop_->PostTaskAndReply(
105 FROM_HERE,
106 base::Bind(&FrameWriterDelegate::DeliverFrameOnIO, this,
107 static_cast<uint8*>(bitmap->getPixels()),
108 bitmap->rowBytes(),
109 bitmap->width(),
110 bitmap->height(),
111 time_stamp_ns),
112 base::Bind(&FrameWriterDelegate::FrameDelivered, this,
113 image_data));
114 }
133 115
134 const gfx::Size frame_size(bitmap->width(), bitmap->height()); 116 void PpFrameWriter::FrameWriterDelegate::FrameDelivered(
117 const scoped_refptr<PPB_ImageData_Impl>& image_data) {
118 DCHECK(thread_checker_.CalledOnValidThread());
119 image_data->Unmap();
120 }
135 121
136 if (state() != MediaStreamVideoSource::STARTED) 122 void PpFrameWriter::FrameWriterDelegate::StartDeliverOnIO(
123 const VideoCaptureDeliverFrameCB& frame_callback) {
124 DCHECK(io_message_loop_->BelongsToCurrentThread());
125 new_frame_callback_ = frame_callback;
126 }
127 void PpFrameWriter::FrameWriterDelegate::StopDeliverOnIO() {
128 DCHECK(io_message_loop_->BelongsToCurrentThread());
129 new_frame_callback_.Reset();
130 }
131
132 void PpFrameWriter::FrameWriterDelegate::DeliverFrameOnIO(
133 uint8* data, int stride, int width, int height, int64 time_stamp_ns) {
134 DCHECK(io_message_loop_->BelongsToCurrentThread());
135 TRACE_EVENT0("video", "PpFrameWriter::FrameWriterDelegate::DeliverFrameOnIO");
136
137 if (new_frame_callback_.is_null())
137 return; 138 return;
138 139
140 const gfx::Size frame_size(width, height);
139 const base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds( 141 const base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds(
140 time_stamp_ns / base::Time::kNanosecondsPerMicrosecond); 142 time_stamp_ns / base::Time::kNanosecondsPerMicrosecond);
141 143
142 // TODO(perkj): It would be more efficient to use I420 here. Using YV12 will 144 // TODO(perkj): It would be more efficient to use I420 here. Using YV12 will
143 // force a copy into a tightly packed I420 frame in 145 // force a copy into a tightly packed I420 frame in
144 // WebRtcVideoCapturerAdapter before the frame is delivered to libJingle. 146 // WebRtcVideoCapturerAdapter before the frame is delivered to libJingle.
145 // crbug/359587. 147 // crbug/359587.
146 scoped_refptr<media::VideoFrame> new_frame = 148 scoped_refptr<media::VideoFrame> new_frame =
147 frame_pool_.CreateFrame(media::VideoFrame::YV12, frame_size, 149 frame_pool_.CreateFrame(media::VideoFrame::YV12, frame_size,
148 gfx::Rect(frame_size), frame_size, timestamp); 150 gfx::Rect(frame_size), frame_size, timestamp);
149 media::VideoCaptureFormat format( 151 media::VideoCaptureFormat format(
150 frame_size, 152 frame_size,
151 MediaStreamVideoSource::kUnknownFrameRate, 153 MediaStreamVideoSource::kUnknownFrameRate,
152 media::PIXEL_FORMAT_YV12); 154 media::PIXEL_FORMAT_YV12);
153 155
154 libyuv::BGRAToI420(reinterpret_cast<uint8*>(bitmap->getPixels()), 156 libyuv::BGRAToI420(data,
155 bitmap->rowBytes(), 157 stride,
156 new_frame->data(media::VideoFrame::kYPlane), 158 new_frame->data(media::VideoFrame::kYPlane),
157 new_frame->stride(media::VideoFrame::kYPlane), 159 new_frame->stride(media::VideoFrame::kYPlane),
158 new_frame->data(media::VideoFrame::kUPlane), 160 new_frame->data(media::VideoFrame::kUPlane),
159 new_frame->stride(media::VideoFrame::kUPlane), 161 new_frame->stride(media::VideoFrame::kUPlane),
160 new_frame->data(media::VideoFrame::kVPlane), 162 new_frame->data(media::VideoFrame::kVPlane),
161 new_frame->stride(media::VideoFrame::kVPlane), 163 new_frame->stride(media::VideoFrame::kVPlane),
162 frame_size.width(), frame_size.height()); 164 frame_size.width(), frame_size.height());
163 165
164 delegate_->DeliverFrame(new_frame, format); 166 // The local time when this frame is generated is unknown so give a null
167 // value to |estimated_capture_time|.
168 new_frame_callback_.Run(new_frame, format, base::TimeTicks());
165 } 169 }
166 170
167 // PpFrameWriterProxy is a helper class to make sure the user won't use 171 PpFrameWriter::PpFrameWriter() {
168 // PpFrameWriter after it is released (IOW its owner - WebMediaStreamSource - 172 DVLOG(3) << "PpFrameWriter ctor";
169 // is released). 173 delegate_ = new FrameWriterDelegate(io_message_loop());
170 class PpFrameWriterProxy : public FrameWriterInterface { 174 }
171 public:
172 explicit PpFrameWriterProxy(const base::WeakPtr<PpFrameWriter>& writer)
173 : writer_(writer) {
174 DCHECK(writer_ != NULL);
175 }
176 175
177 virtual ~PpFrameWriterProxy() {} 176 PpFrameWriter::~PpFrameWriter() {
177 DVLOG(3) << "PpFrameWriter dtor";
178 }
178 179
179 virtual void PutFrame(PPB_ImageData_Impl* image_data, 180 VideoDestinationHandler::FrameWriterCallback
180 int64 time_stamp_ns) override { 181 PpFrameWriter::GetFrameWriterCallback() {
181 writer_->PutFrame(image_data, time_stamp_ns); 182 DCHECK(CalledOnValidThread());
182 } 183 return base::Bind(&PpFrameWriter::FrameWriterDelegate::DeliverFrame,
184 delegate_);
185 }
183 186
184 private: 187 void PpFrameWriter::GetCurrentSupportedFormats(
185 base::WeakPtr<PpFrameWriter> writer_; 188 int max_requested_width,
189 int max_requested_height,
190 double max_requested_frame_rate,
191 const VideoCaptureDeviceFormatsCB& callback) {
192 DCHECK(CalledOnValidThread());
193 DVLOG(3) << "PpFrameWriter::GetCurrentSupportedFormats()";
194 // Since the input is free to change the resolution at any point in time
195 // the supported formats are unknown.
196 media::VideoCaptureFormats formats;
197 callback.Run(formats);
198 }
186 199
187 DISALLOW_COPY_AND_ASSIGN(PpFrameWriterProxy); 200 void PpFrameWriter::StartSourceImpl(
188 }; 201 const media::VideoCaptureFormat& format,
202 const VideoCaptureDeliverFrameCB& frame_callback) {
203 DCHECK(CalledOnValidThread());
204 DVLOG(3) << "PpFrameWriter::StartSourceImpl()";
205 delegate_->StartDeliver(frame_callback);
206 OnStartDone(MEDIA_DEVICE_OK);
207 }
208
209 void PpFrameWriter::StopSourceImpl() {
210 DCHECK(CalledOnValidThread());
211 delegate_->StopDeliver();
212 }
189 213
190 bool VideoDestinationHandler::Open( 214 bool VideoDestinationHandler::Open(
191 MediaStreamRegistryInterface* registry, 215 MediaStreamRegistryInterface* registry,
192 const std::string& url, 216 const std::string& url,
193 FrameWriterInterface** frame_writer) { 217 FrameWriterCallback* frame_writer) {
194 DVLOG(3) << "VideoDestinationHandler::Open"; 218 DVLOG(3) << "VideoDestinationHandler::Open";
195 blink::WebMediaStream stream; 219 blink::WebMediaStream stream;
196 if (registry) { 220 if (registry) {
197 stream = registry->GetMediaStream(url); 221 stream = registry->GetMediaStream(url);
198 } else { 222 } else {
199 stream = 223 stream =
200 blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(GURL(url)); 224 blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(GURL(url));
201 } 225 }
202 if (stream.isNull()) { 226 if (stream.isNull()) {
203 LOG(ERROR) << "VideoDestinationHandler::Open - invalid url: " << url; 227 LOG(ERROR) << "VideoDestinationHandler::Open - invalid url: " << url;
204 return false; 228 return false;
205 } 229 }
206 230
207 // Create a new native video track and add it to |stream|. 231 // Create a new native video track and add it to |stream|.
208 std::string track_id; 232 std::string track_id;
209 // According to spec, a media stream source's id should be unique per 233 // According to spec, a media stream source's id should be unique per
210 // application. There's no easy way to strictly achieve that. The id 234 // application. There's no easy way to strictly achieve that. The id
211 // generated with this method should be unique for most of the cases but 235 // generated with this method should be unique for most of the cases but
212 // theoretically it's possible we can get an id that's duplicated with the 236 // theoretically it's possible we can get an id that's duplicated with the
213 // existing sources. 237 // existing sources.
214 base::Base64Encode(base::RandBytesAsString(64), &track_id); 238 base::Base64Encode(base::RandBytesAsString(64), &track_id);
215 239
216 PpFrameWriter* writer = new PpFrameWriter(); 240 PpFrameWriter* writer = new PpFrameWriter();
241 *frame_writer = writer->GetFrameWriterCallback();
217 242
218 // Create a new webkit video track. 243 // Create a new webkit video track.
219 blink::WebMediaStreamSource webkit_source; 244 blink::WebMediaStreamSource webkit_source;
220 blink::WebMediaStreamSource::Type type = 245 blink::WebMediaStreamSource::Type type =
221 blink::WebMediaStreamSource::TypeVideo; 246 blink::WebMediaStreamSource::TypeVideo;
222 blink::WebString webkit_track_id = base::UTF8ToUTF16(track_id); 247 blink::WebString webkit_track_id = base::UTF8ToUTF16(track_id);
223 webkit_source.initialize(webkit_track_id, type, webkit_track_id); 248 webkit_source.initialize(webkit_track_id, type, webkit_track_id);
224 webkit_source.setExtraData(writer); 249 webkit_source.setExtraData(writer);
225 250
226 blink::WebMediaConstraints constraints; 251 blink::WebMediaConstraints constraints;
227 constraints.initialize(); 252 constraints.initialize();
228 bool track_enabled = true; 253 bool track_enabled = true;
229 254
230 stream.addTrack(MediaStreamVideoTrack::CreateVideoTrack( 255 stream.addTrack(MediaStreamVideoTrack::CreateVideoTrack(
231 writer, constraints, MediaStreamVideoSource::ConstraintsCallback(), 256 writer, constraints, MediaStreamVideoSource::ConstraintsCallback(),
232 track_enabled)); 257 track_enabled));
233 258
234 *frame_writer = new PpFrameWriterProxy(writer->AsWeakPtr());
235 return true; 259 return true;
236 } 260 }
237 261
238 } // namespace content 262 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698