OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 | 158 |
159 VP8EncoderImpl::VP8EncoderImpl() | 159 VP8EncoderImpl::VP8EncoderImpl() |
160 : use_gf_boost_(webrtc::field_trial::IsEnabled(kVp8GfBoostFieldTrial)), | 160 : use_gf_boost_(webrtc::field_trial::IsEnabled(kVp8GfBoostFieldTrial)), |
161 encoded_complete_callback_(nullptr), | 161 encoded_complete_callback_(nullptr), |
162 inited_(false), | 162 inited_(false), |
163 timestamp_(0), | 163 timestamp_(0), |
164 qp_max_(56), // Setting for max quantizer. | 164 qp_max_(56), // Setting for max quantizer. |
165 cpu_speed_default_(-6), | 165 cpu_speed_default_(-6), |
166 number_of_cores_(0), | 166 number_of_cores_(0), |
167 rc_max_intra_target_(0), | 167 rc_max_intra_target_(0), |
168 key_frame_request_(kMaxSimulcastStreams, false) { | 168 key_frame_request_(kMaxSimulcastStreams, false), |
| 169 last_timing_frame_time_ms_(0) { |
169 Random random(rtc::TimeMicros()); | 170 Random random(rtc::TimeMicros()); |
170 picture_id_.reserve(kMaxSimulcastStreams); | 171 picture_id_.reserve(kMaxSimulcastStreams); |
171 for (int i = 0; i < kMaxSimulcastStreams; ++i) { | 172 for (int i = 0; i < kMaxSimulcastStreams; ++i) { |
172 picture_id_.push_back(random.Rand<uint16_t>() & 0x7FFF); | 173 picture_id_.push_back(random.Rand<uint16_t>() & 0x7FFF); |
173 tl0_pic_idx_.push_back(random.Rand<uint8_t>()); | 174 tl0_pic_idx_.push_back(random.Rand<uint8_t>()); |
174 } | 175 } |
175 temporal_layers_.reserve(kMaxSimulcastStreams); | 176 temporal_layers_.reserve(kMaxSimulcastStreams); |
176 raw_images_.reserve(kMaxSimulcastStreams); | 177 raw_images_.reserve(kMaxSimulcastStreams); |
177 encoded_images_.reserve(kMaxSimulcastStreams); | 178 encoded_images_.reserve(kMaxSimulcastStreams); |
178 send_stream_.reserve(kMaxSimulcastStreams); | 179 send_stream_.reserve(kMaxSimulcastStreams); |
(...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
661 const CodecSpecificInfo* codec_specific_info, | 662 const CodecSpecificInfo* codec_specific_info, |
662 const std::vector<FrameType>* frame_types) { | 663 const std::vector<FrameType>* frame_types) { |
663 RTC_DCHECK_EQ(frame.width(), codec_.width); | 664 RTC_DCHECK_EQ(frame.width(), codec_.width); |
664 RTC_DCHECK_EQ(frame.height(), codec_.height); | 665 RTC_DCHECK_EQ(frame.height(), codec_.height); |
665 | 666 |
666 if (!inited_) | 667 if (!inited_) |
667 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 668 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
668 if (encoded_complete_callback_ == NULL) | 669 if (encoded_complete_callback_ == NULL) |
669 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 670 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
670 | 671 |
| 672 int64_t encode_start_ms = rtc::TimeMillis(); |
| 673 |
671 rtc::scoped_refptr<VideoFrameBuffer> input_image = frame.video_frame_buffer(); | 674 rtc::scoped_refptr<VideoFrameBuffer> input_image = frame.video_frame_buffer(); |
672 // Since we are extracting raw pointers from |input_image| to | 675 // Since we are extracting raw pointers from |input_image| to |
673 // |raw_images_[0]|, the resolution of these frames must match. | 676 // |raw_images_[0]|, the resolution of these frames must match. |
674 RTC_DCHECK_EQ(input_image->width(), raw_images_[0].d_w); | 677 RTC_DCHECK_EQ(input_image->width(), raw_images_[0].d_w); |
675 RTC_DCHECK_EQ(input_image->height(), raw_images_[0].d_h); | 678 RTC_DCHECK_EQ(input_image->height(), raw_images_[0].d_h); |
676 | 679 |
677 // Image in vpx_image_t format. | 680 // Image in vpx_image_t format. |
678 // Input image is const. VP8's raw image is not defined as const. | 681 // Input image is const. VP8's raw image is not defined as const. |
679 raw_images_[0].planes[VPX_PLANE_Y] = | 682 raw_images_[0].planes[VPX_PLANE_Y] = |
680 const_cast<uint8_t*>(input_image->DataY()); | 683 const_cast<uint8_t*>(input_image->DataY()); |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
782 duration, 0, VPX_DL_REALTIME); | 785 duration, 0, VPX_DL_REALTIME); |
783 // Reset specific intra frame thresholds, following the key frame. | 786 // Reset specific intra frame thresholds, following the key frame. |
784 if (send_key_frame) { | 787 if (send_key_frame) { |
785 vpx_codec_control(&(encoders_[0]), VP8E_SET_MAX_INTRA_BITRATE_PCT, | 788 vpx_codec_control(&(encoders_[0]), VP8E_SET_MAX_INTRA_BITRATE_PCT, |
786 rc_max_intra_target_); | 789 rc_max_intra_target_); |
787 } | 790 } |
788 if (error) | 791 if (error) |
789 return WEBRTC_VIDEO_CODEC_ERROR; | 792 return WEBRTC_VIDEO_CODEC_ERROR; |
790 timestamp_ += duration; | 793 timestamp_ += duration; |
791 // Examines frame timestamps only. | 794 // Examines frame timestamps only. |
792 return GetEncodedPartitions(tl_configs, frame); | 795 return GetEncodedPartitions(tl_configs, frame, encode_start_ms); |
793 } | 796 } |
794 | 797 |
795 void VP8EncoderImpl::PopulateCodecSpecific( | 798 void VP8EncoderImpl::PopulateCodecSpecific( |
796 CodecSpecificInfo* codec_specific, | 799 CodecSpecificInfo* codec_specific, |
797 const TemporalLayers::FrameConfig& tl_config, | 800 const TemporalLayers::FrameConfig& tl_config, |
798 const vpx_codec_cx_pkt_t& pkt, | 801 const vpx_codec_cx_pkt_t& pkt, |
799 int stream_idx, | 802 int stream_idx, |
800 uint32_t timestamp) { | 803 uint32_t timestamp) { |
801 assert(codec_specific != NULL); | 804 assert(codec_specific != NULL); |
802 codec_specific->codecType = kVideoCodecVP8; | 805 codec_specific->codecType = kVideoCodecVP8; |
803 codec_specific->codec_name = ImplementationName(); | 806 codec_specific->codec_name = ImplementationName(); |
804 CodecSpecificInfoVP8* vp8Info = &(codec_specific->codecSpecific.VP8); | 807 CodecSpecificInfoVP8* vp8Info = &(codec_specific->codecSpecific.VP8); |
805 vp8Info->pictureId = picture_id_[stream_idx]; | 808 vp8Info->pictureId = picture_id_[stream_idx]; |
806 vp8Info->simulcastIdx = stream_idx; | 809 vp8Info->simulcastIdx = stream_idx; |
807 vp8Info->keyIdx = kNoKeyIdx; // TODO(hlundin) populate this | 810 vp8Info->keyIdx = kNoKeyIdx; // TODO(hlundin) populate this |
808 vp8Info->nonReference = (pkt.data.frame.flags & VPX_FRAME_IS_DROPPABLE) != 0; | 811 vp8Info->nonReference = (pkt.data.frame.flags & VPX_FRAME_IS_DROPPABLE) != 0; |
809 temporal_layers_[stream_idx]->PopulateCodecSpecific( | 812 temporal_layers_[stream_idx]->PopulateCodecSpecific( |
810 (pkt.data.frame.flags & VPX_FRAME_IS_KEY) != 0, tl_config, vp8Info, | 813 (pkt.data.frame.flags & VPX_FRAME_IS_KEY) != 0, tl_config, vp8Info, |
811 timestamp); | 814 timestamp); |
812 // Prepare next. | 815 // Prepare next. |
813 picture_id_[stream_idx] = (picture_id_[stream_idx] + 1) & 0x7FFF; | 816 picture_id_[stream_idx] = (picture_id_[stream_idx] + 1) & 0x7FFF; |
814 } | 817 } |
815 | 818 |
816 int VP8EncoderImpl::GetEncodedPartitions( | 819 int VP8EncoderImpl::GetEncodedPartitions( |
817 const TemporalLayers::FrameConfig tl_configs[], | 820 const TemporalLayers::FrameConfig tl_configs[], |
818 const VideoFrame& input_image) { | 821 const VideoFrame& input_image, |
| 822 int64_t encode_start_ms) { |
819 int bw_resolutions_disabled = | 823 int bw_resolutions_disabled = |
820 (encoders_.size() > 1) ? NumStreamsDisabled(send_stream_) : -1; | 824 (encoders_.size() > 1) ? NumStreamsDisabled(send_stream_) : -1; |
821 | 825 |
| 826 bool is_time_for_timing_frame = |
| 827 input_image.render_time_ms() - last_timing_frame_time_ms_ >= |
| 828 codec_.timingFramesDelayMs; |
| 829 if (is_time_for_timing_frame) |
| 830 last_timing_frame_time_ms_ = input_image.render_time_ms(); |
| 831 |
822 int stream_idx = static_cast<int>(encoders_.size()) - 1; | 832 int stream_idx = static_cast<int>(encoders_.size()) - 1; |
823 int result = WEBRTC_VIDEO_CODEC_OK; | 833 int result = WEBRTC_VIDEO_CODEC_OK; |
824 for (size_t encoder_idx = 0; encoder_idx < encoders_.size(); | 834 for (size_t encoder_idx = 0; encoder_idx < encoders_.size(); |
825 ++encoder_idx, --stream_idx) { | 835 ++encoder_idx, --stream_idx) { |
826 vpx_codec_iter_t iter = NULL; | 836 vpx_codec_iter_t iter = NULL; |
827 int part_idx = 0; | 837 int part_idx = 0; |
828 encoded_images_[encoder_idx]._length = 0; | 838 encoded_images_[encoder_idx]._length = 0; |
829 encoded_images_[encoder_idx]._frameType = kVideoFrameDelta; | 839 encoded_images_[encoder_idx]._frameType = kVideoFrameDelta; |
830 RTPFragmentationHeader frag_info; | 840 RTPFragmentationHeader frag_info; |
831 // kTokenPartitions is number of bits used. | 841 // kTokenPartitions is number of bits used. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
871 } | 881 } |
872 } | 882 } |
873 encoded_images_[encoder_idx]._timeStamp = input_image.timestamp(); | 883 encoded_images_[encoder_idx]._timeStamp = input_image.timestamp(); |
874 encoded_images_[encoder_idx].capture_time_ms_ = | 884 encoded_images_[encoder_idx].capture_time_ms_ = |
875 input_image.render_time_ms(); | 885 input_image.render_time_ms(); |
876 encoded_images_[encoder_idx].rotation_ = input_image.rotation(); | 886 encoded_images_[encoder_idx].rotation_ = input_image.rotation(); |
877 encoded_images_[encoder_idx].content_type_ = | 887 encoded_images_[encoder_idx].content_type_ = |
878 (codec_.mode == kScreensharing) ? VideoContentType::SCREENSHARE | 888 (codec_.mode == kScreensharing) ? VideoContentType::SCREENSHARE |
879 : VideoContentType::UNSPECIFIED; | 889 : VideoContentType::UNSPECIFIED; |
880 | 890 |
| 891 if (is_time_for_timing_frame || |
| 892 encoded_images_[encoder_idx]._length >= |
| 893 codec_.minFrameSizeToForceTimingFrameBytes) { |
| 894 encoded_images_[encoder_idx].timing_.is_timing_frame = true; |
| 895 encoded_images_[encoder_idx].timing_.encode_start_ms = encode_start_ms; |
| 896 encoded_images_[encoder_idx].timing_.encode_finish_ms = rtc::TimeMillis(); |
| 897 } else { |
| 898 encoded_images_[encoder_idx].timing_.is_timing_frame = false; |
| 899 } |
| 900 |
881 int qp = -1; | 901 int qp = -1; |
882 vpx_codec_control(&encoders_[encoder_idx], VP8E_GET_LAST_QUANTIZER_64, &qp); | 902 vpx_codec_control(&encoders_[encoder_idx], VP8E_GET_LAST_QUANTIZER_64, &qp); |
883 temporal_layers_[stream_idx]->FrameEncoded( | 903 temporal_layers_[stream_idx]->FrameEncoded( |
884 encoded_images_[encoder_idx]._length, qp); | 904 encoded_images_[encoder_idx]._length, qp); |
885 if (send_stream_[stream_idx]) { | 905 if (send_stream_[stream_idx]) { |
886 if (encoded_images_[encoder_idx]._length > 0) { | 906 if (encoded_images_[encoder_idx]._length > 0) { |
887 TRACE_COUNTER_ID1("webrtc", "EncodedFrameSize", encoder_idx, | 907 TRACE_COUNTER_ID1("webrtc", "EncodedFrameSize", encoder_idx, |
888 encoded_images_[encoder_idx]._length); | 908 encoded_images_[encoder_idx]._length); |
889 encoded_images_[encoder_idx]._encodedHeight = | 909 encoded_images_[encoder_idx]._encodedHeight = |
890 codec_.simulcastStream[stream_idx].height; | 910 codec_.simulcastStream[stream_idx].height; |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1148 buffer_pool_.Release(); | 1168 buffer_pool_.Release(); |
1149 inited_ = false; | 1169 inited_ = false; |
1150 return WEBRTC_VIDEO_CODEC_OK; | 1170 return WEBRTC_VIDEO_CODEC_OK; |
1151 } | 1171 } |
1152 | 1172 |
1153 const char* VP8DecoderImpl::ImplementationName() const { | 1173 const char* VP8DecoderImpl::ImplementationName() const { |
1154 return "libvpx"; | 1174 return "libvpx"; |
1155 } | 1175 } |
1156 | 1176 |
1157 } // namespace webrtc | 1177 } // namespace webrtc |
OLD | NEW |