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