OLD | NEW |
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 "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/location.h" | 8 #include "base/location.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/memory/scoped_vector.h" | 10 #include "base/memory/scoped_vector.h" |
11 #include "base/message_loop/message_loop_proxy.h" | 11 #include "base/message_loop/message_loop_proxy.h" |
12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
| 13 #include "base/rand_util.h" |
13 #include "base/synchronization/waitable_event.h" | 14 #include "base/synchronization/waitable_event.h" |
14 #include "media/base/bitstream_buffer.h" | 15 #include "media/base/bitstream_buffer.h" |
15 #include "media/base/video_frame.h" | 16 #include "media/base/video_frame.h" |
16 #include "media/base/video_util.h" | 17 #include "media/base/video_util.h" |
17 #include "media/filters/gpu_video_accelerator_factories.h" | 18 #include "media/filters/gpu_video_accelerator_factories.h" |
18 #include "media/video/video_encode_accelerator.h" | 19 #include "media/video/video_encode_accelerator.h" |
19 #include "third_party/webrtc/system_wrappers/interface/tick_util.h" | 20 #include "third_party/webrtc/system_wrappers/interface/tick_util.h" |
20 | 21 |
21 #define NOTIFY_ERROR(x) \ | 22 #define NOTIFY_ERROR(x) \ |
22 do { \ | 23 do { \ |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 ScopedVector<base::SharedMemory> output_buffers_; | 146 ScopedVector<base::SharedMemory> output_buffers_; |
146 | 147 |
147 // Input buffers ready to be filled with input from Encode(). As a LIFO since | 148 // Input buffers ready to be filled with input from Encode(). As a LIFO since |
148 // we don't care about ordering. | 149 // we don't care about ordering. |
149 std::vector<int> input_buffers_free_; | 150 std::vector<int> input_buffers_free_; |
150 | 151 |
151 // The number of output buffers ready to be filled with output from the | 152 // The number of output buffers ready to be filled with output from the |
152 // encoder. | 153 // encoder. |
153 int output_buffers_free_count_; | 154 int output_buffers_free_count_; |
154 | 155 |
| 156 // 15 bits running index of the VP8 frames. See VP8 RTP spec for details. |
| 157 uint16 picture_id_; |
| 158 |
155 DISALLOW_COPY_AND_ASSIGN(Impl); | 159 DISALLOW_COPY_AND_ASSIGN(Impl); |
156 }; | 160 }; |
157 | 161 |
158 RTCVideoEncoder::Impl::Impl( | 162 RTCVideoEncoder::Impl::Impl( |
159 const base::WeakPtr<RTCVideoEncoder>& weak_encoder, | 163 const base::WeakPtr<RTCVideoEncoder>& weak_encoder, |
160 const scoped_refptr<media::GpuVideoAcceleratorFactories>& gpu_factories) | 164 const scoped_refptr<media::GpuVideoAcceleratorFactories>& gpu_factories) |
161 : weak_encoder_(weak_encoder), | 165 : weak_encoder_(weak_encoder), |
162 encoder_message_loop_proxy_(base::MessageLoopProxy::current()), | 166 encoder_message_loop_proxy_(base::MessageLoopProxy::current()), |
163 gpu_factories_(gpu_factories), | 167 gpu_factories_(gpu_factories), |
164 async_waiter_(NULL), | 168 async_waiter_(NULL), |
165 async_retval_(NULL), | 169 async_retval_(NULL), |
166 input_next_frame_(NULL), | 170 input_next_frame_(NULL), |
167 input_next_frame_keyframe_(false), | 171 input_next_frame_keyframe_(false), |
168 output_buffers_free_count_(0) { | 172 output_buffers_free_count_(0) { |
169 thread_checker_.DetachFromThread(); | 173 thread_checker_.DetachFromThread(); |
| 174 // Picture ID should start on a random number. |
| 175 picture_id_ = static_cast<uint16_t>(base::RandInt(0, 0x7FFF)); |
170 } | 176 } |
171 | 177 |
172 void RTCVideoEncoder::Impl::CreateAndInitializeVEA( | 178 void RTCVideoEncoder::Impl::CreateAndInitializeVEA( |
173 const gfx::Size& input_visible_size, | 179 const gfx::Size& input_visible_size, |
174 uint32 bitrate, | 180 uint32 bitrate, |
175 media::VideoCodecProfile profile, | 181 media::VideoCodecProfile profile, |
176 base::WaitableEvent* async_waiter, | 182 base::WaitableEvent* async_waiter, |
177 int32_t* async_retval) { | 183 int32_t* async_retval) { |
178 DVLOG(3) << "Impl::CreateAndInitializeVEA()"; | 184 DVLOG(3) << "Impl::CreateAndInitializeVEA()"; |
179 DCHECK(thread_checker_.CalledOnValidThread()); | 185 DCHECK(thread_checker_.CalledOnValidThread()); |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
371 image->_timeStamp = rtp_timestamp; | 377 image->_timeStamp = rtp_timestamp; |
372 image->capture_time_ms_ = capture_time_ms; | 378 image->capture_time_ms_ = capture_time_ms; |
373 image->_frameType = (key_frame ? webrtc::kKeyFrame : webrtc::kDeltaFrame); | 379 image->_frameType = (key_frame ? webrtc::kKeyFrame : webrtc::kDeltaFrame); |
374 image->_completeFrame = true; | 380 image->_completeFrame = true; |
375 | 381 |
376 encoder_message_loop_proxy_->PostTask( | 382 encoder_message_loop_proxy_->PostTask( |
377 FROM_HERE, | 383 FROM_HERE, |
378 base::Bind(&RTCVideoEncoder::ReturnEncodedImage, | 384 base::Bind(&RTCVideoEncoder::ReturnEncodedImage, |
379 weak_encoder_, | 385 weak_encoder_, |
380 base::Passed(&image), | 386 base::Passed(&image), |
381 bitstream_buffer_id)); | 387 bitstream_buffer_id, |
| 388 picture_id_)); |
| 389 // Picture ID must wrap after reaching the maximum. |
| 390 picture_id_ = (picture_id_ + 1) & 0x7FFF; |
382 } | 391 } |
383 | 392 |
384 void RTCVideoEncoder::Impl::NotifyError( | 393 void RTCVideoEncoder::Impl::NotifyError( |
385 media::VideoEncodeAccelerator::Error error) { | 394 media::VideoEncodeAccelerator::Error error) { |
386 DVLOG(3) << "Impl::NotifyError(): error=" << error; | 395 DVLOG(3) << "Impl::NotifyError(): error=" << error; |
387 DCHECK(thread_checker_.CalledOnValidThread()); | 396 DCHECK(thread_checker_.CalledOnValidThread()); |
388 int32_t retval; | 397 int32_t retval; |
389 switch (error) { | 398 switch (error) { |
390 case media::VideoEncodeAccelerator::kInvalidArgumentError: | 399 case media::VideoEncodeAccelerator::kInvalidArgumentError: |
391 retval = WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 400 retval = WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
630 gpu_factories_->GetTaskRunner()->PostTask( | 639 gpu_factories_->GetTaskRunner()->PostTask( |
631 FROM_HERE, | 640 FROM_HERE, |
632 base::Bind(&RTCVideoEncoder::Impl::RequestEncodingParametersChange, | 641 base::Bind(&RTCVideoEncoder::Impl::RequestEncodingParametersChange, |
633 impl_, | 642 impl_, |
634 new_bit_rate, | 643 new_bit_rate, |
635 frame_rate)); | 644 frame_rate)); |
636 return WEBRTC_VIDEO_CODEC_OK; | 645 return WEBRTC_VIDEO_CODEC_OK; |
637 } | 646 } |
638 | 647 |
639 void RTCVideoEncoder::ReturnEncodedImage(scoped_ptr<webrtc::EncodedImage> image, | 648 void RTCVideoEncoder::ReturnEncodedImage(scoped_ptr<webrtc::EncodedImage> image, |
640 int32 bitstream_buffer_id) { | 649 int32 bitstream_buffer_id, |
| 650 uint16 picture_id) { |
641 DCHECK(thread_checker_.CalledOnValidThread()); | 651 DCHECK(thread_checker_.CalledOnValidThread()); |
642 DVLOG(3) << "ReturnEncodedImage(): " | 652 DVLOG(3) << "ReturnEncodedImage(): " |
643 "bitstream_buffer_id=" << bitstream_buffer_id; | 653 << "bitstream_buffer_id=" << bitstream_buffer_id |
| 654 << ", picture_id=" << picture_id; |
644 | 655 |
645 if (!encoded_image_callback_) | 656 if (!encoded_image_callback_) |
646 return; | 657 return; |
647 | 658 |
648 webrtc::CodecSpecificInfo info; | 659 webrtc::CodecSpecificInfo info; |
649 memset(&info, 0, sizeof(info)); | 660 memset(&info, 0, sizeof(info)); |
650 info.codecType = video_codec_type_; | 661 info.codecType = video_codec_type_; |
651 if (video_codec_type_ == webrtc::kVideoCodecVP8) { | 662 if (video_codec_type_ == webrtc::kVideoCodecVP8) { |
652 info.codecSpecific.VP8.pictureId = -1; | 663 info.codecSpecific.VP8.pictureId = picture_id; |
653 info.codecSpecific.VP8.tl0PicIdx = -1; | 664 info.codecSpecific.VP8.tl0PicIdx = -1; |
654 info.codecSpecific.VP8.keyIdx = -1; | 665 info.codecSpecific.VP8.keyIdx = -1; |
655 } | 666 } |
656 | 667 |
657 // Generate a header describing a single fragment. | 668 // Generate a header describing a single fragment. |
658 webrtc::RTPFragmentationHeader header; | 669 webrtc::RTPFragmentationHeader header; |
659 memset(&header, 0, sizeof(header)); | 670 memset(&header, 0, sizeof(header)); |
660 header.VerifyAndAllocateFragmentationHeader(1); | 671 header.VerifyAndAllocateFragmentationHeader(1); |
661 header.fragmentationOffset[0] = 0; | 672 header.fragmentationOffset[0] = 0; |
662 header.fragmentationLength[0] = image->_length; | 673 header.fragmentationLength[0] = image->_length; |
(...skipping 29 matching lines...) Expand all Loading... |
692 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoEncoderInitEncodeSuccess", | 703 UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoEncoderInitEncodeSuccess", |
693 init_retval == WEBRTC_VIDEO_CODEC_OK); | 704 init_retval == WEBRTC_VIDEO_CODEC_OK); |
694 if (init_retval == WEBRTC_VIDEO_CODEC_OK) { | 705 if (init_retval == WEBRTC_VIDEO_CODEC_OK) { |
695 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoEncoderProfile", | 706 UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoEncoderProfile", |
696 video_codec_profile_, | 707 video_codec_profile_, |
697 media::VIDEO_CODEC_PROFILE_MAX + 1); | 708 media::VIDEO_CODEC_PROFILE_MAX + 1); |
698 } | 709 } |
699 } | 710 } |
700 | 711 |
701 } // namespace content | 712 } // namespace content |
OLD | NEW |