OLD | NEW |
---|---|
(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 | |
OLD | NEW |