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

Side by Side Diff: content/renderer/media/rtc_video_encoder.cc

Issue 1845563006: Make RTCVideoEncoder usable from non-postable thread. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 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
« no previous file with comments | « content/renderer/media/rtc_video_encoder.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 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/rtc_video_encoder.h" 5 #include "content/renderer/media/rtc_video_encoder.h"
6 6
7 #include <string.h> 7 #include <string.h>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/location.h" 10 #include "base/location.h"
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 // 96 //
97 // This class separates state related to the thread that RTCVideoEncoder 97 // This class separates state related to the thread that RTCVideoEncoder
98 // operates on (presently the libjingle worker thread) from the thread that 98 // operates on (presently the libjingle worker thread) from the thread that
99 // |gpu_factories_| provides for accelerator operations (presently the media 99 // |gpu_factories_| provides for accelerator operations (presently the media
100 // thread). The RTCVideoEncoder class can be deleted directly by WebRTC, while 100 // thread). The RTCVideoEncoder class can be deleted directly by WebRTC, while
101 // RTCVideoEncoder::Impl stays around long enough to properly shut down the VEA. 101 // RTCVideoEncoder::Impl stays around long enough to properly shut down the VEA.
102 class RTCVideoEncoder::Impl 102 class RTCVideoEncoder::Impl
103 : public media::VideoEncodeAccelerator::Client, 103 : public media::VideoEncodeAccelerator::Client,
104 public base::RefCountedThreadSafe<RTCVideoEncoder::Impl> { 104 public base::RefCountedThreadSafe<RTCVideoEncoder::Impl> {
105 public: 105 public:
106 Impl(const base::WeakPtr<RTCVideoEncoder>& weak_encoder, 106 Impl(media::GpuVideoAcceleratorFactories* gpu_factories,
107 media::GpuVideoAcceleratorFactories* gpu_factories); 107 webrtc::VideoCodecType video_codec_type);
108 108
109 // Create the VEA and call Initialize() on it. Called once per instantiation, 109 // Create the VEA and call Initialize() on it. Called once per instantiation,
110 // and then the instance is bound forevermore to whichever thread made the 110 // and then the instance is bound forevermore to whichever thread made the
111 // call. 111 // call.
112 // RTCVideoEncoder expects to be able to call this function synchronously from 112 // RTCVideoEncoder expects to be able to call this function synchronously from
113 // its own thread, hence the |async_waiter| and |async_retval| arguments. 113 // its own thread, hence the |async_waiter| and |async_retval| arguments.
114 void CreateAndInitializeVEA(const gfx::Size& input_visible_size, 114 void CreateAndInitializeVEA(const gfx::Size& input_visible_size,
115 uint32_t bitrate, 115 uint32_t bitrate,
116 media::VideoCodecProfile profile, 116 media::VideoCodecProfile profile,
117 base::WaitableEvent* async_waiter, 117 base::WaitableEvent* async_waiter,
118 int32_t* async_retval); 118 int32_t* async_retval);
119 // Enqueue a frame from WebRTC for encoding. 119 // Enqueue a frame from WebRTC for encoding.
120 // RTCVideoEncoder expects to be able to call this function synchronously from 120 // RTCVideoEncoder expects to be able to call this function synchronously from
121 // its own thread, hence the |async_waiter| and |async_retval| arguments. 121 // its own thread, hence the |async_waiter| and |async_retval| arguments.
122 void Enqueue(const webrtc::VideoFrame* input_frame, 122 void Enqueue(const webrtc::VideoFrame* input_frame,
123 bool force_keyframe, 123 bool force_keyframe,
124 base::WaitableEvent* async_waiter, 124 base::WaitableEvent* async_waiter,
125 int32_t* async_retval); 125 int32_t* async_retval);
126 126
127 // RTCVideoEncoder is given a buffer to be passed to WebRTC through the 127 // RTCVideoEncoder is given a buffer to be passed to WebRTC through the
128 // RTCVideoEncoder::ReturnEncodedImage() function. When that is complete, 128 // RTCVideoEncoder::ReturnEncodedImage() function. When that is complete,
129 // the buffer is returned to Impl by its index using this function. 129 // the buffer is returned to Impl by its index using this function.
130 void UseOutputBitstreamBufferId(int32_t bitstream_buffer_id); 130 void UseOutputBitstreamBufferId(int32_t bitstream_buffer_id);
131 131
132 // Request encoding parameter change for the underlying encoder. 132 // Request encoding parameter change for the underlying encoder.
133 void RequestEncodingParametersChange(uint32_t bitrate, uint32_t framerate); 133 void RequestEncodingParametersChange(uint32_t bitrate, uint32_t framerate);
134 134
135 // Destroy this Impl's encoder. The destructor is not explicitly called, as 135 // Destroy this Impl's encoder. The destructor is not explicitly called, as
136 // Impl is a base::RefCountedThreadSafe. 136 // Impl is a base::RefCountedThreadSafe.
137 void Destroy(); 137 void Destroy(base::WaitableEvent* waiter);
138 138
139 // media::VideoEncodeAccelerator::Client implementation. 139 // media::VideoEncodeAccelerator::Client implementation.
140 void RequireBitstreamBuffers(unsigned int input_count, 140 void RequireBitstreamBuffers(unsigned int input_count,
141 const gfx::Size& input_coded_size, 141 const gfx::Size& input_coded_size,
142 size_t output_buffer_size) override; 142 size_t output_buffer_size) override;
143 void BitstreamBufferReady(int32_t bitstream_buffer_id, 143 void BitstreamBufferReady(int32_t bitstream_buffer_id,
144 size_t payload_size, 144 size_t payload_size,
145 bool key_frame) override; 145 bool key_frame) override;
146 void NotifyError(media::VideoEncodeAccelerator::Error error) override; 146 void NotifyError(media::VideoEncodeAccelerator::Error error) override;
147 147
148 void RegisterEncodeCompleteCallback(base::WaitableEvent* waiter,
149 webrtc::EncodedImageCallback* callback);
150
148 private: 151 private:
149 friend class base::RefCountedThreadSafe<Impl>; 152 friend class base::RefCountedThreadSafe<Impl>;
150 153
151 enum { 154 enum {
152 kInputBufferExtraCount = 1, // The number of input buffers allocated, more 155 kInputBufferExtraCount = 1, // The number of input buffers allocated, more
153 // than what is requested by 156 // than what is requested by
154 // VEA::RequireBitstreamBuffers(). 157 // VEA::RequireBitstreamBuffers().
155 kOutputBufferCount = 3, 158 kOutputBufferCount = 3,
156 }; 159 };
157 160
(...skipping 15 matching lines...) Expand all
173 void RegisterAsyncWaiter(base::WaitableEvent* waiter, int32_t* retval); 176 void RegisterAsyncWaiter(base::WaitableEvent* waiter, int32_t* retval);
174 void SignalAsyncWaiter(int32_t retval); 177 void SignalAsyncWaiter(int32_t retval);
175 178
176 // Checks if the bitrate would overflow when passing from kbps to bps. 179 // Checks if the bitrate would overflow when passing from kbps to bps.
177 bool IsBitrateTooHigh(uint32_t bitrate); 180 bool IsBitrateTooHigh(uint32_t bitrate);
178 181
179 // Checks if the frame size is different than hardware accelerator 182 // Checks if the frame size is different than hardware accelerator
180 // requirements. 183 // requirements.
181 bool RequiresSizeChange(const scoped_refptr<media::VideoFrame>& frame) const; 184 bool RequiresSizeChange(const scoped_refptr<media::VideoFrame>& frame) const;
182 185
186 // Return an encoded output buffer to WebRTC.
187 void ReturnEncodedImage(scoped_ptr<webrtc::EncodedImage> image,
188 int32_t bitstream_buffer_id,
189 uint16_t picture_id);
190
183 base::ThreadChecker thread_checker_; 191 base::ThreadChecker thread_checker_;
184 192
185 // Weak pointer to the parent RTCVideoEncoder, for posting back VEA::Client
186 // notifications.
187 const base::WeakPtr<RTCVideoEncoder> weak_encoder_;
188
189 // The message loop on which to post callbacks to |weak_encoder_|.
190 const scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner_;
191
192 // Factory for creating VEAs, shared memory buffers, etc. 193 // Factory for creating VEAs, shared memory buffers, etc.
193 media::GpuVideoAcceleratorFactories* gpu_factories_; 194 media::GpuVideoAcceleratorFactories* gpu_factories_;
194 195
195 // webrtc::VideoEncoder expects InitEncode() and Encode() to be synchronous. 196 // webrtc::VideoEncoder expects InitEncode() and Encode() to be synchronous.
196 // Do this by waiting on the |async_waiter_| and returning the return value in 197 // Do this by waiting on the |async_waiter_| and returning the return value in
197 // |async_retval_| when initialization completes, encoding completes, or 198 // |async_retval_| when initialization completes, encoding completes, or
198 // an error occurs. 199 // an error occurs.
199 base::WaitableEvent* async_waiter_; 200 base::WaitableEvent* async_waiter_;
200 int32_t* async_retval_; 201 int32_t* async_retval_;
201 202
(...skipping 19 matching lines...) Expand all
221 // we don't care about ordering. 222 // we don't care about ordering.
222 std::vector<int> input_buffers_free_; 223 std::vector<int> input_buffers_free_;
223 224
224 // The number of output buffers ready to be filled with output from the 225 // The number of output buffers ready to be filled with output from the
225 // encoder. 226 // encoder.
226 int output_buffers_free_count_; 227 int output_buffers_free_count_;
227 228
228 // 15 bits running index of the VP8 frames. See VP8 RTP spec for details. 229 // 15 bits running index of the VP8 frames. See VP8 RTP spec for details.
229 uint16_t picture_id_; 230 uint16_t picture_id_;
230 231
232 // webrtc::VideoEncoder encode complete callback.
233 webrtc::EncodedImageCallback* encoded_image_callback_;
234
235 // The video codec type, as reported to WebRTC.
236 const webrtc::VideoCodecType video_codec_type_;
237
238 // If video encode accelerator posts an error, cache it here and return it
239 // the next time Enqueue is called.
240 int32_t status_;
241
231 DISALLOW_COPY_AND_ASSIGN(Impl); 242 DISALLOW_COPY_AND_ASSIGN(Impl);
232 }; 243 };
233 244
234 RTCVideoEncoder::Impl::Impl(const base::WeakPtr<RTCVideoEncoder>& weak_encoder, 245 RTCVideoEncoder::Impl::Impl(media::GpuVideoAcceleratorFactories* gpu_factories,
235 media::GpuVideoAcceleratorFactories* gpu_factories) 246 webrtc::VideoCodecType video_codec_type)
236 : weak_encoder_(weak_encoder), 247 : gpu_factories_(gpu_factories),
237 encoder_task_runner_(base::ThreadTaskRunnerHandle::Get()),
238 gpu_factories_(gpu_factories),
239 async_waiter_(NULL), 248 async_waiter_(NULL),
240 async_retval_(NULL), 249 async_retval_(NULL),
241 input_next_frame_(NULL), 250 input_next_frame_(NULL),
242 input_next_frame_keyframe_(false), 251 input_next_frame_keyframe_(false),
243 output_buffers_free_count_(0) { 252 output_buffers_free_count_(0),
253 encoded_image_callback_(nullptr),
254 video_codec_type_(video_codec_type),
255 status_(WEBRTC_VIDEO_CODEC_OK) {
244 thread_checker_.DetachFromThread(); 256 thread_checker_.DetachFromThread();
245 // Picture ID should start on a random number. 257 // Picture ID should start on a random number.
246 picture_id_ = static_cast<uint16_t>(base::RandInt(0, 0x7FFF)); 258 picture_id_ = static_cast<uint16_t>(base::RandInt(0, 0x7FFF));
247 } 259 }
248 260
249 void RTCVideoEncoder::Impl::CreateAndInitializeVEA( 261 void RTCVideoEncoder::Impl::CreateAndInitializeVEA(
250 const gfx::Size& input_visible_size, 262 const gfx::Size& input_visible_size,
251 uint32_t bitrate, 263 uint32_t bitrate,
252 media::VideoCodecProfile profile, 264 media::VideoCodecProfile profile,
253 base::WaitableEvent* async_waiter, 265 base::WaitableEvent* async_waiter,
254 int32_t* async_retval) { 266 int32_t* async_retval) {
255 DVLOG(3) << "Impl::CreateAndInitializeVEA()"; 267 DVLOG(3) << "Impl::CreateAndInitializeVEA()";
256 DCHECK(thread_checker_.CalledOnValidThread()); 268 DCHECK(thread_checker_.CalledOnValidThread());
257 269
258 RegisterAsyncWaiter(async_waiter, async_retval); 270 RegisterAsyncWaiter(async_waiter, async_retval);
259 271
260 // Check for overflow converting bitrate (kilobits/sec) to bits/sec. 272 // Check for overflow converting bitrate (kilobits/sec) to bits/sec.
261 if (IsBitrateTooHigh(bitrate)) 273 if (IsBitrateTooHigh(bitrate))
262 return; 274 return;
263 275
264 video_encoder_ = gpu_factories_->CreateVideoEncodeAccelerator(); 276 video_encoder_ = gpu_factories_->CreateVideoEncodeAccelerator();
265 if (!video_encoder_) { 277 if (!video_encoder_) {
266 LogAndNotifyError(FROM_HERE, "Error creating VideoEncodeAccelerator", 278 LogAndNotifyError(FROM_HERE, "Error creating VideoEncodeAccelerator",
267 media::VideoEncodeAccelerator::kPlatformFailureError); 279 media::VideoEncodeAccelerator::kPlatformFailureError);
268 return; 280 return;
269 } 281 }
270 input_visible_size_ = input_visible_size; 282 input_visible_size_ = input_visible_size;
283
271 if (!video_encoder_->Initialize(media::PIXEL_FORMAT_I420, input_visible_size_, 284 if (!video_encoder_->Initialize(media::PIXEL_FORMAT_I420, input_visible_size_,
272 profile, bitrate * 1000, this)) { 285 profile, bitrate * 1000, this)) {
273 LogAndNotifyError(FROM_HERE, "Error initializing video_encoder", 286 LogAndNotifyError(FROM_HERE, "Error initializing video_encoder",
274 media::VideoEncodeAccelerator::kInvalidArgumentError); 287 media::VideoEncodeAccelerator::kInvalidArgumentError);
275 return; 288 return;
276 } 289 }
277 } 290 }
kcwu 2016/04/01 12:33:05 I don't understand the original code. There is n
wuchengli 2016/04/03 14:28:01 VEA will call RequireBitstreamBuffers after initia
278 291
279 void RTCVideoEncoder::Impl::Enqueue(const webrtc::VideoFrame* input_frame, 292 void RTCVideoEncoder::Impl::Enqueue(const webrtc::VideoFrame* input_frame,
280 bool force_keyframe, 293 bool force_keyframe,
281 base::WaitableEvent* async_waiter, 294 base::WaitableEvent* async_waiter,
282 int32_t* async_retval) { 295 int32_t* async_retval) {
283 DVLOG(3) << "Impl::Enqueue()"; 296 DVLOG(3) << "Impl::Enqueue()";
284 DCHECK(thread_checker_.CalledOnValidThread()); 297 DCHECK(thread_checker_.CalledOnValidThread());
285 DCHECK(!input_next_frame_); 298 DCHECK(!input_next_frame_);
286 299
287 RegisterAsyncWaiter(async_waiter, async_retval); 300 RegisterAsyncWaiter(async_waiter, async_retval);
301 if (status_ != WEBRTC_VIDEO_CODEC_OK)
302 SignalAsyncWaiter(status_);
kcwu 2016/04/01 12:33:05 return here?
wuchengli 2016/04/03 14:28:01 Done.
303
288 // If there are no free input and output buffers, drop the frame to avoid a 304 // If there are no free input and output buffers, drop the frame to avoid a
289 // deadlock. If there is a free input buffer, EncodeOneFrame will run and 305 // deadlock. If there is a free input buffer, EncodeOneFrame will run and
290 // unblock Encode(). If there are no free input buffers but there is a free 306 // unblock Encode(). If there are no free input buffers but there is a free
291 // output buffer, EncodeFrameFinished will be called later to unblock 307 // output buffer, EncodeFrameFinished will be called later to unblock
292 // Encode(). 308 // Encode().
293 // 309 //
294 // The caller of Encode() holds a webrtc lock. The deadlock happens when: 310 // The caller of Encode() holds a webrtc lock. The deadlock happens when:
295 // (1) Encode() is waiting for the frame to be encoded in EncodeOneFrame(). 311 // (1) Encode() is waiting for the frame to be encoded in EncodeOneFrame().
296 // (2) There are no free input buffers and they cannot be freed because 312 // (2) There are no free input buffers and they cannot be freed because
297 // the encoder has no output buffers. 313 // the encoder has no output buffers.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 DCHECK(thread_checker_.CalledOnValidThread()); 353 DCHECK(thread_checker_.CalledOnValidThread());
338 354
339 // Check for overflow converting bitrate (kilobits/sec) to bits/sec. 355 // Check for overflow converting bitrate (kilobits/sec) to bits/sec.
340 if (IsBitrateTooHigh(bitrate)) 356 if (IsBitrateTooHigh(bitrate))
341 return; 357 return;
342 358
343 if (video_encoder_) 359 if (video_encoder_)
344 video_encoder_->RequestEncodingParametersChange(bitrate * 1000, framerate); 360 video_encoder_->RequestEncodingParametersChange(bitrate * 1000, framerate);
345 } 361 }
346 362
347 void RTCVideoEncoder::Impl::Destroy() { 363 void RTCVideoEncoder::Impl::Destroy(base::WaitableEvent* waiter) {
348 DVLOG(3) << "Impl::Destroy()"; 364 DVLOG(3) << "Impl::Destroy()";
349 DCHECK(thread_checker_.CalledOnValidThread()); 365 DCHECK(thread_checker_.CalledOnValidThread());
350 video_encoder_.reset(); 366 video_encoder_.reset();
367 waiter->Signal();
351 } 368 }
352 369
353 void RTCVideoEncoder::Impl::RequireBitstreamBuffers( 370 void RTCVideoEncoder::Impl::RequireBitstreamBuffers(
354 unsigned int input_count, 371 unsigned int input_count,
355 const gfx::Size& input_coded_size, 372 const gfx::Size& input_coded_size,
356 size_t output_buffer_size) { 373 size_t output_buffer_size) {
357 DVLOG(3) << "Impl::RequireBitstreamBuffers(): input_count=" << input_count 374 DVLOG(3) << "Impl::RequireBitstreamBuffers(): input_count=" << input_count
358 << ", input_coded_size=" << input_coded_size.ToString() 375 << ", input_coded_size=" << input_coded_size.ToString()
359 << ", output_buffer_size=" << output_buffer_size; 376 << ", output_buffer_size=" << output_buffer_size;
360 DCHECK(thread_checker_.CalledOnValidThread()); 377 DCHECK(thread_checker_.CalledOnValidThread());
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 439
423 // Use webrtc timestamps to ensure correct RTP sender behavior. 440 // Use webrtc timestamps to ensure correct RTP sender behavior.
424 // TODO(hshi): obtain timestamp from the capturer, see crbug.com/350106. 441 // TODO(hshi): obtain timestamp from the capturer, see crbug.com/350106.
425 const int64_t capture_time_us = webrtc::TickTime::MicrosecondTimestamp(); 442 const int64_t capture_time_us = webrtc::TickTime::MicrosecondTimestamp();
426 443
427 // Derive the capture time (in ms) and RTP timestamp (in 90KHz ticks). 444 // Derive the capture time (in ms) and RTP timestamp (in 90KHz ticks).
428 const int64_t capture_time_ms = capture_time_us / 1000; 445 const int64_t capture_time_ms = capture_time_us / 1000;
429 const uint32_t rtp_timestamp = 446 const uint32_t rtp_timestamp =
430 static_cast<uint32_t>(capture_time_us * 90 / 1000); 447 static_cast<uint32_t>(capture_time_us * 90 / 1000);
431 448
432 scoped_ptr<webrtc::EncodedImage> image(new webrtc::EncodedImage( 449 scoped_ptr<webrtc::EncodedImage> image(new webrtc::EncodedImage(
pbos 2016/03/31 09:47:21 This can be stack allocated now, right?
wuchengli 2016/04/01 10:19:51 Yes. I'll update the code in the next patchset.
wuchengli 2016/04/03 14:28:01 Done.
433 reinterpret_cast<uint8_t*>(output_buffer->memory()), 450 reinterpret_cast<uint8_t*>(output_buffer->memory()),
434 payload_size, 451 payload_size,
435 output_buffer->mapped_size())); 452 output_buffer->mapped_size()));
436 image->_encodedWidth = input_visible_size_.width(); 453 image->_encodedWidth = input_visible_size_.width();
437 image->_encodedHeight = input_visible_size_.height(); 454 image->_encodedHeight = input_visible_size_.height();
438 image->_timeStamp = rtp_timestamp; 455 image->_timeStamp = rtp_timestamp;
439 image->capture_time_ms_ = capture_time_ms; 456 image->capture_time_ms_ = capture_time_ms;
440 image->_frameType = 457 image->_frameType =
441 (key_frame ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta); 458 (key_frame ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta);
442 image->_completeFrame = true; 459 image->_completeFrame = true;
443 460
444 encoder_task_runner_->PostTask( 461 ReturnEncodedImage(std::move(image), bitstream_buffer_id, picture_id_);
445 FROM_HERE,
446 base::Bind(&RTCVideoEncoder::ReturnEncodedImage, weak_encoder_,
447 base::Passed(&image), bitstream_buffer_id, picture_id_));
448 // Picture ID must wrap after reaching the maximum. 462 // Picture ID must wrap after reaching the maximum.
449 picture_id_ = (picture_id_ + 1) & 0x7FFF; 463 picture_id_ = (picture_id_ + 1) & 0x7FFF;
450 } 464 }
451 465
452 void RTCVideoEncoder::Impl::NotifyError( 466 void RTCVideoEncoder::Impl::NotifyError(
453 media::VideoEncodeAccelerator::Error error) { 467 media::VideoEncodeAccelerator::Error error) {
454 DCHECK(thread_checker_.CalledOnValidThread()); 468 DCHECK(thread_checker_.CalledOnValidThread());
455 int32_t retval; 469 int32_t retval;
456 switch (error) { 470 switch (error) {
457 case media::VideoEncodeAccelerator::kInvalidArgumentError: 471 case media::VideoEncodeAccelerator::kInvalidArgumentError:
458 retval = WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 472 retval = WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
459 break; 473 break;
460 default: 474 default:
461 retval = WEBRTC_VIDEO_CODEC_ERROR; 475 retval = WEBRTC_VIDEO_CODEC_ERROR;
462 } 476 }
463 477
464 video_encoder_.reset(); 478 video_encoder_.reset();
465 479
466 if (async_waiter_) { 480 if (async_waiter_) {
467 SignalAsyncWaiter(retval); 481 SignalAsyncWaiter(retval);
468 } else { 482 } else {
469 encoder_task_runner_->PostTask( 483 status_ = retval;
kcwu 2016/04/01 12:33:05 In the original code, if any error occurs, RTCVide
wuchengli 2016/04/03 14:28:01 Moved impl_status_ to Impl. Now all methods will c
470 FROM_HERE,
471 base::Bind(&RTCVideoEncoder::NotifyError, weak_encoder_, retval));
472 } 484 }
473 } 485 }
474 486
475 RTCVideoEncoder::Impl::~Impl() { DCHECK(!video_encoder_); } 487 RTCVideoEncoder::Impl::~Impl() { DCHECK(!video_encoder_); }
476 488
477 void RTCVideoEncoder::Impl::LogAndNotifyError( 489 void RTCVideoEncoder::Impl::LogAndNotifyError(
478 const tracked_objects::Location& location, 490 const tracked_objects::Location& location,
479 const std::string& str, 491 const std::string& str,
480 media::VideoEncodeAccelerator::Error error) { 492 media::VideoEncodeAccelerator::Error error) {
481 static const char* kErrorNames[] = { 493 static const char* kErrorNames[] = {
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
592 media::VideoEncodeAccelerator::kInvalidArgumentError); 604 media::VideoEncodeAccelerator::kInvalidArgumentError);
593 return true; 605 return true;
594 } 606 }
595 607
596 bool RTCVideoEncoder::Impl::RequiresSizeChange( 608 bool RTCVideoEncoder::Impl::RequiresSizeChange(
597 const scoped_refptr<media::VideoFrame>& frame) const { 609 const scoped_refptr<media::VideoFrame>& frame) const {
598 return (frame->coded_size() != input_frame_coded_size_ || 610 return (frame->coded_size() != input_frame_coded_size_ ||
599 frame->visible_rect() != gfx::Rect(input_visible_size_)); 611 frame->visible_rect() != gfx::Rect(input_visible_size_));
600 } 612 }
601 613
614 void RTCVideoEncoder::Impl::RegisterEncodeCompleteCallback(
615 base::WaitableEvent* waiter,
616 webrtc::EncodedImageCallback* callback) {
617 DCHECK(thread_checker_.CalledOnValidThread());
618 DVLOG(3) << "RegisterEncodeCompleteCallback()";
619 encoded_image_callback_ = callback;
620 waiter->Signal();
621 }
622
623 void RTCVideoEncoder::Impl::ReturnEncodedImage(
624 scoped_ptr<webrtc::EncodedImage> image,
pbos 2016/03/31 09:47:21 And this could be a const webrtc::EncodedImage&, n
wuchengli 2016/04/01 10:19:51 Yes. I'll update the code in the next patchset.
wuchengli 2016/04/03 14:28:01 Done.
625 int32_t bitstream_buffer_id,
626 uint16_t picture_id) {
627 DCHECK(thread_checker_.CalledOnValidThread());
628 DVLOG(3) << "ReturnEncodedImage(): "
629 << "bitstream_buffer_id=" << bitstream_buffer_id
630 << ", picture_id=" << picture_id;
631
632 if (!encoded_image_callback_)
633 return;
634
635 webrtc::RTPFragmentationHeader header;
636 memset(&header, 0, sizeof(header));
637 switch (video_codec_type_) {
638 case webrtc::kVideoCodecVP8:
639 // Generate a header describing a single fragment.
640 header.VerifyAndAllocateFragmentationHeader(1);
641 header.fragmentationOffset[0] = 0;
642 header.fragmentationLength[0] = image->_length;
643 header.fragmentationPlType[0] = 0;
644 header.fragmentationTimeDiff[0] = 0;
645 break;
646 case webrtc::kVideoCodecH264:
647 if (!GetRTPFragmentationHeaderH264(&header, image->_buffer,
648 image->_length)) {
649 DLOG(ERROR) << "Failed to get RTP fragmentation header for H264";
650 NotifyError(
651 (media::VideoEncodeAccelerator::Error)WEBRTC_VIDEO_CODEC_ERROR);
652 return;
653 }
654 break;
655 default:
656 NOTREACHED() << "Invalid video codec type";
657 return;
658 }
659
660 webrtc::CodecSpecificInfo info;
661 memset(&info, 0, sizeof(info));
662 info.codecType = video_codec_type_;
663 if (video_codec_type_ == webrtc::kVideoCodecVP8) {
664 info.codecSpecific.VP8.pictureId = picture_id;
665 info.codecSpecific.VP8.tl0PicIdx = -1;
666 info.codecSpecific.VP8.keyIdx = -1;
667 }
668
669 int32_t retval = encoded_image_callback_->Encoded(*image, &info, &header);
670 if (retval < 0) {
671 DVLOG(2) << "ReturnEncodedImage(): encoded_image_callback_ returned "
672 << retval;
673 }
674
675 UseOutputBitstreamBufferId(bitstream_buffer_id);
676 }
677
602 RTCVideoEncoder::RTCVideoEncoder( 678 RTCVideoEncoder::RTCVideoEncoder(
603 webrtc::VideoCodecType type, 679 webrtc::VideoCodecType type,
604 media::GpuVideoAcceleratorFactories* gpu_factories) 680 media::GpuVideoAcceleratorFactories* gpu_factories)
605 : video_codec_type_(type), 681 : video_codec_type_(type),
606 gpu_factories_(gpu_factories), 682 gpu_factories_(gpu_factories),
607 gpu_task_runner_(gpu_factories->GetTaskRunner()), 683 gpu_task_runner_(gpu_factories->GetTaskRunner()),
608 encoded_image_callback_(NULL), 684 impl_status_(WEBRTC_VIDEO_CODEC_UNINITIALIZED) {
kcwu 2016/04/01 12:33:05 impl_status_ becomes useless
wuchengli 2016/04/03 14:28:01 Removed. Added Impl.status_.
609 impl_status_(WEBRTC_VIDEO_CODEC_UNINITIALIZED),
610 weak_factory_(this) {
611 DVLOG(1) << "RTCVideoEncoder(): codec type=" << type; 685 DVLOG(1) << "RTCVideoEncoder(): codec type=" << type;
612 } 686 }
613 687
614 RTCVideoEncoder::~RTCVideoEncoder() { 688 RTCVideoEncoder::~RTCVideoEncoder() {
615 DVLOG(3) << "~RTCVideoEncoder"; 689 DVLOG(3) << "~RTCVideoEncoder";
616 DCHECK(thread_checker_.CalledOnValidThread());
617 Release(); 690 Release();
618 DCHECK(!impl_.get()); 691 DCHECK(!impl_.get());
619 } 692 }
620 693
621 int32_t RTCVideoEncoder::InitEncode(const webrtc::VideoCodec* codec_settings, 694 int32_t RTCVideoEncoder::InitEncode(const webrtc::VideoCodec* codec_settings,
622 int32_t number_of_cores, 695 int32_t number_of_cores,
623 size_t max_payload_size) { 696 size_t max_payload_size) {
624 DVLOG(1) << "InitEncode(): codecType=" << codec_settings->codecType 697 DVLOG(1) << "InitEncode(): codecType=" << codec_settings->codecType
625 << ", width=" << codec_settings->width 698 << ", width=" << codec_settings->width
626 << ", height=" << codec_settings->height 699 << ", height=" << codec_settings->height
627 << ", startBitrate=" << codec_settings->startBitrate; 700 << ", startBitrate=" << codec_settings->startBitrate;
628 DCHECK(thread_checker_.CalledOnValidThread());
629 DCHECK(!impl_.get()); 701 DCHECK(!impl_.get());
630 702
631 const media::VideoCodecProfile profile = 703 const media::VideoCodecProfile profile =
632 WebRTCVideoCodecToVideoCodecProfile(video_codec_type_, codec_settings); 704 WebRTCVideoCodecToVideoCodecProfile(video_codec_type_, codec_settings);
633 705
634 weak_factory_.InvalidateWeakPtrs(); 706 impl_ = new Impl(gpu_factories_, video_codec_type_);
635 impl_ = new Impl(weak_factory_.GetWeakPtr(), gpu_factories_);
636 base::WaitableEvent initialization_waiter(true, false); 707 base::WaitableEvent initialization_waiter(true, false);
637 int32_t initialization_retval = WEBRTC_VIDEO_CODEC_UNINITIALIZED; 708 int32_t initialization_retval = WEBRTC_VIDEO_CODEC_UNINITIALIZED;
638 gpu_task_runner_->PostTask( 709 gpu_task_runner_->PostTask(
639 FROM_HERE, 710 FROM_HERE,
640 base::Bind(&RTCVideoEncoder::Impl::CreateAndInitializeVEA, 711 base::Bind(&RTCVideoEncoder::Impl::CreateAndInitializeVEA,
641 impl_, 712 impl_,
642 gfx::Size(codec_settings->width, codec_settings->height), 713 gfx::Size(codec_settings->width, codec_settings->height),
643 codec_settings->startBitrate, 714 codec_settings->startBitrate,
644 profile, 715 profile,
645 &initialization_waiter, 716 &initialization_waiter,
(...skipping 30 matching lines...) Expand all
676 747
677 // webrtc::VideoEncoder expects this call to be synchronous. 748 // webrtc::VideoEncoder expects this call to be synchronous.
678 encode_waiter.Wait(); 749 encode_waiter.Wait();
679 DVLOG(3) << "Encode(): returning encode_retval=" << encode_retval; 750 DVLOG(3) << "Encode(): returning encode_retval=" << encode_retval;
680 return encode_retval; 751 return encode_retval;
681 } 752 }
682 753
683 int32_t RTCVideoEncoder::RegisterEncodeCompleteCallback( 754 int32_t RTCVideoEncoder::RegisterEncodeCompleteCallback(
684 webrtc::EncodedImageCallback* callback) { 755 webrtc::EncodedImageCallback* callback) {
685 DVLOG(3) << "RegisterEncodeCompleteCallback()"; 756 DVLOG(3) << "RegisterEncodeCompleteCallback()";
686 DCHECK(thread_checker_.CalledOnValidThread());
687 if (!impl_.get()) { 757 if (!impl_.get()) {
688 DVLOG(3) << "RegisterEncodeCompleteCallback(): returning " << impl_status_; 758 DVLOG(3) << "RegisterEncodeCompleteCallback(): returning " << impl_status_;
689 return impl_status_; 759 return impl_status_;
690 } 760 }
691 761
692 encoded_image_callback_ = callback; 762 base::WaitableEvent encode_waiter(true, false);
763 gpu_task_runner_->PostTask(
764 FROM_HERE,
765 base::Bind(&RTCVideoEncoder::Impl::RegisterEncodeCompleteCallback, impl_,
766 &encode_waiter, callback));
767 encode_waiter.Wait();
693 return WEBRTC_VIDEO_CODEC_OK; 768 return WEBRTC_VIDEO_CODEC_OK;
694 } 769 }
695 770
696 int32_t RTCVideoEncoder::Release() { 771 int32_t RTCVideoEncoder::Release() {
697 DVLOG(3) << "Release()"; 772 DVLOG(3) << "Release()";
698 DCHECK(thread_checker_.CalledOnValidThread());
699 773
700 if (impl_.get()) { 774 if (impl_.get()) {
701 gpu_task_runner_->PostTask(FROM_HERE, 775 base::WaitableEvent encode_waiter(true, false);
702 base::Bind(&RTCVideoEncoder::Impl::Destroy, impl_)); 776 gpu_task_runner_->PostTask(
777 FROM_HERE,
778 base::Bind(&RTCVideoEncoder::Impl::Destroy, impl_, &encode_waiter));
kcwu 2016/04/01 12:33:05 I'm wondering maybe we need to get async_retval he
wuchengli 2016/04/03 14:28:01 I don't think we should return error in Release. R
779 encode_waiter.Wait();
703 impl_ = NULL; 780 impl_ = NULL;
704 weak_factory_.InvalidateWeakPtrs();
705 impl_status_ = WEBRTC_VIDEO_CODEC_UNINITIALIZED; 781 impl_status_ = WEBRTC_VIDEO_CODEC_UNINITIALIZED;
706 } 782 }
707 return WEBRTC_VIDEO_CODEC_OK; 783 return WEBRTC_VIDEO_CODEC_OK;
708 } 784 }
709 785
710 int32_t RTCVideoEncoder::SetChannelParameters(uint32_t packet_loss, 786 int32_t RTCVideoEncoder::SetChannelParameters(uint32_t packet_loss,
711 int64_t rtt) { 787 int64_t rtt) {
712 DVLOG(3) << "SetChannelParameters(): packet_loss=" << packet_loss 788 DVLOG(3) << "SetChannelParameters(): packet_loss=" << packet_loss
713 << ", rtt=" << rtt; 789 << ", rtt=" << rtt;
714 // Ignored. 790 // Ignored.
(...skipping 10 matching lines...) Expand all
725 801
726 gpu_task_runner_->PostTask( 802 gpu_task_runner_->PostTask(
727 FROM_HERE, 803 FROM_HERE,
728 base::Bind(&RTCVideoEncoder::Impl::RequestEncodingParametersChange, 804 base::Bind(&RTCVideoEncoder::Impl::RequestEncodingParametersChange,
729 impl_, 805 impl_,
730 new_bit_rate, 806 new_bit_rate,
731 frame_rate)); 807 frame_rate));
732 return WEBRTC_VIDEO_CODEC_OK; 808 return WEBRTC_VIDEO_CODEC_OK;
733 } 809 }
734 810
735 void RTCVideoEncoder::ReturnEncodedImage(scoped_ptr<webrtc::EncodedImage> image,
736 int32_t bitstream_buffer_id,
737 uint16_t picture_id) {
738 DCHECK(thread_checker_.CalledOnValidThread());
739 DVLOG(3) << "ReturnEncodedImage(): "
740 << "bitstream_buffer_id=" << bitstream_buffer_id
741 << ", picture_id=" << picture_id;
742
743 if (!encoded_image_callback_)
744 return;
745
746 webrtc::RTPFragmentationHeader header;
747 memset(&header, 0, sizeof(header));
748 switch (video_codec_type_) {
749 case webrtc::kVideoCodecVP8:
750 // Generate a header describing a single fragment.
751 header.VerifyAndAllocateFragmentationHeader(1);
752 header.fragmentationOffset[0] = 0;
753 header.fragmentationLength[0] = image->_length;
754 header.fragmentationPlType[0] = 0;
755 header.fragmentationTimeDiff[0] = 0;
756 break;
757 case webrtc::kVideoCodecH264:
758 if (!GetRTPFragmentationHeaderH264(
759 &header, image->_buffer, image->_length)) {
760 DLOG(ERROR) << "Failed to get RTP fragmentation header for H264";
761 NotifyError(WEBRTC_VIDEO_CODEC_ERROR);
762 return;
763 }
764 break;
765 default:
766 NOTREACHED() << "Invalid video codec type";
767 return;
768 }
769
770 webrtc::CodecSpecificInfo info;
771 memset(&info, 0, sizeof(info));
772 info.codecType = video_codec_type_;
773 if (video_codec_type_ == webrtc::kVideoCodecVP8) {
774 info.codecSpecific.VP8.pictureId = picture_id;
775 info.codecSpecific.VP8.tl0PicIdx = -1;
776 info.codecSpecific.VP8.keyIdx = -1;
777 }
778
779 int32_t retval = encoded_image_callback_->Encoded(*image, &info, &header);
780 if (retval < 0) {
781 DVLOG(2) << "ReturnEncodedImage(): encoded_image_callback_ returned "
782 << retval;
783 }
784
785 // The call through webrtc::EncodedImageCallback is synchronous, so we can
786 // immediately recycle the output buffer back to the Impl.
787 gpu_task_runner_->PostTask(
788 FROM_HERE,
789 base::Bind(&RTCVideoEncoder::Impl::UseOutputBitstreamBufferId,
790 impl_,
791 bitstream_buffer_id));
792 }
793
794 void RTCVideoEncoder::NotifyError(int32_t error) {
795 DCHECK(thread_checker_.CalledOnValidThread());
796 DVLOG(1) << "NotifyError(): error=" << error;
797
798 impl_status_ = error;
799 gpu_task_runner_->PostTask(FROM_HERE,
800 base::Bind(&RTCVideoEncoder::Impl::Destroy, impl_));
801 impl_ = NULL;
802 }
803
804 void RTCVideoEncoder::RecordInitEncodeUMA( 811 void RTCVideoEncoder::RecordInitEncodeUMA(
805 int32_t init_retval, media::VideoCodecProfile profile) { 812 int32_t init_retval, media::VideoCodecProfile profile) {
806 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoEncoderInitEncodeSuccess", 813 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoEncoderInitEncodeSuccess",
807 init_retval == WEBRTC_VIDEO_CODEC_OK); 814 init_retval == WEBRTC_VIDEO_CODEC_OK);
808 if (init_retval == WEBRTC_VIDEO_CODEC_OK) { 815 if (init_retval == WEBRTC_VIDEO_CODEC_OK) {
809 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoEncoderProfile", 816 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoEncoderProfile",
810 profile, 817 profile,
811 media::VIDEO_CODEC_PROFILE_MAX + 1); 818 media::VIDEO_CODEC_PROFILE_MAX + 1);
812 } 819 }
813 } 820 }
814 821
815 } // namespace content 822 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/media/rtc_video_encoder.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698