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

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

Issue 20632002: Add media::VideoEncodeAccelerator with WebRTC integration (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@git-svn
Patch Set: fcfd089c More comments addressed. Created 7 years, 4 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "content/renderer/media/rtc_video_encoder.h"
6
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "base/logging.h"
10 #include "base/memory/scoped_vector.h"
11 #include "base/message_loop/message_loop_proxy.h"
12 #include "base/synchronization/waitable_event.h"
13 #include "content/renderer/media/renderer_gpu_video_accelerator_factories.h"
14 #include "media/base/bitstream_buffer.h"
15 #include "media/base/video_frame.h"
16 #include "media/filters/gpu_video_accelerator_factories.h"
17 #include "media/video/video_encode_accelerator.h"
18
19 #define NOTIFY_ERROR(x) \
20 do { \
21 DLOG(ERROR) << "calling NotifyError(): " << x; \
22 NotifyError(x); \
23 } while (0)
24
25 namespace content {
26
27 // This private class of RTCVideoEncoder does the actual work of communicating
28 // with a media::VideoEncodeAccelerator for handling video encoding. It can
29 // be created on any thread, but should subsequently be posted to (and Destroy()
30 // called on) a single thread. Callbacks to RTCVideoEncoder are posted to the
31 // thread on which the instance was constructed.
32 //
33 // This class separates state related to the thread that RTCVideoEncoder
34 // operates on (presently the libjingle worker thread) from the thread that
35 // |gpu_factories_| provides for accelerator operations (presently the media
36 // thread). The RTCVideoEncoder class can be deleted directly by WebRTC, while
37 // RTCVideoEncoder::Impl stays around long enough to properly shut down the VEA.
38 class RTCVideoEncoder::Impl
39 : public media::VideoEncodeAccelerator::Client,
40 public base::RefCountedThreadSafe<RTCVideoEncoder::Impl> {
41 public:
42 explicit Impl(
Ami GONE FROM CHROMIUM 2013/08/06 20:41:13 explicit no longer necessary
sheu 2013/08/07 09:25:03 Done.
43 const base::WeakPtr<RTCVideoEncoder>& weak_encoder,
44 const scoped_refptr<RendererGpuVideoAcceleratorFactories>& gpu_factories);
45
46 // Create the VEA and call Initialize() on it. Called once per instantiation,
47 // and then the instance is then bound forevermore to whichever thread made
Ami GONE FROM CHROMIUM 2013/08/06 20:41:13 s/is then/is/
sheu 2013/08/07 09:25:03 Done.
48 // the call.
49 // WebRTC expects this call to be synchronous.
Ami GONE FROM CHROMIUM 2013/08/06 20:41:13 This sentence is out of place here considering thi
sheu 2013/08/07 09:25:03 Done.
50 void CreateAndInitializeVEA(const gfx::Size& input_visible_size,
51 int32 bitrate,
52 media::VideoCodecProfile profile,
53 base::WaitableEvent* async_waiter,
54 int32_t* async_retval);
55 // Enqueue a frame from WebRTC for encoding. WebRTC expects this call to be
56 // synchronous.
57 void Enqueue(const webrtc::I420VideoFrame* input_frame,
58 bool force_keyframe,
59 base::WaitableEvent* async_waiter,
60 int32_t* async_retval);
61 // These can be asynchronous to WebRTC.
62 void UseOutputBitstreamBufferId(int32 bitstream_buffer_id);
63 void RequestEncodingParameterChange(int32 bitrate);
64 void Destroy();
Ami GONE FROM CHROMIUM 2013/08/06 20:41:13 No you didn't.
sheu 2013/08/07 09:25:03 I added one more. I suppose you want more than th
Ami GONE FROM CHROMIUM 2013/08/07 21:07:15 I wanted the doco to talk about how it deletes thi
65
66 // media::VideoEncodeAccelerator::Client implementation.
67 virtual void NotifyInitializeDone() OVERRIDE;
68 virtual void RequireBitstreamBuffers(int input_count,
69 const gfx::Size& input_coded_size,
70 size_t output_buffer_size) OVERRIDE;
71 virtual void BitstreamBufferReady(int32 bitstream_buffer_id,
72 size_t payload_size,
73 bool key_frame) OVERRIDE;
74 virtual void NotifyError(media::VideoEncodeAccelerator::Error error) OVERRIDE;
75
76 private:
77 friend class base::RefCountedThreadSafe<Impl>;
78
79 enum {
80 kInputBufferExtraCount = 1, // The number of input buffers allocated, more
81 // than what is requested by
82 // VEA::RequireBitstreamBuffers().
83 kOutputBufferCount = 3,
84 };
85
86 virtual ~Impl();
87
88 // Perform encoding on an input frame from the input queue.
89 void EncodeOneFrame();
90
91 // Notify that an input frame is finished for encoding. |index| is the index
92 // of the completed frame in |input_buffers_|.
93 void EncodeFrameFinished(int index);
94
95 // Set up/signal |async_waiter_| and |async_retval_|; see declarations below.
96 void RegisterAsyncWaiter(base::WaitableEvent* waiter, int32_t* retval);
97 void SignalAsyncWaiter(int32_t retval);
98
99 base::ThreadChecker thread_checker_;
100
101 // Weak pointer to the parent RTCVideoEncoder, for posting back VEA::Client
102 // notifications.
103 const base::WeakPtr<RTCVideoEncoder> weak_encoder_;
104
105 // The message loop on which to post callbacks to |weak_encoder_|.
106 const scoped_refptr<base::MessageLoopProxy> encoder_message_loop_proxy_;
107
108 // Factory for creating VEAs, shared memory buffers, etc.
109 const scoped_refptr<RendererGpuVideoAcceleratorFactories> gpu_factories_;
110
111 // webrtc::VideoEncoder expects InitEncode() and Encode() to be synchronous.
112 // Do this by waiting on the |async_waiter_| and returning the return value in
113 // |async_retval_| when initialization completes, encoding completes, or
114 // an error occurs.
115 base::WaitableEvent* async_waiter_;
116 int32_t* async_retval_;
117
118 // The underlying VEA to perform encoding on.
119 scoped_ptr<media::VideoEncodeAccelerator> video_encoder_;
120
121 // Next input frame. Since there is at most one next frame, a single-element
122 // queue is sufficient.
123 const webrtc::I420VideoFrame* input_next_frame_;
124
125 // Whether to encode a keyframe next.
126 bool input_next_frame_keyframe_;
127
128 // Frame sizes.
129 gfx::Size input_frame_coded_size_;
130 gfx::Size input_visible_size_;
131
132 // Shared memory buffers for input/output with the VEA.
133 ScopedVector<base::SharedMemory> input_buffers_;
134 ScopedVector<base::SharedMemory> output_buffers_;
135
136 // Input buffers ready to be filled with input from Encode(). As a LIFO since
137 // we don't care about ordering.
138 std::vector<int> input_buffers_free_;
139
140 DISALLOW_COPY_AND_ASSIGN(Impl);
141 };
142
143 RTCVideoEncoder::Impl::Impl(
144 const base::WeakPtr<RTCVideoEncoder>& weak_encoder,
145 const scoped_refptr<RendererGpuVideoAcceleratorFactories>& gpu_factories)
146 : weak_encoder_(weak_encoder),
147 encoder_message_loop_proxy_(base::MessageLoopProxy::current()),
148 gpu_factories_(gpu_factories),
149 async_waiter_(NULL),
150 async_retval_(NULL),
151 input_next_frame_(NULL),
152 input_next_frame_keyframe_(false) {
153 thread_checker_.DetachFromThread();
154 }
155
156 void RTCVideoEncoder::Impl::CreateAndInitializeVEA(
157 const gfx::Size& input_visible_size,
158 int32 bitrate,
159 media::VideoCodecProfile profile,
160 base::WaitableEvent* async_waiter,
161 int32_t* async_retval) {
162 DVLOG(3) << "Impl::CreateAndInitializeVEA()";
163 DCHECK(thread_checker_.CalledOnValidThread());
164
165 RegisterAsyncWaiter(async_waiter, async_retval);
166
167 // Check for overflow converting codecSettings.startBitrate (kilobits/sec) to
168 // bits/sec.
169 if (bitrate > kint32max / 1000) {
170 NOTIFY_ERROR(media::VideoEncodeAccelerator::kInvalidArgumentError);
171 return;
172 }
173
174 video_encoder_ = gpu_factories_->CreateVideoEncodeAccelerator(this).Pass();
175 if (!video_encoder_) {
176 NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError);
177 return;
178 }
179 input_visible_size_ = input_visible_size;
180 video_encoder_->Initialize(media::VideoFrame::I420,
181 input_visible_size_,
182 profile,
183 bitrate * 1000);
184 }
185
186 void RTCVideoEncoder::Impl::Enqueue(const webrtc::I420VideoFrame* input_frame,
187 bool force_keyframe,
188 base::WaitableEvent* async_waiter,
189 int32_t* async_retval) {
190 DVLOG(3) << "Impl::Enqueue()";
191 DCHECK(thread_checker_.CalledOnValidThread());
192 DCHECK(!input_next_frame_);
193
194 RegisterAsyncWaiter(async_waiter, async_retval);
195 input_next_frame_ = input_frame;
196 input_next_frame_keyframe_ = force_keyframe;
197
198 if (!input_buffers_free_.empty())
199 EncodeOneFrame();
200 }
201
202 void RTCVideoEncoder::Impl::UseOutputBitstreamBufferId(
203 int32 bitstream_buffer_id) {
204 DVLOG(3) << "Impl::UseOutputBitstreamBufferIndex(): "
205 "bitstream_buffer_id=" << bitstream_buffer_id;
206 DCHECK(thread_checker_.CalledOnValidThread());
207 if (video_encoder_) {
208 video_encoder_->UseOutputBitstreamBuffer(media::BitstreamBuffer(
209 bitstream_buffer_id,
210 output_buffers_[bitstream_buffer_id]->handle(),
211 output_buffers_[bitstream_buffer_id]->mapped_size()));
212 }
213 }
214
215 void RTCVideoEncoder::Impl::RequestEncodingParameterChange(int32 bitrate) {
216 DVLOG(3) << "Impl::RequestEncodingParameterChange(): bitrate=" << bitrate;
217 DCHECK(thread_checker_.CalledOnValidThread());
218 if (video_encoder_)
219 video_encoder_->RequestEncodingParameterChange(bitrate);
220 }
221
222 void RTCVideoEncoder::Impl::Destroy() {
223 DVLOG(3) << "Impl::Destroy()";
224 DCHECK(thread_checker_.CalledOnValidThread());
225 if (video_encoder_)
226 video_encoder_.release()->Destroy();
227 }
228
229 void RTCVideoEncoder::Impl::NotifyInitializeDone() {
230 DVLOG(3) << "Impl::NotifyInitializeDone()";
231 DCHECK(thread_checker_.CalledOnValidThread());
232 SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_OK);
233 }
234
235 void RTCVideoEncoder::Impl::RequireBitstreamBuffers(
236 int input_count,
237 const gfx::Size& input_coded_size,
238 size_t output_buffer_size) {
239 DVLOG(3) << "Impl::RequireBitstreamBuffers(): input_count=" << input_count
240 << ", input_coded_size=" << input_coded_size.ToString()
241 << ", output_buffer_size=" << output_buffer_size;
242 DCHECK(thread_checker_.CalledOnValidThread());
243
244 if (!video_encoder_)
245 return;
246
247 input_frame_coded_size_ = input_coded_size;
248
249 for (int i = 0; i < input_count + kInputBufferExtraCount; ++i) {
250 base::SharedMemory* shm =
251 gpu_factories_->CreateSharedMemory(input_coded_size.GetArea() * 3 / 2);
252 if (!shm) {
253 DLOG(ERROR) << "Impl::RequireBitstreamBuffers(): "
254 "failed to create input buffer " << i;
255 NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError);
256 return;
257 }
258 input_buffers_.push_back(shm);
259 input_buffers_free_.push_back(i);
260 }
261
262 for (int i = 0; i < kOutputBufferCount; ++i) {
263 base::SharedMemory* shm =
264 gpu_factories_->CreateSharedMemory(output_buffer_size);
265 if (!shm) {
266 DLOG(ERROR) << "Impl::RequireBitstreamBuffers(): "
267 "failed to create output buffer " << i;
268 NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError);
269 return;
270 }
271 output_buffers_.push_back(shm);
272 }
273
274 // Immediately provide all output buffers to the VEA.
275 for (size_t i = 0; i < output_buffers_.size(); ++i) {
276 video_encoder_->UseOutputBitstreamBuffer(media::BitstreamBuffer(
277 i, output_buffers_[i]->handle(), output_buffers_[i]->mapped_size()));
278 }
279 }
280
281 void RTCVideoEncoder::Impl::BitstreamBufferReady(int32 bitstream_buffer_id,
282 size_t payload_size,
283 bool key_frame) {
284 DVLOG(3) << "Impl::BitstreamBufferReady(): "
285 "bitstream_buffer_id=" << bitstream_buffer_id
286 << ", payload_size=" << payload_size
287 << ", key_frame=" << key_frame;
288 DCHECK(thread_checker_.CalledOnValidThread());
289
290 if (bitstream_buffer_id < 0 ||
291 bitstream_buffer_id >= static_cast<int>(output_buffers_.size())) {
292 DLOG(ERROR) << "Impl::BitstreamBufferReady(): invalid bitstream_buffer_id="
293 << bitstream_buffer_id;
294 NOTIFY_ERROR(media::VideoEncodeAccelerator::kInvalidArgumentError);
Ami GONE FROM CHROMIUM 2013/08/06 20:41:13 No, it's an invalid argument coming from the VEA i
sheu 2013/08/07 09:25:03 BitstreamBufferReady is part of the VEA::Client in
295 return;
296 }
297 base::SharedMemory* output_buffer = output_buffers_[bitstream_buffer_id];
298 if (payload_size > output_buffer->mapped_size()) {
299 DLOG(ERROR) << "Impl::BitstreamBufferReady(): invalid payload_size="
300 << payload_size;
301 NOTIFY_ERROR(media::VideoEncodeAccelerator::kInvalidArgumentError);
302 return;
303 }
304
305 scoped_ptr<webrtc::EncodedImage> image(new webrtc::EncodedImage(
306 reinterpret_cast<uint8_t*>(output_buffer->memory()),
307 payload_size,
308 output_buffer->mapped_size()));
309 image->_encodedWidth = input_visible_size_.width();
310 image->_encodedHeight = input_visible_size_.height();
311 image->_frameType = (key_frame ? webrtc::kKeyFrame : webrtc::kDeltaFrame);
312 image->_completeFrame = true;
313
314 encoder_message_loop_proxy_->PostTask(
315 FROM_HERE,
316 base::Bind(&RTCVideoEncoder::ReturnEncodedImage,
317 weak_encoder_,
318 make_scoped_refptr(this),
319 base::Passed(&image),
320 bitstream_buffer_id));
321 }
322
323 void RTCVideoEncoder::Impl::NotifyError(
324 media::VideoEncodeAccelerator::Error error) {
325 DVLOG(3) << "Impl::NotifyError(): error=" << error;
326 DCHECK(thread_checker_.CalledOnValidThread());
327 int32_t retval;
328 switch (error) {
329 case media::VideoEncodeAccelerator::kInvalidArgumentError:
330 retval = WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
331 break;
332 case media::VideoEncodeAccelerator::kPlatformFailureError:
333 retval = WEBRTC_VIDEO_CODEC_MEMORY;
Ami GONE FROM CHROMIUM 2013/08/06 20:41:13 I guess s/MEMORY/ERROR/ (better to be vague than
sheu 2013/08/07 09:25:03 Most kPlatformFailureErrors are memory-related I t
Ami GONE FROM CHROMIUM 2013/08/07 21:07:15 I worry that MEMORY is specific enough that it'll
334 break;
335 default:
336 retval = WEBRTC_VIDEO_CODEC_ERROR;
337 }
338
339 if (video_encoder_)
340 video_encoder_.release()->Destroy();
341
342 if (async_waiter_) {
343 SignalAsyncWaiter(retval);
344 } else {
345 encoder_message_loop_proxy_->PostTask(
346 FROM_HERE,
347 base::Bind(&RTCVideoEncoder::NotifyError,
348 weak_encoder_,
349 make_scoped_refptr(this),
350 retval));
351 }
352 }
353
354 RTCVideoEncoder::Impl::~Impl() { DCHECK(!video_encoder_); }
355
356 void RTCVideoEncoder::Impl::EncodeOneFrame() {
357 DVLOG(3) << "Impl::EncodeOneFrame()";
358 DCHECK(thread_checker_.CalledOnValidThread());
359 DCHECK(input_next_frame_);
360 DCHECK(!input_buffers_free_.empty());
361
362 const int index = input_buffers_free_.back();
363 base::SharedMemory* input_buffer = input_buffers_[index];
sheu 2013/08/07 09:25:03 Actually now that I think of it, I should move the
364
365 if (video_encoder_) {
Ami GONE FROM CHROMIUM 2013/08/06 20:41:13 Isn't the negation an error condition?
sheu 2013/08/07 09:25:03 It is, but I'd still like to leave the Impl in a s
366 // Do a strided copy of the input frame to match the input requirements for
367 // the encoder.
Ami GONE FROM CHROMIUM 2013/08/06 20:41:13 Please add a TODO pointing to a crbug for the rema
sheu 2013/08/07 09:25:03 Done.
368 const uint8_t* src = input_next_frame_->buffer(webrtc::kYPlane);
369 uint8* dst = reinterpret_cast<uint8*>(input_buffer->memory());
370 uint8* const y_dst = dst;
371 int width = input_frame_coded_size_.width();
372 int stride = input_next_frame_->stride(webrtc::kYPlane);
373 for (int i = 0; i < input_next_frame_->height(); ++i) {
374 memcpy(dst, src, width);
375 src += stride;
376 dst += width;
sheu 2013/08/06 06:16:36 Teehee The benefits of not testing
377 }
378 src = input_next_frame_->buffer(webrtc::kUPlane);
379 width = input_frame_coded_size_.width() / 2;
380 stride = input_next_frame_->stride(webrtc::kUPlane);
381 uint8* const u_dst = dst;
382 for (int i = 0; i < input_next_frame_->height() / 2; ++i) {
383 memcpy(dst, src, width);
384 src += stride;
385 dst += width;
386 }
387 src = input_next_frame_->buffer(webrtc::kVPlane);
388 width = input_frame_coded_size_.width() / 2;
389 stride = input_next_frame_->stride(webrtc::kVPlane);
390 uint8* const v_dst = dst;
391 for (int i = 0; i < input_next_frame_->height() / 2; ++i) {
392 memcpy(dst, src, width);
393 src += stride;
394 dst += width;
395 }
396
397 scoped_refptr<media::VideoFrame> frame =
398 media::VideoFrame::WrapExternalYuvData(
399 media::VideoFrame::I420,
400 input_frame_coded_size_,
401 gfx::Rect(input_visible_size_),
402 input_visible_size_,
403 input_frame_coded_size_.width(),
404 input_frame_coded_size_.width() / 2,
405 input_frame_coded_size_.width() / 2,
406 y_dst,
407 u_dst,
408 v_dst,
409 base::TimeDelta(),
410 input_buffer->handle(),
411 base::Bind(
412 &RTCVideoEncoder::Impl::EncodeFrameFinished, this, index));
413 video_encoder_->Encode(frame, input_next_frame_keyframe_);
414 }
415
416 input_next_frame_ = NULL;
417 input_next_frame_keyframe_ = false;
418 input_buffers_free_.pop_back();
419
420 SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_OK);
421 }
422
423 void RTCVideoEncoder::Impl::EncodeFrameFinished(int index) {
424 DVLOG(3) << "Impl::EncodeFrameFinished(): index=" << index;
425 DCHECK(thread_checker_.CalledOnValidThread());
426 DCHECK_GE(index, 0);
427 DCHECK_LT(index, static_cast<int>(input_buffers_.size()));
428 input_buffers_free_.push_back(index);
429 if (input_next_frame_)
430 EncodeOneFrame();
431 }
432
433 void RTCVideoEncoder::Impl::RegisterAsyncWaiter(base::WaitableEvent* waiter,
434 int32_t* retval) {
435 DCHECK(thread_checker_.CalledOnValidThread());
436 DCHECK(!async_waiter_);
437 DCHECK(!async_retval_);
438 async_waiter_ = waiter;
439 async_retval_ = retval;
440 }
441
442 void RTCVideoEncoder::Impl::SignalAsyncWaiter(int32_t retval) {
443 DCHECK(thread_checker_.CalledOnValidThread());
444 *async_retval_ = retval;
445 async_waiter_->Signal();
446 async_retval_ = NULL;
447 async_waiter_ = NULL;
448 }
449
450 ////////////////////////////////////////////////////////////////////////////////
451 //
452 // RTCVideoEncoder
453 //
454 ////////////////////////////////////////////////////////////////////////////////
455
456 #undef NOTIFY_ERROR
Ami GONE FROM CHROMIUM 2013/08/06 20:41:13 go above separator
sheu 2013/08/07 09:25:03 Done.
457
458 RTCVideoEncoder::RTCVideoEncoder(
459 media::VideoCodecProfile profile,
460 const scoped_refptr<RendererGpuVideoAcceleratorFactories>& gpu_factories)
461 : video_codec_profile_(profile),
462 gpu_factories_(gpu_factories),
463 weak_this_factory_(this),
464 weak_this_(weak_this_factory_.GetWeakPtr()),
465 encoded_image_callback_(NULL),
466 impl_status_(WEBRTC_VIDEO_CODEC_UNINITIALIZED) {
467 DVLOG(1) << "RTCVideoEncoder(): profile=" << profile;
468 }
469
470 RTCVideoEncoder::~RTCVideoEncoder() {
471 DCHECK(thread_checker_.CalledOnValidThread());
472 Release();
473 DCHECK(!impl_);
474 }
475
476 int32_t RTCVideoEncoder::InitEncode(const webrtc::VideoCodec* codec_settings,
477 int32_t number_of_cores,
478 uint32_t max_payload_size) {
479 DVLOG(1) << "InitEncode(): codecType=" << codec_settings->codecType
480 << ", width=" << codec_settings->width
481 << ", height=" << codec_settings->height
482 << ", startBitrate=" << codec_settings->startBitrate;
483 DCHECK(thread_checker_.CalledOnValidThread());
484 DCHECK(!impl_);
485
486 impl_ = new Impl(weak_this_, gpu_factories_);
487 base::WaitableEvent initialization_waiter(true, false);
488 int32_t initialization_retval = WEBRTC_VIDEO_CODEC_UNINITIALIZED;
Ami GONE FROM CHROMIUM 2013/08/06 20:41:13 What does that mean?
sheu 2013/08/07 09:25:03 Yeah ok that made no sense. Anyways I was thinkin
489 gpu_factories_->GetMessageLoop()->PostTask(
490 FROM_HERE,
491 base::Bind(&RTCVideoEncoder::Impl::CreateAndInitializeVEA,
492 impl_,
493 gfx::Size(codec_settings->width, codec_settings->height),
494 codec_settings->startBitrate,
495 video_codec_profile_,
496 &initialization_waiter,
497 &initialization_retval));
498
499 // webrtc::VideoEncoder expects this call to be synchronous.
500 initialization_waiter.Wait();
501 return initialization_retval;
502 }
503
504 int32_t RTCVideoEncoder::Encode(
505 const webrtc::I420VideoFrame& input_image,
506 const webrtc::CodecSpecificInfo* codec_specific_info,
507 const std::vector<webrtc::VideoFrameType>* frame_types) {
508 DVLOG(3) << "Encode()";
509 // DCHECK(thread_checker_.CalledOnValidThread());
Ami GONE FROM CHROMIUM 2013/08/06 20:41:13 Big-ass TODO please, then.
sheu 2013/08/07 09:25:03 Done.
510 if (!impl_) {
511 DVLOG(3) << "Encode(): returning impl_status_=" << impl_status_;
512 return impl_status_;
513 }
514
515 base::WaitableEvent encode_waiter(true, false);
516 int32_t encode_retval = WEBRTC_VIDEO_CODEC_UNINITIALIZED;
517 gpu_factories_->GetMessageLoop()->PostTask(
518 FROM_HERE,
519 base::Bind(&RTCVideoEncoder::Impl::Enqueue,
520 impl_,
521 &input_image,
522 (frame_types->front() == webrtc::kKeyFrame),
523 &encode_waiter,
524 &encode_retval));
525
526 // webrtc::VideoEncoder expects this call to be synchronous.
527 encode_waiter.Wait();
528 DVLOG(3) << "Encode(): returning encode_retval=" << encode_retval;
529 return encode_retval;
530 }
531
532 int32_t RTCVideoEncoder::RegisterEncodeCompleteCallback(
533 webrtc::EncodedImageCallback* callback) {
534 DVLOG(3) << "RegisterEncodeCompleteCallback()";
535 DCHECK(thread_checker_.CalledOnValidThread());
536 if (!impl_) {
537 DVLOG(3) << "RegisterEncodeCompleteCallback(): returning " << impl_status_;
538 return impl_status_;
539 }
540
541 encoded_image_callback_ = callback;
542 return WEBRTC_VIDEO_CODEC_OK;
543 }
544
545 int32_t RTCVideoEncoder::Release() {
546 DVLOG(3) << "Release()";
547 DCHECK(thread_checker_.CalledOnValidThread());
548
549 // Reset the gpu_factory_, in case we reuse this encoder.
550 gpu_factories_->Abort();
551 gpu_factories_ = gpu_factories_->Clone();
552 if (impl_) {
553 gpu_factories_->GetMessageLoop()->PostTask(
554 FROM_HERE, base::Bind(&RTCVideoEncoder::Impl::Destroy, impl_));
555 impl_ = NULL;
556 impl_status_ = WEBRTC_VIDEO_CODEC_UNINITIALIZED;
557 }
558 return WEBRTC_VIDEO_CODEC_OK;
559 }
560
561 int32_t RTCVideoEncoder::SetChannelParameters(uint32_t packet_loss, int rtt) {
562 DVLOG(3) << "SetChannelParameters(): packet_loss=" << packet_loss
563 << ", rtt=" << rtt;
564 DCHECK(thread_checker_.CalledOnValidThread());
565 // Ignored.
566 return WEBRTC_VIDEO_CODEC_OK;
567 }
568
569 int32_t RTCVideoEncoder::SetRates(uint32_t new_bit_rate,
570 uint32_t /* ignored_frame_rate */) {
571 DVLOG(3) << "SetRates(): new_bit_rate=" << new_bit_rate;
572 DCHECK(thread_checker_.CalledOnValidThread());
573 if (!impl_) {
574 DVLOG(3) << "SetRates(): returning " << impl_status_;
575 return impl_status_;
576 }
577
578 gpu_factories_->GetMessageLoop()->PostTask(
579 FROM_HERE,
580 base::Bind(&RTCVideoEncoder::Impl::RequestEncodingParameterChange,
581 impl_,
582 new_bit_rate));
583 return WEBRTC_VIDEO_CODEC_OK;
584 }
585
586 void RTCVideoEncoder::ReturnEncodedImage(const scoped_refptr<Impl>& impl,
587 scoped_ptr<webrtc::EncodedImage> image,
588 int32 bitstream_buffer_id) {
589 DCHECK(thread_checker_.CalledOnValidThread());
590
591 if (impl != impl_)
592 return;
593
594 DVLOG(3) << "ReturnEncodedImage(): "
595 "bitstream_buffer_id=" << bitstream_buffer_id;
596
597 if (!encoded_image_callback_)
598 return;
599
600 int32_t retval = encoded_image_callback_->Encoded(*image, NULL, NULL);
601 if (retval < 0) {
602 DLOG(ERROR) << "ReturnEncodedImage(): encoded_image_callback_ returned "
603 << retval;
604 NotifyError(impl_, retval);
605 return;
606 }
607
608 // The call through webrtc::EncodedImageCallback is synchronous, so we can
609 // immediately recycle the output buffer back to the Impl.
610 gpu_factories_->GetMessageLoop()->PostTask(
611 FROM_HERE,
612 base::Bind(&RTCVideoEncoder::Impl::UseOutputBitstreamBufferId,
613 impl_,
614 bitstream_buffer_id));
615 }
616
617 void RTCVideoEncoder::NotifyError(const scoped_refptr<Impl>& impl,
618 int32_t error) {
619 DCHECK(thread_checker_.CalledOnValidThread());
620
621 if (!impl_)
Ami GONE FROM CHROMIUM 2013/08/06 20:41:13 impossible given l.623 (and the fact that the only
sheu 2013/08/07 09:25:03 Done.
622 return;
623 if (impl != impl_)
624 return;
625
626 DVLOG(1) << "NotifyError(): error=" << error;
627
628 impl_status_ = error;
629 gpu_factories_->GetMessageLoop()->PostTask(
630 FROM_HERE, base::Bind(&RTCVideoEncoder::Impl::Destroy, impl_));
631 impl_ = NULL;
632 }
633
634 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698