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

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: 2247fd82 Rebase. 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 "media/base/bitstream_buffer.h"
14 #include "media/filters/gpu_video_accelerator_factories.h"
15 #include "media/video/video_encode_accelerator.h"
16
17 #define NOTIFY_ERROR(x) \
18 do { \
19 DLOG(ERROR) << "calling NotifyError(): " << x; \
20 NotifyError(x); \
21 } while (0)
22
23 namespace content {
24
25 // This private class of RTCVideoEncoder does the actual work of communicating
26 // with a media::VideoEncodeAccelerator for handling video encoding. It can
27 // be created on any thread, but should subsequently be posted to (and Destroy()
28 // called on) the thread that calls CreateAndInitializeVEA(). Notifications
29 // returned by the encoder are posted to the thread on which the instance was
30 // constructed.
31 //
32 // This class is separated from the RTCVideoEncoder class to allow
33 // RTCVideoEncoder to be deleted directly by WebRTC, while RTCVideoEncoder::Impl
34 // stays long enough to properly shut down the VEA.
Ami GONE FROM CHROMIUM 2013/08/02 22:00:49 You seem to have missed my super-insight into why
sheu 2013/08/03 01:31:03 I moved state around and so pimpl is making more s
35 class RTCVideoEncoder::Impl
36 : public media::VideoEncodeAccelerator::Client,
37 public base::RefCountedThreadSafe<RTCVideoEncoder::Impl> {
38 public:
39 explicit Impl(const base::WeakPtr<RTCVideoEncoder>& weak_encoder);
40
41 // Create the VEA and call Initialize() on it. This instance of Impl is bound
42 // to whichever thread makes this call.
43 void CreateAndInitializeVEA(
44 const webrtc::VideoCodec& codecSettings,
45 media::VideoCodecProfile profile,
46 base::WaitableEvent* async_waiter,
47 int32_t* async_retval,
48 const scoped_refptr<media::GpuVideoAcceleratorFactories>& gpu_factories);
49 void Enqueue(const webrtc::I420VideoFrame* input_frame, bool force_keyframe,
50 base::WaitableEvent* async_waiter, int32_t* async_retval);
51 void UseOutputBitstreamBufferId(int32 bitstream_buffer_id);
52 void RequestEncodingParameterChange(int32 bitrate);
53 void Destroy();
54
55 // media::VideoEncodeAccelerator::Client implementation.
56 virtual void NotifyInitializeDone() OVERRIDE;
57 virtual void RequireBitstreamBuffers(int input_count,
58 const gfx::Size& input_dimensions,
59 size_t output_size) OVERRIDE;
60 virtual void NotifyInputDone(int32 bitstream_buffer_id) OVERRIDE;
61 virtual void BitstreamBufferReady(int32 bitstream_buffer_id,
62 size_t payload_size,
63 bool key_frame) OVERRIDE;
64 virtual void NotifyError(media::VideoEncodeAccelerator::Error error) OVERRIDE;
65
66 private:
67 friend class base::RefCountedThreadSafe<Impl>;
68
69 enum {
70 kInputBufferExtraCount = 1, // The number of input buffers allocated, more
71 // than what is requested by
72 // VEA::RequireBitstreamBuffers().
73 kOutputBufferCount = 3,
74 };
75
76 virtual ~Impl();
77
78 // Perform encoding on an input frame from the input queue.
79 void EncodeOneFrame();
80
81 base::ThreadChecker thread_checker_;
82
83 // Weak pointer to the parent RTCVideoEncoder, for posting back VEA::Client
84 // notifications.
85 const base::WeakPtr<RTCVideoEncoder> weak_encoder_;
86
87 // Factory for creating VEAs, shared memory buffers, etc.
88 scoped_refptr<media::GpuVideoAcceleratorFactories> gpu_factories_;
89
90 // The message loop on which to post notifications.
91 const scoped_refptr<base::MessageLoopProxy> encoder_message_loop_proxy_;
92
93 // webrtc::VideoEncoder expects InitEncode() and Encode() to be synchronous.
94 // Do this by waiting on the |async_waiter_| and returning the return value in
95 // |async_retval_| when we initialization completes, encoding completes, or
96 // an error occurs.
97 base::WaitableEvent* async_waiter_;
98 int32_t* async_retval_;
99
100 // The underling VEA to perform encoding on.
101 scoped_ptr<media::VideoEncodeAccelerator> video_encoder_;
102
103 // Next input frame. Since there is at most one next frame, a single-element
104 // queue is sufficient.
105 const webrtc::I420VideoFrame* input_next_frame_;
106
107 // Whether to encode a keyframe next.
108 bool input_next_frame_keyframe_;
109
110 // Frame sizes.
111 gfx::Size input_frame_dimensions_;
112 gfx::Size output_frame_dimensions_;
113
114 // Shared memory buffers for input/output with the VEA.
115 ScopedVector<base::SharedMemory> input_buffers_;
116 ScopedVector<base::SharedMemory> output_buffers_;
117
118 // Input buffers ready to be filled with input from Encode(). As a LIFO since
119 // we don't care about ordering.
120 std::vector<int> input_buffers_free_;
121
122
123 DISALLOW_COPY_AND_ASSIGN(Impl);
124 };
125
126 RTCVideoEncoder::Impl::Impl(const base::WeakPtr<RTCVideoEncoder>& weak_encoder)
127 : weak_encoder_(weak_encoder),
128 encoder_message_loop_proxy_(base::MessageLoopProxy::current()),
129 async_waiter_(NULL),
130 async_retval_(NULL),
131 input_next_frame_(NULL),
132 input_next_frame_keyframe_(false) {
133 thread_checker_.DetachFromThread();
134 }
135
136 void RTCVideoEncoder::Impl::CreateAndInitializeVEA(
137 const webrtc::VideoCodec& codecSettings,
138 media::VideoCodecProfile profile,
139 base::WaitableEvent* async_waiter,
140 int32_t* async_retval,
141 const scoped_refptr<media::GpuVideoAcceleratorFactories>& gpu_factories) {
142 DVLOG(3) << "Impl::CreateAndInitializeVEA()";
143 DCHECK(thread_checker_.CalledOnValidThread());
144
145 async_waiter_ = async_waiter;
146 async_retval_ = async_retval;
147 gpu_factories_ = gpu_factories;
148
149 video_encoder_ = gpu_factories_->CreateVideoEncodeAccelerator(this).Pass();
150 if (!video_encoder_) {
151 NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError);
152 return;
153 }
154 output_frame_dimensions_.SetSize(codecSettings.width, codecSettings.height);
155 video_encoder_->Initialize(
156 media::VideoFrame::I420,
157 output_frame_dimensions_,
158 profile,
159 codecSettings.startBitrate * 1000); // startBitrate is in kbits/sec.
hshi1 2013/08/02 17:29:36 (copied from the EVS review comment by palmer@) sh
sheu 2013/08/03 01:31:03 Done.
160 }
161
162 void RTCVideoEncoder::Impl::Enqueue(const webrtc::I420VideoFrame* input_frame,
163 bool force_keyframe,
164 base::WaitableEvent* async_waiter,
165 int32_t* async_retval) {
166 DVLOG(3) << "Impl::Enqueue()";
167 DCHECK(thread_checker_.CalledOnValidThread());
168 DCHECK(!input_next_frame_);
169
170 async_waiter_ = async_waiter;
171 async_retval_ = async_retval;
172 input_next_frame_ = input_frame;
173 input_next_frame_keyframe_ = force_keyframe;
174
175 if (!input_buffers_free_.empty())
176 EncodeOneFrame();
177 }
178
179 void RTCVideoEncoder::Impl::UseOutputBitstreamBufferId(
180 int32 bitstream_buffer_id) {
181 DVLOG(3) << "Impl::UseOutputBitstreamBufferIndex(): "
182 "bitstream_buffer_id=" << bitstream_buffer_id;
183 DCHECK(thread_checker_.CalledOnValidThread());
184 if (video_encoder_) {
185 video_encoder_->UseOutputBitstreamBuffer(media::BitstreamBuffer(
186 bitstream_buffer_id,
187 output_buffers_[bitstream_buffer_id]->handle(),
188 output_buffers_[bitstream_buffer_id]->mapped_size()));
189 }
190 }
191
192 void RTCVideoEncoder::Impl::RequestEncodingParameterChange(int32 bitrate) {
193 DVLOG(3) << "Impl::RequestEncodingParameterChange(): bitrate=" << bitrate;
194 DCHECK(thread_checker_.CalledOnValidThread());
195 if (video_encoder_)
196 video_encoder_->RequestEncodingParameterChange(bitrate);
197 }
198
199 void RTCVideoEncoder::Impl::Destroy() {
200 DVLOG(3) << "Impl::Destroy()";
201 DCHECK(thread_checker_.CalledOnValidThread());
202 if (video_encoder_)
203 video_encoder_.release()->Destroy();
204 }
205
206 void RTCVideoEncoder::Impl::NotifyInitializeDone() {
207 DVLOG(3) << "Impl::NotifyInitializeDone()";
208 DCHECK(thread_checker_.CalledOnValidThread());
209 *async_retval_ = WEBRTC_VIDEO_CODEC_OK;
210 async_waiter_->Signal();
211 async_retval_ = NULL;
212 async_waiter_ = NULL;
213 }
214
215 void RTCVideoEncoder::Impl::RequireBitstreamBuffers(
216 int input_count,
217 const gfx::Size& input_dimensions,
218 size_t output_size) {
219 DVLOG(3) << "Impl::RequireBitstreamBuffers(): input_count=" << input_count
220 << ", input_dimensions=" << input_dimensions.ToString()
221 << ", output_size=" << output_size;
222 DCHECK(thread_checker_.CalledOnValidThread());
223
224 if (!video_encoder_)
225 return;
226
227 input_frame_dimensions_ = input_dimensions;
228
229 for (int i = 0; i < input_count + kInputBufferExtraCount; ++i) {
230 base::SharedMemory* shm = gpu_factories_->CreateSharedMemory(
231 input_dimensions.GetArea() * 3 / 2);
232 if (!shm) {
233 DLOG(ERROR) << "Impl::RequireBitstreamBuffers(): "
234 "failed to create input buffer " << i;
235 NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError);
236 return;
237 }
238 input_buffers_.push_back(shm);
239 }
240 for (size_t i = 0; i < input_buffers_.size(); ++i)
241 input_buffers_free_.push_back(i);
242
243 for (int i = 0; i < kOutputBufferCount; ++i) {
244 base::SharedMemory* shm = gpu_factories_->CreateSharedMemory(output_size);
245 if (!shm) {
246 DLOG(ERROR) << "Impl::RequireBitstreamBuffers(): "
247 "failed to create output buffer " << i;
248 NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError);
249 return;
250 }
251 output_buffers_.push_back(shm);
252 }
253
254 // Immediately provide all output buffers to the VEA.
255 for (size_t i = 0; i < output_buffers_.size(); ++i) {
256 video_encoder_->UseOutputBitstreamBuffer(media::BitstreamBuffer(
257 i, output_buffers_[i]->handle(), output_buffers_[i]->mapped_size()));
258 }
259 }
260
261 void RTCVideoEncoder::Impl::NotifyInputDone(int32 bitstream_buffer_id) {
262 DVLOG(3) << "Impl::NotifyInputDone(): bitstream_buffer_id="
263 << bitstream_buffer_id;
264 DCHECK(thread_checker_.CalledOnValidThread());
265 if (bitstream_buffer_id < 0 ||
266 bitstream_buffer_id >= static_cast<int>(input_buffers_.size())) {
267 DLOG(ERROR) << "Impl::NotifyInputDone(): invalid bitstream_buffer_id="
268 << bitstream_buffer_id;
269 NOTIFY_ERROR(media::VideoEncodeAccelerator::kInvalidArgumentError);
270 return;
271 }
272
273 input_buffers_free_.push_back(bitstream_buffer_id);
274 if (input_next_frame_)
275 EncodeOneFrame();
276 }
277
278 void RTCVideoEncoder::Impl::BitstreamBufferReady(int32 bitstream_buffer_id,
279 size_t payload_size,
280 bool key_frame) {
281 DVLOG(3) << "Impl::BitstreamBufferReady(): "
282 "bitstream_buffer_id=" << bitstream_buffer_id
283 << ", payload_size=" << payload_size
284 << ", key_frame=" << key_frame;
285 DCHECK(thread_checker_.CalledOnValidThread());
286
287 if (bitstream_buffer_id < 0 ||
288 bitstream_buffer_id >= static_cast<int>(output_buffers_.size())) {
289 DLOG(ERROR) << "Impl::BitstreamBufferReady(): invalid bitstream_buffer_id="
290 << bitstream_buffer_id;
291 NOTIFY_ERROR(media::VideoEncodeAccelerator::kInvalidArgumentError);
292 return;
293 }
294 base::SharedMemory* output_buffer = output_buffers_[bitstream_buffer_id];
295 if (payload_size > output_buffer->mapped_size()) {
296 DLOG(ERROR) << "Impl::BitstreamBufferReady(): invalid payload_size="
297 << payload_size;
298 NOTIFY_ERROR(media::VideoEncodeAccelerator::kInvalidArgumentError);
299 return;
300 }
301
302 scoped_ptr<webrtc::EncodedImage> image(new webrtc::EncodedImage(
303 reinterpret_cast<uint8_t*>(output_buffer->memory()),
304 payload_size,
305 output_buffer->mapped_size()));
306 image->_encodedWidth = output_frame_dimensions_.width();
307 image->_encodedHeight = output_frame_dimensions_.height();
308 image->_frameType = (key_frame ? webrtc::kKeyFrame : webrtc::kDeltaFrame);
309 image->_completeFrame = true;
310
311 encoder_message_loop_proxy_->PostTask(
312 FROM_HERE,
313 base::Bind(&RTCVideoEncoder::ReturnEncodedImage,
314 weak_encoder_,
315 make_scoped_refptr(this),
316 base::Passed(&image),
317 bitstream_buffer_id));
318 }
319
320 void RTCVideoEncoder::Impl::NotifyError(
321 media::VideoEncodeAccelerator::Error error) {
322 DVLOG(3) << "Impl::NotifyError(): error=" << error;
323 DCHECK(thread_checker_.CalledOnValidThread());
324 int32_t retval;
325 switch (error) {
326 default:
327 retval = WEBRTC_VIDEO_CODEC_ERROR;
328 }
329
330 if (video_encoder_)
331 video_encoder_.release()->Destroy();
332
333 if (async_waiter_) {
334 *async_retval_ = retval;
335 async_waiter_->Signal();
336 async_retval_ = NULL;
337 async_waiter_ = NULL;
338 } else {
339 encoder_message_loop_proxy_->PostTask(
340 FROM_HERE,
341 base::Bind(&RTCVideoEncoder::NotifyError,
342 weak_encoder_,
343 make_scoped_refptr(this),
344 retval));
345 }
346 }
347
348 RTCVideoEncoder::Impl::~Impl() {
349 DCHECK(!video_encoder_);
350 }
351
352 void RTCVideoEncoder::Impl::EncodeOneFrame() {
353 DVLOG(3) << "Impl::EncodeOneFrame()";
354 DCHECK(thread_checker_.CalledOnValidThread());
355 DCHECK(input_next_frame_);
356 DCHECK(!input_buffers_free_.empty());
357 DCHECK(async_waiter_);
358 DCHECK(async_retval_);
359
360 const int index = input_buffers_free_.back();
361 base::SharedMemory* input_buffer = input_buffers_[index];
362
363 if (video_encoder_) {
364 // Do a strided copy of the input frame to match the input requirements for
365 // the encoder.
366 const uint8_t* src = input_next_frame_->buffer(webrtc::kYPlane);
367 uint8* dst = reinterpret_cast<uint8*>(input_buffer->memory());
368 int width = input_frame_dimensions_.width();
369 int stride = input_next_frame_->stride(webrtc::kYPlane);
370 for (int i = 0; i < input_next_frame_->height(); ++i) {
371 memcpy(dst, src, width);
372 dst += stride;
373 src += width;
374 }
375 src = input_next_frame_->buffer(webrtc::kUPlane);
376 width = input_frame_dimensions_.width() / 2;
377 stride = input_next_frame_->stride(webrtc::kUPlane);
378 for (int i = 0; i < input_next_frame_->height() / 2; ++i) {
379 memcpy(dst, src, width);
380 dst += stride;
381 src += width;
382 }
383 src = input_next_frame_->buffer(webrtc::kVPlane);
384 width = input_frame_dimensions_.width() / 2;
385 stride = input_next_frame_->stride(webrtc::kVPlane);
386 for (int i = 0; i < input_next_frame_->height() / 2; ++i) {
387 memcpy(dst, src, width);
388 dst += stride;
389 src += width;
390 }
391
392 video_encoder_->Encode(
393 media::BitstreamBuffer(
394 index,
395 input_buffer->handle(),
396 input_frame_dimensions_.GetArea() * 3 / 2),
397 input_next_frame_keyframe_);
398 }
399
400 input_next_frame_ = NULL;
401 input_next_frame_keyframe_ = false;
402 input_buffers_free_.pop_back();
403
404 *async_retval_ = WEBRTC_VIDEO_CODEC_OK;
405 async_waiter_->Signal();
406 async_retval_ = NULL;
407 async_waiter_ = NULL;
408 }
409
410 RTCVideoEncoder::RTCVideoEncoder(
411 media::VideoCodecProfile profile,
412 const scoped_refptr<media::GpuVideoAcceleratorFactories>& gpu_factories)
413 : video_codec_profile_(profile),
414 gpu_factories_(gpu_factories),
415 impl_message_loop_proxy_(gpu_factories_->GetMessageLoop()),
416 weak_this_factory_(this),
417 weak_this_(weak_this_factory_.GetWeakPtr()),
418 encoded_image_callback_(NULL),
419 impl_status_(WEBRTC_VIDEO_CODEC_OK) {
420 DVLOG(1) << "RTCVideoEncoder(): profile=" << profile;
421 }
422
423 RTCVideoEncoder::~RTCVideoEncoder() {
424 DCHECK(thread_checker_.CalledOnValidThread());
425 Release();
426 DCHECK(!impl_);
427 }
428
429 int32_t RTCVideoEncoder::InitEncode(const webrtc::VideoCodec* codec_settings,
430 int32_t number_of_cores,
431 uint32_t max_payload_size) {
432 DVLOG(1) << "InitEncode(): codecType=" << codec_settings->codecType
433 << ", width=" << codec_settings->width
434 << ", height=" << codec_settings->height
435 << ", startBitrate=" << codec_settings->startBitrate;
436 DCHECK(thread_checker_.CalledOnValidThread());
437 DCHECK(!impl_);
438
439 impl_ = new Impl(weak_this_);
440 base::WaitableEvent initialization_waiter(true, false);
441 int32_t initialization_retval = WEBRTC_VIDEO_CODEC_UNINITIALIZED;
442 impl_message_loop_proxy_->PostTask(
443 FROM_HERE,
444 base::Bind(&RTCVideoEncoder::Impl::CreateAndInitializeVEA,
445 impl_,
446 *codec_settings,
447 video_codec_profile_,
448 &initialization_waiter,
449 &initialization_retval,
450 gpu_factories_));
451
452 // webrtc::VideoEncoder expects this call to be synchronous.
453 initialization_waiter.Wait();
454 return initialization_retval;
455 }
456
457 int32_t RTCVideoEncoder::Encode(
458 const webrtc::I420VideoFrame& input_image,
459 const webrtc::CodecSpecificInfo* codec_specific_info,
460 const std::vector<webrtc::VideoFrameType>* frame_types) {
461 DVLOG(3) << "Encode()";
462 //DCHECK(thread_checker_.CalledOnValidThread());
463 if (!impl_) {
464 DVLOG(3) << "Encode(): returning impl_status_=" << impl_status_;
465 return impl_status_;
466 }
467
468 base::WaitableEvent encode_waiter(true, false);
469 int32_t encode_retval = WEBRTC_VIDEO_CODEC_UNINITIALIZED;
470 impl_message_loop_proxy_->PostTask(
471 FROM_HERE,
472 base::Bind(&RTCVideoEncoder::Impl::Enqueue,
473 impl_,
474 &input_image,
475 (frame_types->front() == webrtc::kKeyFrame),
476 &encode_waiter,
477 &encode_retval));
478
479 // webrtc::VideoEncoder expects this call to be synchronous.
480 encode_waiter.Wait();
481 DVLOG(3) << "Encode(): returning encode_retval=" << encode_retval;
482 return encode_retval;
483 }
484
485 int32_t RTCVideoEncoder::RegisterEncodeCompleteCallback(
486 webrtc::EncodedImageCallback* callback) {
487 DVLOG(3) << "RegisterEncodeCompleteCallback()";
488 DCHECK(thread_checker_.CalledOnValidThread());
489 if (!impl_) {
490 DVLOG(3) << "RegisterEncodeCompleteCallback(): returning " << impl_status_;
491 return impl_status_;
492 }
493
494 encoded_image_callback_ = callback;
495 return WEBRTC_VIDEO_CODEC_OK;
496 }
497
498 int32_t RTCVideoEncoder::Release() {
499 DVLOG(3) << "Release()";
500 DCHECK(thread_checker_.CalledOnValidThread());
501
502 // Reset the gpu_factory_, in case we reuse this encoder.
503 gpu_factories_->Abort();
504 gpu_factories_ = gpu_factories_->Clone();
505 impl_message_loop_proxy_->PostTask(
506 FROM_HERE,
507 base::Bind(&RTCVideoEncoder::Impl::Destroy, impl_));
hshi1 2013/08/02 17:29:36 nit: the above 2 lines ("FROM_HERE, base::Bind(&RT
sheu 2013/08/03 01:31:03 Done.
508 impl_ = NULL;
509 impl_status_ = WEBRTC_VIDEO_CODEC_OK;
510 return WEBRTC_VIDEO_CODEC_OK;
511 }
512
513 int32_t RTCVideoEncoder::SetChannelParameters(uint32_t packet_loss, int rtt) {
514 DVLOG(3) << "SetChannelParameters(): packet_loss=" << packet_loss
515 << ", rtt=" << rtt;
516 DCHECK(thread_checker_.CalledOnValidThread());
517 // Ignored.
518 return WEBRTC_VIDEO_CODEC_OK;
519 }
520
521 int32_t RTCVideoEncoder::SetRates(uint32_t new_bit_rate, uint32_t frame_rate) {
522 DVLOG(3) << "SetRates(): new_bit_rate=" << new_bit_rate
523 << ", frame_rate=" << frame_rate;
524 DCHECK(thread_checker_.CalledOnValidThread());
525 if (!impl_) {
526 DVLOG(3) << "SetRates(): returning " << impl_status_;
527 return impl_status_;
528 }
529
530 impl_message_loop_proxy_->PostTask(
531 FROM_HERE,
532 base::Bind(&RTCVideoEncoder::Impl::RequestEncodingParameterChange,
533 impl_,
534 new_bit_rate));
535 return WEBRTC_VIDEO_CODEC_OK;
536 }
537
538 void RTCVideoEncoder::ReturnEncodedImage(const scoped_refptr<Impl>& impl,
539 scoped_ptr<webrtc::EncodedImage> image,
540 int32 bitstream_buffer_id) {
541 DCHECK(thread_checker_.CalledOnValidThread());
542
543 if (impl != impl_)
544 return;
545
546 DVLOG(3) << "ReturnEncodedImage(): "
547 "bitstream_buffer_id=" << bitstream_buffer_id;
548
549 if (!impl_)
550 return;
551 if (!encoded_image_callback_)
552 return;
553
554 int32_t retval = encoded_image_callback_->Encoded(*image, NULL, NULL);
555 if (retval < 0) {
556 NotifyError(impl_, retval);
557 return;
558 }
559
560 // The call through webrtc::EncodedImageCallback is synchronous, so we can
561 // immediately recycle the output buffer back to the Impl.
562 impl_message_loop_proxy_->PostTask(
563 FROM_HERE,
564 base::Bind(&RTCVideoEncoder::Impl::UseOutputBitstreamBufferId,
565 impl_,
566 bitstream_buffer_id));
567 }
568
569 void RTCVideoEncoder::NotifyError(const scoped_refptr<Impl>& impl,
570 int32_t error) {
571 DCHECK(thread_checker_.CalledOnValidThread());
572
573 if (impl != impl_)
574 return;
575
576 DVLOG(1) << "NotifyError(): error=" << error;
577
578 impl_status_ = error;
579 impl_message_loop_proxy_->PostTask(
580 FROM_HERE,
581 base::Bind(&RTCVideoEncoder::Impl::Destroy, impl_));
hshi1 2013/08/02 17:29:36 nit: ditto
sheu 2013/08/03 01:31:03 Done.
582 impl_ = NULL;
583 }
584
585 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698