1 /* 2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3 * 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 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "webrtc/modules/video_processing/main/interface/video_processing.h" 12 #include "webrtc/modules/video_processing/main/source/video_decimator.h" 13 #include "webrtc/system_wrappers/interface/tick_util.h" 14 15 #define VD_MIN(a, b) ((a) < (b)) ? (a) : (b) 16 17 namespace webrtc { 18 VPMVideoDecimator()19VPMVideoDecimator::VPMVideoDecimator() { 20 Reset(); 21 } 22 ~VPMVideoDecimator()23VPMVideoDecimator::~VPMVideoDecimator() {} 24 Reset()25void VPMVideoDecimator::Reset() { 26 overshoot_modifier_ = 0; 27 drop_count_ = 0; 28 keep_count_ = 0; 29 target_frame_rate_ = 30; 30 incoming_frame_rate_ = 0.0f; 31 memset(incoming_frame_times_, 0, sizeof(incoming_frame_times_)); 32 enable_temporal_decimation_ = true; 33 } 34 EnableTemporalDecimation(bool enable)35void VPMVideoDecimator::EnableTemporalDecimation(bool enable) { 36 enable_temporal_decimation_ = enable; 37 } 38 SetTargetFramerate(uint32_t frame_rate)39int32_t VPMVideoDecimator::SetTargetFramerate(uint32_t frame_rate) { 40 if (frame_rate == 0) return VPM_PARAMETER_ERROR; 41 42 target_frame_rate_ = frame_rate; 43 return VPM_OK; 44 } 45 DropFrame()46bool VPMVideoDecimator::DropFrame() { 47 if (!enable_temporal_decimation_) return false; 48 49 if (incoming_frame_rate_ <= 0) return false; 50 51 const uint32_t incomingframe_rate = 52 static_cast<uint32_t>(incoming_frame_rate_ + 0.5f); 53 54 if (target_frame_rate_ == 0) return true; 55 56 bool drop = false; 57 if (incomingframe_rate > target_frame_rate_) { 58 int32_t overshoot = 59 overshoot_modifier_ + (incomingframe_rate - target_frame_rate_); 60 if (overshoot < 0) { 61 overshoot = 0; 62 overshoot_modifier_ = 0; 63 } 64 65 if (overshoot && 2 * overshoot < (int32_t) incomingframe_rate) { 66 if (drop_count_) { // Just got here so drop to be sure. 67 drop_count_ = 0; 68 return true; 69 } 70 const uint32_t dropVar = incomingframe_rate / overshoot; 71 72 if (keep_count_ >= dropVar) { 73 drop = true; 74 overshoot_modifier_ = -((int32_t) incomingframe_rate % overshoot) / 3; 75 keep_count_ = 1; 76 } else { 77 keep_count_++; 78 } 79 } else { 80 keep_count_ = 0; 81 const uint32_t dropVar = overshoot / target_frame_rate_; 82 if (drop_count_ < dropVar) { 83 drop = true; 84 drop_count_++; 85 } else { 86 overshoot_modifier_ = overshoot % target_frame_rate_; 87 drop = false; 88 drop_count_ = 0; 89 } 90 } 91 } 92 return drop; 93 } 94 95 Decimatedframe_rate()96uint32_t VPMVideoDecimator::Decimatedframe_rate() { 97 ProcessIncomingframe_rate(TickTime::MillisecondTimestamp()); 98 if (!enable_temporal_decimation_) { 99 return static_cast<uint32_t>(incoming_frame_rate_ + 0.5f); 100 } 101 return VD_MIN(target_frame_rate_, 102 static_cast<uint32_t>(incoming_frame_rate_ + 0.5f)); 103 } 104 Inputframe_rate()105uint32_t VPMVideoDecimator::Inputframe_rate() { 106 ProcessIncomingframe_rate(TickTime::MillisecondTimestamp()); 107 return static_cast<uint32_t>(incoming_frame_rate_ + 0.5f); 108 } 109 UpdateIncomingframe_rate()110void VPMVideoDecimator::UpdateIncomingframe_rate() { 111 int64_t now = TickTime::MillisecondTimestamp(); 112 if (incoming_frame_times_[0] == 0) { 113 // First no shift. 114 } else { 115 // Shift. 116 for (int i = kFrameCountHistory_size - 2; i >= 0; i--) { 117 incoming_frame_times_[i+1] = incoming_frame_times_[i]; 118 } 119 } 120 incoming_frame_times_[0] = now; 121 ProcessIncomingframe_rate(now); 122 } 123 ProcessIncomingframe_rate(int64_t now)124void VPMVideoDecimator::ProcessIncomingframe_rate(int64_t now) { 125 int32_t num = 0; 126 int32_t nrOfFrames = 0; 127 for (num = 1; num < (kFrameCountHistory_size - 1); num++) { 128 // Don't use data older than 2sec. 129 if (incoming_frame_times_[num] <= 0 || 130 now - incoming_frame_times_[num] > kFrameHistoryWindowMs) { 131 break; 132 } else { 133 nrOfFrames++; 134 } 135 } 136 if (num > 1) { 137 int64_t diff = now - incoming_frame_times_[num-1]; 138 incoming_frame_rate_ = 1.0; 139 if (diff > 0) { 140 incoming_frame_rate_ = nrOfFrames * 1000.0f / static_cast<float>(diff); 141 } 142 } else { 143 incoming_frame_rate_ = static_cast<float>(nrOfFrames); 144 } 145 } 146 147 } // namespace webrtc 148