| 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 |