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 23 matching lines...) Expand all Loading... |
34 #include "webrtc/system_wrappers/include/clock.h" | 34 #include "webrtc/system_wrappers/include/clock.h" |
35 #include "webrtc/system_wrappers/include/field_trial.h" | 35 #include "webrtc/system_wrappers/include/field_trial.h" |
36 #include "webrtc/system_wrappers/include/metrics.h" | 36 #include "webrtc/system_wrappers/include/metrics.h" |
37 | 37 |
38 namespace webrtc { | 38 namespace webrtc { |
39 namespace { | 39 namespace { |
40 | 40 |
41 const char kVp8PostProcArmFieldTrial[] = "WebRTC-VP8-Postproc-Arm"; | 41 const char kVp8PostProcArmFieldTrial[] = "WebRTC-VP8-Postproc-Arm"; |
42 const char kVp8GfBoostFieldTrial[] = "WebRTC-VP8-GfBoost"; | 42 const char kVp8GfBoostFieldTrial[] = "WebRTC-VP8-GfBoost"; |
43 | 43 |
| 44 const int kTokenPartitions = VP8_ONE_TOKENPARTITION; |
44 enum { kVp8ErrorPropagationTh = 30 }; | 45 enum { kVp8ErrorPropagationTh = 30 }; |
45 enum { kVp832ByteAlign = 32 }; | 46 enum { kVp832ByteAlign = 32 }; |
46 | 47 |
47 // VP8 denoiser states. | 48 // VP8 denoiser states. |
48 enum denoiserState { | 49 enum denoiserState { |
49 kDenoiserOff, | 50 kDenoiserOff, |
50 kDenoiserOnYOnly, | 51 kDenoiserOnYOnly, |
51 kDenoiserOnYUV, | 52 kDenoiserOnYUV, |
52 kDenoiserOnYUVAggressive, | 53 kDenoiserOnYUVAggressive, |
53 // Adaptive mode defaults to kDenoiserOnYUV on key frame, but may switch | 54 // Adaptive mode defaults to kDenoiserOnYUV on key frame, but may switch |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 | 125 |
125 VP8Encoder* VP8Encoder::Create() { | 126 VP8Encoder* VP8Encoder::Create() { |
126 return new VP8EncoderImpl(); | 127 return new VP8EncoderImpl(); |
127 } | 128 } |
128 | 129 |
129 VP8Decoder* VP8Decoder::Create() { | 130 VP8Decoder* VP8Decoder::Create() { |
130 return new VP8DecoderImpl(); | 131 return new VP8DecoderImpl(); |
131 } | 132 } |
132 | 133 |
133 VP8EncoderImpl::VP8EncoderImpl() | 134 VP8EncoderImpl::VP8EncoderImpl() |
134 : encoded_complete_callback_(nullptr), | 135 : use_gf_boost_(webrtc::field_trial::IsEnabled(kVp8GfBoostFieldTrial)), |
| 136 encoded_complete_callback_(nullptr), |
135 inited_(false), | 137 inited_(false), |
136 timestamp_(0), | 138 timestamp_(0), |
137 qp_max_(56), // Setting for max quantizer. | 139 qp_max_(56), // Setting for max quantizer. |
138 cpu_speed_default_(-6), | 140 cpu_speed_default_(-6), |
139 number_of_cores_(0), | 141 number_of_cores_(0), |
140 rc_max_intra_target_(0), | 142 rc_max_intra_target_(0), |
141 token_partitions_(VP8_ONE_TOKENPARTITION), | |
142 down_scale_requested_(false), | |
143 down_scale_bitrate_(0), | |
144 use_gf_boost_(webrtc::field_trial::IsEnabled(kVp8GfBoostFieldTrial)), | |
145 key_frame_request_(kMaxSimulcastStreams, false) { | 143 key_frame_request_(kMaxSimulcastStreams, false) { |
146 uint32_t seed = rtc::Time32(); | 144 uint32_t seed = rtc::Time32(); |
147 srand(seed); | 145 srand(seed); |
148 | 146 |
149 picture_id_.reserve(kMaxSimulcastStreams); | 147 picture_id_.reserve(kMaxSimulcastStreams); |
150 last_key_frame_picture_id_.reserve(kMaxSimulcastStreams); | 148 last_key_frame_picture_id_.reserve(kMaxSimulcastStreams); |
151 temporal_layers_.reserve(kMaxSimulcastStreams); | 149 temporal_layers_.reserve(kMaxSimulcastStreams); |
152 raw_images_.reserve(kMaxSimulcastStreams); | 150 raw_images_.reserve(kMaxSimulcastStreams); |
153 encoded_images_.reserve(kMaxSimulcastStreams); | 151 encoded_images_.reserve(kMaxSimulcastStreams); |
154 send_stream_.reserve(kMaxSimulcastStreams); | 152 send_stream_.reserve(kMaxSimulcastStreams); |
155 cpu_speed_.assign(kMaxSimulcastStreams, -6); // Set default to -6. | 153 cpu_speed_.assign(kMaxSimulcastStreams, cpu_speed_default_); |
156 encoders_.reserve(kMaxSimulcastStreams); | 154 encoders_.reserve(kMaxSimulcastStreams); |
157 configurations_.reserve(kMaxSimulcastStreams); | 155 configurations_.reserve(kMaxSimulcastStreams); |
158 downsampling_factors_.reserve(kMaxSimulcastStreams); | 156 downsampling_factors_.reserve(kMaxSimulcastStreams); |
159 } | 157 } |
160 | 158 |
161 VP8EncoderImpl::~VP8EncoderImpl() { | 159 VP8EncoderImpl::~VP8EncoderImpl() { |
162 Release(); | 160 Release(); |
163 } | 161 } |
164 | 162 |
165 int VP8EncoderImpl::Release() { | 163 int VP8EncoderImpl::Release() { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
213 | 211 |
214 // At this point, bitrate allocation should already match codec settings. | 212 // At this point, bitrate allocation should already match codec settings. |
215 if (codec_.maxBitrate > 0) | 213 if (codec_.maxBitrate > 0) |
216 RTC_DCHECK_LE(bitrate.get_sum_kbps(), codec_.maxBitrate); | 214 RTC_DCHECK_LE(bitrate.get_sum_kbps(), codec_.maxBitrate); |
217 RTC_DCHECK_GE(bitrate.get_sum_kbps(), codec_.minBitrate); | 215 RTC_DCHECK_GE(bitrate.get_sum_kbps(), codec_.minBitrate); |
218 if (codec_.numberOfSimulcastStreams > 0) | 216 if (codec_.numberOfSimulcastStreams > 0) |
219 RTC_DCHECK_GE(bitrate.get_sum_kbps(), codec_.simulcastStream[0].minBitrate); | 217 RTC_DCHECK_GE(bitrate.get_sum_kbps(), codec_.simulcastStream[0].minBitrate); |
220 | 218 |
221 codec_.maxFramerate = new_framerate; | 219 codec_.maxFramerate = new_framerate; |
222 | 220 |
223 if (encoders_.size() == 1) { | 221 if (encoders_.size() > 1) { |
224 // 1:1. | |
225 // Calculate a rough limit for when to trigger a potental down scale. | |
226 uint32_t k_pixels_per_frame = codec_.width * codec_.height / 1000; | |
227 // TODO(pwestin): we currently lack CAMA, this is a temporary fix to work | |
228 // around the current limitations. | |
229 // Only trigger keyframes if we are allowed to scale down. | |
230 if (configurations_[0].rc_resize_allowed) { | |
231 if (!down_scale_requested_) { | |
232 if (k_pixels_per_frame > bitrate.get_sum_kbps()) { | |
233 down_scale_requested_ = true; | |
234 down_scale_bitrate_ = bitrate.get_sum_kbps(); | |
235 key_frame_request_[0] = true; | |
236 } | |
237 } else { | |
238 if (bitrate.get_sum_kbps() > (2 * down_scale_bitrate_) || | |
239 bitrate.get_sum_kbps() < (down_scale_bitrate_ / 2)) { | |
240 down_scale_requested_ = false; | |
241 } | |
242 } | |
243 } | |
244 } else { | |
245 // If we have more than 1 stream, reduce the qp_max for the low resolution | 222 // If we have more than 1 stream, reduce the qp_max for the low resolution |
246 // stream if frame rate is not too low. The trade-off with lower qp_max is | 223 // stream if frame rate is not too low. The trade-off with lower qp_max is |
247 // possibly more dropped frames, so we only do this if the frame rate is | 224 // possibly more dropped frames, so we only do this if the frame rate is |
248 // above some threshold (base temporal layer is down to 1/4 for 3 layers). | 225 // above some threshold (base temporal layer is down to 1/4 for 3 layers). |
249 // We may want to condition this on bitrate later. | 226 // We may want to condition this on bitrate later. |
250 if (new_framerate > 20) { | 227 if (new_framerate > 20) { |
251 configurations_[encoders_.size() - 1].rc_max_quantizer = 45; | 228 configurations_[encoders_.size() - 1].rc_max_quantizer = 45; |
252 } else { | 229 } else { |
253 // Go back to default value set in InitEncode. | 230 // Go back to default value set in InitEncode. |
254 configurations_[encoders_.size() - 1].rc_max_quantizer = qp_max_; | 231 configurations_[encoders_.size() - 1].rc_max_quantizer = qp_max_; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 // allow zero to represent an unspecified maxBitRate | 294 // allow zero to represent an unspecified maxBitRate |
318 if (inst->maxBitrate > 0 && inst->startBitrate > inst->maxBitrate) { | 295 if (inst->maxBitrate > 0 && inst->startBitrate > inst->maxBitrate) { |
319 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 296 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
320 } | 297 } |
321 if (inst->width <= 1 || inst->height <= 1) { | 298 if (inst->width <= 1 || inst->height <= 1) { |
322 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 299 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
323 } | 300 } |
324 if (number_of_cores < 1) { | 301 if (number_of_cores < 1) { |
325 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 302 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
326 } | 303 } |
327 if (inst->VP8().feedbackModeOn && inst->numberOfSimulcastStreams > 1) { | |
328 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | |
329 } | |
330 if (inst->VP8().automaticResizeOn && inst->numberOfSimulcastStreams > 1) { | 304 if (inst->VP8().automaticResizeOn && inst->numberOfSimulcastStreams > 1) { |
331 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 305 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
332 } | 306 } |
333 int retVal = Release(); | 307 int retVal = Release(); |
334 if (retVal < 0) { | 308 if (retVal < 0) { |
335 return retVal; | 309 return retVal; |
336 } | 310 } |
337 | 311 |
338 int number_of_streams = NumberOfStreams(*inst); | 312 int number_of_streams = NumberOfStreams(*inst); |
339 bool doing_simulcast = (number_of_streams > 1); | 313 bool doing_simulcast = (number_of_streams > 1); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 configurations_[0].g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT; | 391 configurations_[0].g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT; |
418 break; | 392 break; |
419 case kResilientFrames: | 393 case kResilientFrames: |
420 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; // Not supported | 394 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; // Not supported |
421 } | 395 } |
422 | 396 |
423 // rate control settings | 397 // rate control settings |
424 configurations_[0].rc_dropframe_thresh = inst->VP8().frameDroppingOn ? 30 : 0; | 398 configurations_[0].rc_dropframe_thresh = inst->VP8().frameDroppingOn ? 30 : 0; |
425 configurations_[0].rc_end_usage = VPX_CBR; | 399 configurations_[0].rc_end_usage = VPX_CBR; |
426 configurations_[0].g_pass = VPX_RC_ONE_PASS; | 400 configurations_[0].g_pass = VPX_RC_ONE_PASS; |
427 // TODO(hellner): investigate why the following two lines produce | 401 // Handle resizing outside of libvpx. |
428 // automaticResizeOn value of 3 when running | |
429 // WebRtcVideoMediaChannelTest.GetStatsMultipleSendStreams inside the talk | |
430 // framework. | |
431 // configurations_[0].rc_resize_allowed = | |
432 // inst->codecSpecific.VP8.automaticResizeOn ? 1 : 0; | |
433 configurations_[0].rc_resize_allowed = 0; | 402 configurations_[0].rc_resize_allowed = 0; |
434 // Handle resizing outside of libvpx when doing single-stream. | |
435 if (inst->VP8().automaticResizeOn && number_of_streams > 1) { | |
436 configurations_[0].rc_resize_allowed = 1; | |
437 } | |
438 configurations_[0].rc_min_quantizer = 2; | 403 configurations_[0].rc_min_quantizer = 2; |
439 if (inst->qpMax >= configurations_[0].rc_min_quantizer) { | 404 if (inst->qpMax >= configurations_[0].rc_min_quantizer) { |
440 qp_max_ = inst->qpMax; | 405 qp_max_ = inst->qpMax; |
441 } | 406 } |
442 configurations_[0].rc_max_quantizer = qp_max_; | 407 configurations_[0].rc_max_quantizer = qp_max_; |
443 configurations_[0].rc_undershoot_pct = 100; | 408 configurations_[0].rc_undershoot_pct = 100; |
444 configurations_[0].rc_overshoot_pct = 15; | 409 configurations_[0].rc_overshoot_pct = 15; |
445 configurations_[0].rc_buf_initial_sz = 500; | 410 configurations_[0].rc_buf_initial_sz = 500; |
446 configurations_[0].rc_buf_optimal_sz = 600; | 411 configurations_[0].rc_buf_optimal_sz = 600; |
447 configurations_[0].rc_buf_sz = 1000; | 412 configurations_[0].rc_buf_sz = 1000; |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
627 vpx_codec_control( | 592 vpx_codec_control( |
628 &encoders_[1], VP8E_SET_NOISE_SENSITIVITY, | 593 &encoders_[1], VP8E_SET_NOISE_SENSITIVITY, |
629 codec_.VP8()->denoisingOn ? denoiser_state : kDenoiserOff); | 594 codec_.VP8()->denoisingOn ? denoiser_state : kDenoiserOff); |
630 } | 595 } |
631 for (size_t i = 0; i < encoders_.size(); ++i) { | 596 for (size_t i = 0; i < encoders_.size(); ++i) { |
632 // Allow more screen content to be detected as static. | 597 // Allow more screen content to be detected as static. |
633 vpx_codec_control(&(encoders_[i]), VP8E_SET_STATIC_THRESHOLD, | 598 vpx_codec_control(&(encoders_[i]), VP8E_SET_STATIC_THRESHOLD, |
634 codec_.mode == kScreensharing ? 300 : 1); | 599 codec_.mode == kScreensharing ? 300 : 1); |
635 vpx_codec_control(&(encoders_[i]), VP8E_SET_CPUUSED, cpu_speed_[i]); | 600 vpx_codec_control(&(encoders_[i]), VP8E_SET_CPUUSED, cpu_speed_[i]); |
636 vpx_codec_control(&(encoders_[i]), VP8E_SET_TOKEN_PARTITIONS, | 601 vpx_codec_control(&(encoders_[i]), VP8E_SET_TOKEN_PARTITIONS, |
637 static_cast<vp8e_token_partitions>(token_partitions_)); | 602 static_cast<vp8e_token_partitions>(kTokenPartitions)); |
638 vpx_codec_control(&(encoders_[i]), VP8E_SET_MAX_INTRA_BITRATE_PCT, | 603 vpx_codec_control(&(encoders_[i]), VP8E_SET_MAX_INTRA_BITRATE_PCT, |
639 rc_max_intra_target_); | 604 rc_max_intra_target_); |
640 // VP8E_SET_SCREEN_CONTENT_MODE 2 = screen content with more aggressive | 605 // VP8E_SET_SCREEN_CONTENT_MODE 2 = screen content with more aggressive |
641 // rate control (drop frames on large target bitrate overshoot) | 606 // rate control (drop frames on large target bitrate overshoot) |
642 vpx_codec_control(&(encoders_[i]), VP8E_SET_SCREEN_CONTENT_MODE, | 607 vpx_codec_control(&(encoders_[i]), VP8E_SET_SCREEN_CONTENT_MODE, |
643 codec_.mode == kScreensharing ? 2 : 0); | 608 codec_.mode == kScreensharing ? 2 : 0); |
644 // Apply boost on golden frames (has only effect when resilience is off). | 609 // Apply boost on golden frames (has only effect when resilience is off). |
645 if (use_gf_boost_ && codec_.VP8()->resilience == kResilienceOff) { | 610 if (use_gf_boost_ && codec_.VP8()->resilience == kResilienceOff) { |
646 int gf_boost_percent; | 611 int gf_boost_percent; |
647 if (GetGfBoostPercentageFromFieldTrialGroup(&gf_boost_percent)) { | 612 if (GetGfBoostPercentageFromFieldTrialGroup(&gf_boost_percent)) { |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
869 | 834 |
870 int stream_idx = static_cast<int>(encoders_.size()) - 1; | 835 int stream_idx = static_cast<int>(encoders_.size()) - 1; |
871 int result = WEBRTC_VIDEO_CODEC_OK; | 836 int result = WEBRTC_VIDEO_CODEC_OK; |
872 for (size_t encoder_idx = 0; encoder_idx < encoders_.size(); | 837 for (size_t encoder_idx = 0; encoder_idx < encoders_.size(); |
873 ++encoder_idx, --stream_idx) { | 838 ++encoder_idx, --stream_idx) { |
874 vpx_codec_iter_t iter = NULL; | 839 vpx_codec_iter_t iter = NULL; |
875 int part_idx = 0; | 840 int part_idx = 0; |
876 encoded_images_[encoder_idx]._length = 0; | 841 encoded_images_[encoder_idx]._length = 0; |
877 encoded_images_[encoder_idx]._frameType = kVideoFrameDelta; | 842 encoded_images_[encoder_idx]._frameType = kVideoFrameDelta; |
878 RTPFragmentationHeader frag_info; | 843 RTPFragmentationHeader frag_info; |
879 // token_partitions_ is number of bits used. | 844 // kTokenPartitions is number of bits used. |
880 frag_info.VerifyAndAllocateFragmentationHeader((1 << token_partitions_) + | 845 frag_info.VerifyAndAllocateFragmentationHeader((1 << kTokenPartitions) + 1); |
881 1); | |
882 CodecSpecificInfo codec_specific; | 846 CodecSpecificInfo codec_specific; |
883 const vpx_codec_cx_pkt_t* pkt = NULL; | 847 const vpx_codec_cx_pkt_t* pkt = NULL; |
884 while ((pkt = vpx_codec_get_cx_data(&encoders_[encoder_idx], &iter)) != | 848 while ((pkt = vpx_codec_get_cx_data(&encoders_[encoder_idx], &iter)) != |
885 NULL) { | 849 NULL) { |
886 switch (pkt->kind) { | 850 switch (pkt->kind) { |
887 case VPX_CODEC_CX_FRAME_PKT: { | 851 case VPX_CODEC_CX_FRAME_PKT: { |
888 size_t length = encoded_images_[encoder_idx]._length; | 852 size_t length = encoded_images_[encoder_idx]._length; |
889 if (pkt->data.frame.sz + length > | 853 if (pkt->data.frame.sz + length > |
890 encoded_images_[encoder_idx]._size) { | 854 encoded_images_[encoder_idx]._size) { |
891 uint8_t* buffer = new uint8_t[pkt->data.frame.sz + length]; | 855 uint8_t* buffer = new uint8_t[pkt->data.frame.sz + length]; |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
966 return WEBRTC_VIDEO_CODEC_OK; | 930 return WEBRTC_VIDEO_CODEC_OK; |
967 } | 931 } |
968 | 932 |
969 int VP8EncoderImpl::RegisterEncodeCompleteCallback( | 933 int VP8EncoderImpl::RegisterEncodeCompleteCallback( |
970 EncodedImageCallback* callback) { | 934 EncodedImageCallback* callback) { |
971 encoded_complete_callback_ = callback; | 935 encoded_complete_callback_ = callback; |
972 return WEBRTC_VIDEO_CODEC_OK; | 936 return WEBRTC_VIDEO_CODEC_OK; |
973 } | 937 } |
974 | 938 |
975 VP8DecoderImpl::VP8DecoderImpl() | 939 VP8DecoderImpl::VP8DecoderImpl() |
976 : buffer_pool_(false, 300 /* max_number_of_buffers*/), | 940 : use_postproc_arm_(webrtc::field_trial::FindFullName( |
| 941 kVp8PostProcArmFieldTrial) == "Enabled"), |
| 942 buffer_pool_(false, 300 /* max_number_of_buffers*/), |
977 decode_complete_callback_(NULL), | 943 decode_complete_callback_(NULL), |
978 inited_(false), | 944 inited_(false), |
979 decoder_(NULL), | 945 decoder_(NULL), |
980 image_format_(VPX_IMG_FMT_NONE), | |
981 ref_frame_(NULL), | |
982 propagation_cnt_(-1), | 946 propagation_cnt_(-1), |
983 last_frame_width_(0), | 947 last_frame_width_(0), |
984 last_frame_height_(0), | 948 last_frame_height_(0), |
985 key_frame_required_(true), | 949 key_frame_required_(true) {} |
986 use_postproc_arm_(webrtc::field_trial::FindFullName( | |
987 kVp8PostProcArmFieldTrial) == "Enabled") {} | |
988 | 950 |
989 VP8DecoderImpl::~VP8DecoderImpl() { | 951 VP8DecoderImpl::~VP8DecoderImpl() { |
990 inited_ = true; // in order to do the actual release | 952 inited_ = true; // in order to do the actual release |
991 Release(); | 953 Release(); |
992 } | 954 } |
993 | 955 |
994 int VP8DecoderImpl::InitDecode(const VideoCodec* inst, int number_of_cores) { | 956 int VP8DecoderImpl::InitDecode(const VideoCodec* inst, int number_of_cores) { |
995 int ret_val = Release(); | 957 int ret_val = Release(); |
996 if (ret_val < 0) { | 958 if (ret_val < 0) { |
997 return ret_val; | 959 return ret_val; |
998 } | 960 } |
999 if (decoder_ == NULL) { | 961 if (decoder_ == NULL) { |
1000 decoder_ = new vpx_codec_ctx_t; | 962 decoder_ = new vpx_codec_ctx_t; |
1001 memset(decoder_, 0, sizeof(*decoder_)); | 963 memset(decoder_, 0, sizeof(*decoder_)); |
1002 } | 964 } |
1003 vpx_codec_dec_cfg_t cfg; | 965 vpx_codec_dec_cfg_t cfg; |
1004 // Setting number of threads to a constant value (1) | 966 // Setting number of threads to a constant value (1) |
1005 cfg.threads = 1; | 967 cfg.threads = 1; |
1006 cfg.h = cfg.w = 0; // set after decode | 968 cfg.h = cfg.w = 0; // set after decode |
1007 | 969 |
1008 vpx_codec_flags_t flags = 0; | |
1009 #if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64) || defined(ANDROID) | 970 #if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64) || defined(ANDROID) |
1010 if (use_postproc_arm_) { | 971 vpx_codec_flags_t flags = use_postproc_arm_ ? VPX_CODEC_USE_POSTPROC : 0; |
1011 flags = VPX_CODEC_USE_POSTPROC; | |
1012 } | |
1013 #else | 972 #else |
1014 flags = VPX_CODEC_USE_POSTPROC; | 973 vpx_codec_flags_t flags = VPX_CODEC_USE_POSTPROC; |
1015 #endif | 974 #endif |
1016 | 975 |
1017 if (vpx_codec_dec_init(decoder_, vpx_codec_vp8_dx(), &cfg, flags)) { | 976 if (vpx_codec_dec_init(decoder_, vpx_codec_vp8_dx(), &cfg, flags)) { |
1018 delete decoder_; | 977 delete decoder_; |
1019 decoder_ = nullptr; | 978 decoder_ = nullptr; |
1020 return WEBRTC_VIDEO_CODEC_MEMORY; | 979 return WEBRTC_VIDEO_CODEC_MEMORY; |
1021 } | 980 } |
1022 | 981 |
1023 // Save VideoCodec instance for later; mainly for duplicating the decoder. | |
1024 if (&codec_ != inst) | |
1025 codec_ = *inst; | |
1026 propagation_cnt_ = -1; | 982 propagation_cnt_ = -1; |
1027 | |
1028 inited_ = true; | 983 inited_ = true; |
1029 | 984 |
1030 // Always start with a complete key frame. | 985 // Always start with a complete key frame. |
1031 key_frame_required_ = true; | 986 key_frame_required_ = true; |
1032 return WEBRTC_VIDEO_CODEC_OK; | 987 return WEBRTC_VIDEO_CODEC_OK; |
1033 } | 988 } |
1034 | 989 |
1035 int VP8DecoderImpl::Decode(const EncodedImage& input_image, | 990 int VP8DecoderImpl::Decode(const EncodedImage& input_image, |
1036 bool missing_frames, | 991 bool missing_frames, |
1037 const RTPFragmentationHeader* fragmentation, | 992 const RTPFragmentationHeader* fragmentation, |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1083 return WEBRTC_VIDEO_CODEC_ERROR; | 1038 return WEBRTC_VIDEO_CODEC_ERROR; |
1084 // We have a key frame - is it complete? | 1039 // We have a key frame - is it complete? |
1085 if (input_image._completeFrame) { | 1040 if (input_image._completeFrame) { |
1086 key_frame_required_ = false; | 1041 key_frame_required_ = false; |
1087 } else { | 1042 } else { |
1088 return WEBRTC_VIDEO_CODEC_ERROR; | 1043 return WEBRTC_VIDEO_CODEC_ERROR; |
1089 } | 1044 } |
1090 } | 1045 } |
1091 // Restrict error propagation using key frame requests. | 1046 // Restrict error propagation using key frame requests. |
1092 // Reset on a key frame refresh. | 1047 // Reset on a key frame refresh. |
1093 if (input_image._frameType == kVideoFrameKey && | 1048 if (input_image._frameType == kVideoFrameKey && input_image._completeFrame) { |
1094 input_image._completeFrame) { | 1049 propagation_cnt_ = -1; |
1095 propagation_cnt_ = -1; | 1050 // Start count on first loss. |
1096 // Start count on first loss. | |
1097 } else if ((!input_image._completeFrame || missing_frames) && | 1051 } else if ((!input_image._completeFrame || missing_frames) && |
1098 propagation_cnt_ == -1) { | 1052 propagation_cnt_ == -1) { |
1099 propagation_cnt_ = 0; | 1053 propagation_cnt_ = 0; |
1100 } | 1054 } |
1101 if (propagation_cnt_ >= 0) { | 1055 if (propagation_cnt_ >= 0) { |
1102 propagation_cnt_++; | 1056 propagation_cnt_++; |
1103 } | 1057 } |
1104 | 1058 |
1105 vpx_codec_iter_t iter = NULL; | 1059 vpx_codec_iter_t iter = NULL; |
1106 vpx_image_t* img; | 1060 vpx_image_t* img; |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1179 buffer->MutableDataY(), buffer->StrideY(), | 1133 buffer->MutableDataY(), buffer->StrideY(), |
1180 buffer->MutableDataU(), buffer->StrideU(), | 1134 buffer->MutableDataU(), buffer->StrideU(), |
1181 buffer->MutableDataV(), buffer->StrideV(), | 1135 buffer->MutableDataV(), buffer->StrideV(), |
1182 img->d_w, img->d_h); | 1136 img->d_w, img->d_h); |
1183 | 1137 |
1184 VideoFrame decoded_image(buffer, timestamp, 0, kVideoRotation_0); | 1138 VideoFrame decoded_image(buffer, timestamp, 0, kVideoRotation_0); |
1185 decoded_image.set_ntp_time_ms(ntp_time_ms); | 1139 decoded_image.set_ntp_time_ms(ntp_time_ms); |
1186 decode_complete_callback_->Decoded(decoded_image, rtc::Optional<int32_t>(), | 1140 decode_complete_callback_->Decoded(decoded_image, rtc::Optional<int32_t>(), |
1187 rtc::Optional<uint8_t>(qp)); | 1141 rtc::Optional<uint8_t>(qp)); |
1188 | 1142 |
1189 // Remember image format for later | |
1190 image_format_ = img->fmt; | |
1191 return WEBRTC_VIDEO_CODEC_OK; | 1143 return WEBRTC_VIDEO_CODEC_OK; |
1192 } | 1144 } |
1193 | 1145 |
1194 int VP8DecoderImpl::RegisterDecodeCompleteCallback( | 1146 int VP8DecoderImpl::RegisterDecodeCompleteCallback( |
1195 DecodedImageCallback* callback) { | 1147 DecodedImageCallback* callback) { |
1196 decode_complete_callback_ = callback; | 1148 decode_complete_callback_ = callback; |
1197 return WEBRTC_VIDEO_CODEC_OK; | 1149 return WEBRTC_VIDEO_CODEC_OK; |
1198 } | 1150 } |
1199 | 1151 |
1200 int VP8DecoderImpl::Release() { | 1152 int VP8DecoderImpl::Release() { |
1201 if (decoder_ != NULL) { | 1153 if (decoder_ != NULL) { |
1202 if (vpx_codec_destroy(decoder_)) { | 1154 if (vpx_codec_destroy(decoder_)) { |
1203 return WEBRTC_VIDEO_CODEC_MEMORY; | 1155 return WEBRTC_VIDEO_CODEC_MEMORY; |
1204 } | 1156 } |
1205 delete decoder_; | 1157 delete decoder_; |
1206 decoder_ = NULL; | 1158 decoder_ = NULL; |
1207 } | 1159 } |
1208 if (ref_frame_ != NULL) { | |
1209 vpx_img_free(&ref_frame_->img); | |
1210 delete ref_frame_; | |
1211 ref_frame_ = NULL; | |
1212 } | |
1213 buffer_pool_.Release(); | 1160 buffer_pool_.Release(); |
1214 inited_ = false; | 1161 inited_ = false; |
1215 return WEBRTC_VIDEO_CODEC_OK; | 1162 return WEBRTC_VIDEO_CODEC_OK; |
1216 } | 1163 } |
1217 | 1164 |
1218 const char* VP8DecoderImpl::ImplementationName() const { | 1165 const char* VP8DecoderImpl::ImplementationName() const { |
1219 return "libvpx"; | 1166 return "libvpx"; |
1220 } | 1167 } |
1221 | 1168 |
1222 int VP8DecoderImpl::CopyReference(VP8DecoderImpl* copy) { | |
1223 // The type of frame to copy should be set in ref_frame_->frame_type | |
1224 // before the call to this function. | |
1225 if (vpx_codec_control(decoder_, VP8_COPY_REFERENCE, ref_frame_) != | |
1226 VPX_CODEC_OK) { | |
1227 return -1; | |
1228 } | |
1229 if (vpx_codec_control(copy->decoder_, VP8_SET_REFERENCE, ref_frame_) != | |
1230 VPX_CODEC_OK) { | |
1231 return -1; | |
1232 } | |
1233 return 0; | |
1234 } | |
1235 | |
1236 } // namespace webrtc | 1169 } // namespace webrtc |
OLD | NEW |