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 15 matching lines...) Expand all Loading... |
26 : size_bytes(size_bytes), | 26 : size_bytes(size_bytes), |
27 timestamp(timestamp), | 27 timestamp(timestamp), |
28 time_complete_ms(time_complete_ms) {} | 28 time_complete_ms(time_complete_ms) {} |
29 | 29 |
30 size_t size_bytes; | 30 size_t size_bytes; |
31 uint32_t timestamp; | 31 uint32_t timestamp; |
32 int64_t time_complete_ms; | 32 int64_t time_complete_ms; |
33 }; | 33 }; |
34 | 34 |
35 MediaOptimization::MediaOptimization(Clock* clock) | 35 MediaOptimization::MediaOptimization(Clock* clock) |
36 : crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), | 36 : clock_(clock), |
37 clock_(clock), | |
38 max_bit_rate_(0), | 37 max_bit_rate_(0), |
39 codec_width_(0), | 38 codec_width_(0), |
40 codec_height_(0), | 39 codec_height_(0), |
41 user_frame_rate_(0), | 40 user_frame_rate_(0), |
42 frame_dropper_(new FrameDropper), | 41 frame_dropper_(new FrameDropper), |
43 send_statistics_zero_encode_(0), | 42 send_statistics_zero_encode_(0), |
44 max_payload_size_(1460), | 43 max_payload_size_(1460), |
45 video_target_bitrate_(0), | 44 video_target_bitrate_(0), |
46 incoming_frame_rate_(0), | 45 incoming_frame_rate_(0), |
47 encoded_frame_samples_(), | 46 encoded_frame_samples_(), |
48 avg_sent_bit_rate_bps_(0), | 47 avg_sent_bit_rate_bps_(0), |
49 avg_sent_framerate_(0), | 48 avg_sent_framerate_(0), |
50 num_layers_(0) { | 49 num_layers_(0) { |
51 memset(send_statistics_, 0, sizeof(send_statistics_)); | 50 memset(send_statistics_, 0, sizeof(send_statistics_)); |
52 memset(incoming_frame_times_, -1, sizeof(incoming_frame_times_)); | 51 memset(incoming_frame_times_, -1, sizeof(incoming_frame_times_)); |
53 } | 52 } |
54 | 53 |
55 MediaOptimization::~MediaOptimization(void) { | 54 MediaOptimization::~MediaOptimization(void) { |
56 } | 55 } |
57 | 56 |
58 void MediaOptimization::Reset() { | 57 void MediaOptimization::Reset() { |
59 CriticalSectionScoped lock(crit_sect_.get()); | 58 rtc::CritScope lock(&crit_sect_); |
60 SetEncodingDataInternal(0, 0, 0, 0, 0, 0, max_payload_size_); | 59 SetEncodingDataInternal(0, 0, 0, 0, 0, 0, max_payload_size_); |
61 memset(incoming_frame_times_, -1, sizeof(incoming_frame_times_)); | 60 memset(incoming_frame_times_, -1, sizeof(incoming_frame_times_)); |
62 incoming_frame_rate_ = 0.0; | 61 incoming_frame_rate_ = 0.0; |
63 frame_dropper_->Reset(); | 62 frame_dropper_->Reset(); |
64 frame_dropper_->SetRates(0, 0); | 63 frame_dropper_->SetRates(0, 0); |
65 send_statistics_zero_encode_ = 0; | 64 send_statistics_zero_encode_ = 0; |
66 video_target_bitrate_ = 0; | 65 video_target_bitrate_ = 0; |
67 codec_width_ = 0; | 66 codec_width_ = 0; |
68 codec_height_ = 0; | 67 codec_height_ = 0; |
69 user_frame_rate_ = 0; | 68 user_frame_rate_ = 0; |
70 encoded_frame_samples_.clear(); | 69 encoded_frame_samples_.clear(); |
71 avg_sent_bit_rate_bps_ = 0; | 70 avg_sent_bit_rate_bps_ = 0; |
72 num_layers_ = 1; | 71 num_layers_ = 1; |
73 } | 72 } |
74 | 73 |
75 void MediaOptimization::SetEncodingData(int32_t max_bit_rate, | 74 void MediaOptimization::SetEncodingData(int32_t max_bit_rate, |
76 uint32_t target_bitrate, | 75 uint32_t target_bitrate, |
77 uint16_t width, | 76 uint16_t width, |
78 uint16_t height, | 77 uint16_t height, |
79 uint32_t frame_rate, | 78 uint32_t frame_rate, |
80 int num_layers, | 79 int num_layers, |
81 int32_t mtu) { | 80 int32_t mtu) { |
82 CriticalSectionScoped lock(crit_sect_.get()); | 81 rtc::CritScope lock(&crit_sect_); |
83 SetEncodingDataInternal(max_bit_rate, frame_rate, target_bitrate, width, | 82 SetEncodingDataInternal(max_bit_rate, frame_rate, target_bitrate, width, |
84 height, num_layers, mtu); | 83 height, num_layers, mtu); |
85 } | 84 } |
86 | 85 |
87 void MediaOptimization::SetEncodingDataInternal(int32_t max_bit_rate, | 86 void MediaOptimization::SetEncodingDataInternal(int32_t max_bit_rate, |
88 uint32_t frame_rate, | 87 uint32_t frame_rate, |
89 uint32_t target_bitrate, | 88 uint32_t target_bitrate, |
90 uint16_t width, | 89 uint16_t width, |
91 uint16_t height, | 90 uint16_t height, |
92 int num_layers, | 91 int num_layers, |
93 int32_t mtu) { | 92 int32_t mtu) { |
94 // Everything codec specific should be reset here since this means the codec | 93 // Everything codec specific should be reset here since this means the codec |
95 // has changed. | 94 // has changed. |
96 | 95 |
97 max_bit_rate_ = max_bit_rate; | 96 max_bit_rate_ = max_bit_rate; |
98 video_target_bitrate_ = target_bitrate; | 97 video_target_bitrate_ = target_bitrate; |
99 float target_bitrate_kbps = static_cast<float>(target_bitrate) / 1000.0f; | 98 float target_bitrate_kbps = static_cast<float>(target_bitrate) / 1000.0f; |
100 frame_dropper_->Reset(); | 99 frame_dropper_->Reset(); |
101 frame_dropper_->SetRates(target_bitrate_kbps, static_cast<float>(frame_rate)); | 100 frame_dropper_->SetRates(target_bitrate_kbps, static_cast<float>(frame_rate)); |
102 user_frame_rate_ = static_cast<float>(frame_rate); | 101 user_frame_rate_ = static_cast<float>(frame_rate); |
103 codec_width_ = width; | 102 codec_width_ = width; |
104 codec_height_ = height; | 103 codec_height_ = height; |
105 num_layers_ = (num_layers <= 1) ? 1 : num_layers; // Can also be zero. | 104 num_layers_ = (num_layers <= 1) ? 1 : num_layers; // Can also be zero. |
106 max_payload_size_ = mtu; | 105 max_payload_size_ = mtu; |
107 } | 106 } |
108 | 107 |
109 uint32_t MediaOptimization::SetTargetRates(uint32_t target_bitrate) { | 108 uint32_t MediaOptimization::SetTargetRates(uint32_t target_bitrate) { |
110 CriticalSectionScoped lock(crit_sect_.get()); | 109 rtc::CritScope lock(&crit_sect_); |
111 | 110 |
112 video_target_bitrate_ = target_bitrate; | 111 video_target_bitrate_ = target_bitrate; |
113 | 112 |
114 // Cap target video bitrate to codec maximum. | 113 // Cap target video bitrate to codec maximum. |
115 if (max_bit_rate_ > 0 && video_target_bitrate_ > max_bit_rate_) { | 114 if (max_bit_rate_ > 0 && video_target_bitrate_ > max_bit_rate_) { |
116 video_target_bitrate_ = max_bit_rate_; | 115 video_target_bitrate_ = max_bit_rate_; |
117 } | 116 } |
118 | 117 |
119 // Update encoding rates following protection settings. | 118 // Update encoding rates following protection settings. |
120 float target_video_bitrate_kbps = | 119 float target_video_bitrate_kbps = |
121 static_cast<float>(video_target_bitrate_) / 1000.0f; | 120 static_cast<float>(video_target_bitrate_) / 1000.0f; |
122 frame_dropper_->SetRates(target_video_bitrate_kbps, incoming_frame_rate_); | 121 frame_dropper_->SetRates(target_video_bitrate_kbps, incoming_frame_rate_); |
123 | 122 |
124 return video_target_bitrate_; | 123 return video_target_bitrate_; |
125 } | 124 } |
126 | 125 |
127 uint32_t MediaOptimization::InputFrameRate() { | 126 uint32_t MediaOptimization::InputFrameRate() { |
128 CriticalSectionScoped lock(crit_sect_.get()); | 127 rtc::CritScope lock(&crit_sect_); |
129 return InputFrameRateInternal(); | 128 return InputFrameRateInternal(); |
130 } | 129 } |
131 | 130 |
132 uint32_t MediaOptimization::InputFrameRateInternal() { | 131 uint32_t MediaOptimization::InputFrameRateInternal() { |
133 ProcessIncomingFrameRate(clock_->TimeInMilliseconds()); | 132 ProcessIncomingFrameRate(clock_->TimeInMilliseconds()); |
134 uint32_t framerate = static_cast<uint32_t>(std::min<float>( | 133 uint32_t framerate = static_cast<uint32_t>(std::min<float>( |
135 std::numeric_limits<uint32_t>::max(), incoming_frame_rate_ + 0.5f)); | 134 std::numeric_limits<uint32_t>::max(), incoming_frame_rate_ + 0.5f)); |
136 return framerate; | 135 return framerate; |
137 } | 136 } |
138 | 137 |
139 uint32_t MediaOptimization::SentFrameRate() { | 138 uint32_t MediaOptimization::SentFrameRate() { |
140 CriticalSectionScoped lock(crit_sect_.get()); | 139 rtc::CritScope lock(&crit_sect_); |
141 return SentFrameRateInternal(); | 140 return SentFrameRateInternal(); |
142 } | 141 } |
143 | 142 |
144 uint32_t MediaOptimization::SentFrameRateInternal() { | 143 uint32_t MediaOptimization::SentFrameRateInternal() { |
145 PurgeOldFrameSamples(clock_->TimeInMilliseconds()); | 144 PurgeOldFrameSamples(clock_->TimeInMilliseconds()); |
146 UpdateSentFramerate(); | 145 UpdateSentFramerate(); |
147 return avg_sent_framerate_; | 146 return avg_sent_framerate_; |
148 } | 147 } |
149 | 148 |
150 uint32_t MediaOptimization::SentBitRate() { | 149 uint32_t MediaOptimization::SentBitRate() { |
151 CriticalSectionScoped lock(crit_sect_.get()); | 150 rtc::CritScope lock(&crit_sect_); |
152 const int64_t now_ms = clock_->TimeInMilliseconds(); | 151 const int64_t now_ms = clock_->TimeInMilliseconds(); |
153 PurgeOldFrameSamples(now_ms); | 152 PurgeOldFrameSamples(now_ms); |
154 UpdateSentBitrate(now_ms); | 153 UpdateSentBitrate(now_ms); |
155 return avg_sent_bit_rate_bps_; | 154 return avg_sent_bit_rate_bps_; |
156 } | 155 } |
157 | 156 |
158 int32_t MediaOptimization::UpdateWithEncodedData( | 157 int32_t MediaOptimization::UpdateWithEncodedData( |
159 const EncodedImage& encoded_image) { | 158 const EncodedImage& encoded_image) { |
160 size_t encoded_length = encoded_image._length; | 159 size_t encoded_length = encoded_image._length; |
161 uint32_t timestamp = encoded_image._timeStamp; | 160 uint32_t timestamp = encoded_image._timeStamp; |
162 CriticalSectionScoped lock(crit_sect_.get()); | 161 rtc::CritScope lock(&crit_sect_); |
163 const int64_t now_ms = clock_->TimeInMilliseconds(); | 162 const int64_t now_ms = clock_->TimeInMilliseconds(); |
164 PurgeOldFrameSamples(now_ms); | 163 PurgeOldFrameSamples(now_ms); |
165 if (encoded_frame_samples_.size() > 0 && | 164 if (encoded_frame_samples_.size() > 0 && |
166 encoded_frame_samples_.back().timestamp == timestamp) { | 165 encoded_frame_samples_.back().timestamp == timestamp) { |
167 // Frames having the same timestamp are generated from the same input | 166 // Frames having the same timestamp are generated from the same input |
168 // frame. We don't want to double count them, but only increment the | 167 // frame. We don't want to double count them, but only increment the |
169 // size_bytes. | 168 // size_bytes. |
170 encoded_frame_samples_.back().size_bytes += encoded_length; | 169 encoded_frame_samples_.back().size_bytes += encoded_length; |
171 encoded_frame_samples_.back().time_complete_ms = now_ms; | 170 encoded_frame_samples_.back().time_complete_ms = now_ms; |
172 } else { | 171 } else { |
173 encoded_frame_samples_.push_back( | 172 encoded_frame_samples_.push_back( |
174 EncodedFrameSample(encoded_length, timestamp, now_ms)); | 173 EncodedFrameSample(encoded_length, timestamp, now_ms)); |
175 } | 174 } |
176 UpdateSentBitrate(now_ms); | 175 UpdateSentBitrate(now_ms); |
177 UpdateSentFramerate(); | 176 UpdateSentFramerate(); |
178 if (encoded_length > 0) { | 177 if (encoded_length > 0) { |
179 const bool delta_frame = encoded_image._frameType != kVideoFrameKey; | 178 const bool delta_frame = encoded_image._frameType != kVideoFrameKey; |
180 frame_dropper_->Fill(encoded_length, delta_frame); | 179 frame_dropper_->Fill(encoded_length, delta_frame); |
181 } | 180 } |
182 | 181 |
183 return VCM_OK; | 182 return VCM_OK; |
184 } | 183 } |
185 | 184 |
186 void MediaOptimization::EnableFrameDropper(bool enable) { | 185 void MediaOptimization::EnableFrameDropper(bool enable) { |
187 CriticalSectionScoped lock(crit_sect_.get()); | 186 rtc::CritScope lock(&crit_sect_); |
188 frame_dropper_->Enable(enable); | 187 frame_dropper_->Enable(enable); |
189 } | 188 } |
190 | 189 |
191 bool MediaOptimization::DropFrame() { | 190 bool MediaOptimization::DropFrame() { |
192 CriticalSectionScoped lock(crit_sect_.get()); | 191 rtc::CritScope lock(&crit_sect_); |
193 UpdateIncomingFrameRate(); | 192 UpdateIncomingFrameRate(); |
194 // Leak appropriate number of bytes. | 193 // Leak appropriate number of bytes. |
195 frame_dropper_->Leak((uint32_t)(InputFrameRateInternal() + 0.5f)); | 194 frame_dropper_->Leak((uint32_t)(InputFrameRateInternal() + 0.5f)); |
196 return frame_dropper_->DropFrame(); | 195 return frame_dropper_->DropFrame(); |
197 } | 196 } |
198 | 197 |
199 void MediaOptimization::UpdateIncomingFrameRate() { | 198 void MediaOptimization::UpdateIncomingFrameRate() { |
200 int64_t now = clock_->TimeInMilliseconds(); | 199 int64_t now = clock_->TimeInMilliseconds(); |
201 if (incoming_frame_times_[0] == 0) { | 200 if (incoming_frame_times_[0] == 0) { |
202 // No shifting if this is the first time. | 201 // No shifting if this is the first time. |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
273 const int64_t diff = | 272 const int64_t diff = |
274 incoming_frame_times_[0] - incoming_frame_times_[num - 1]; | 273 incoming_frame_times_[0] - incoming_frame_times_[num - 1]; |
275 incoming_frame_rate_ = 0.0; // No frame rate estimate available. | 274 incoming_frame_rate_ = 0.0; // No frame rate estimate available. |
276 if (diff > 0) { | 275 if (diff > 0) { |
277 incoming_frame_rate_ = nr_of_frames * 1000.0f / static_cast<float>(diff); | 276 incoming_frame_rate_ = nr_of_frames * 1000.0f / static_cast<float>(diff); |
278 } | 277 } |
279 } | 278 } |
280 } | 279 } |
281 } // namespace media_optimization | 280 } // namespace media_optimization |
282 } // namespace webrtc | 281 } // namespace webrtc |
OLD | NEW |