Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1097)

Unified Diff: webrtc/test/fake_encoder.cc

Issue 2883963002: Periodically update codec bit/frame rate settings. (Closed)
Patch Set: cleanup Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/test/fake_encoder.cc
diff --git a/webrtc/test/fake_encoder.cc b/webrtc/test/fake_encoder.cc
index fce12c61a804c8af841435b001779374b912066c..8de59a1d0b8ec57b9aa52a46f8cedf70f233aeae 100644
--- a/webrtc/test/fake_encoder.cc
+++ b/webrtc/test/fake_encoder.cc
@@ -27,8 +27,9 @@ namespace test {
FakeEncoder::FakeEncoder(Clock* clock)
: clock_(clock),
callback_(nullptr),
+ configured_input_framerate_(-1),
max_target_bitrate_kbps_(-1),
- last_encode_time_ms_(0) {
+ pending_keyframe_(true) {
// Generate some arbitrary not-all-zero data
for (size_t i = 0; i < sizeof(encoded_buffer_); ++i) {
encoded_buffer_[i] = static_cast<uint8_t>(i);
@@ -47,6 +48,8 @@ int32_t FakeEncoder::InitEncode(const VideoCodec* config,
rtc::CritScope cs(&crit_sect_);
config_ = *config;
target_bitrate_.SetBitrate(0, 0, config_.startBitrate * 1000);
+ configured_input_framerate_ = config_.maxFramerate;
+ pending_keyframe_ = true;
return 0;
}
@@ -59,9 +62,10 @@ int32_t FakeEncoder::Encode(const VideoFrame& input_image,
EncodedImageCallback* callback;
uint32_t target_bitrate_sum_kbps;
int max_target_bitrate_kbps;
- int64_t last_encode_time_ms;
size_t num_encoded_bytes;
+ int framerate;
VideoCodecMode mode;
+ bool keyframe;
{
rtc::CritScope cs(&crit_sect_);
max_framerate = config_.maxFramerate;
@@ -72,42 +76,33 @@ int32_t FakeEncoder::Encode(const VideoFrame& input_image,
callback = callback_;
target_bitrate_sum_kbps = target_bitrate_.get_sum_kbps();
max_target_bitrate_kbps = max_target_bitrate_kbps_;
- last_encode_time_ms = last_encode_time_ms_;
num_encoded_bytes = sizeof(encoded_buffer_);
mode = config_.mode;
+ if (configured_input_framerate_ > 0) {
+ framerate = configured_input_framerate_;
+ } else {
+ framerate = max_framerate;
+ }
+ keyframe = pending_keyframe_;
+ pending_keyframe_ = false;
}
- int64_t time_now_ms = clock_->TimeInMilliseconds();
- const bool first_encode = (last_encode_time_ms == 0);
- RTC_DCHECK_GT(max_framerate, 0);
- int64_t time_since_last_encode_ms = 1000 / max_framerate;
- if (!first_encode) {
- // For all frames but the first we can estimate the display time by looking
- // at the display time of the previous frame.
- time_since_last_encode_ms = time_now_ms - last_encode_time_ms;
- }
- if (time_since_last_encode_ms > 3 * 1000 / max_framerate) {
- // Rudimentary check to make sure we don't widely overshoot bitrate target
- // when resuming encoding after a suspension.
- time_since_last_encode_ms = 3 * 1000 / max_framerate;
+ for (FrameType frame_type : *frame_types) {
+ if (frame_type == kVideoFrameKey) {
+ keyframe = true;
+ break;
+ }
}
- size_t bits_available =
- static_cast<size_t>(target_bitrate_sum_kbps * time_since_last_encode_ms);
- size_t min_bits = static_cast<size_t>(simulcast_streams[0].minBitrate *
- time_since_last_encode_ms);
+ RTC_DCHECK_GT(max_framerate, 0);
- if (bits_available < min_bits)
- bits_available = min_bits;
- size_t max_bits =
- static_cast<size_t>(max_target_bitrate_kbps * time_since_last_encode_ms);
- if (max_bits > 0 && max_bits < bits_available)
- bits_available = max_bits;
+ size_t bitrate = target_bitrate_sum_kbps;
+ bitrate =
+ std::max(bitrate, static_cast<size_t>(simulcast_streams[0].minBitrate));
+ if (max_target_bitrate_kbps > 0)
+ bitrate = std::min(bitrate, static_cast<size_t>(max_target_bitrate_kbps));
- {
- rtc::CritScope cs(&crit_sect_);
- last_encode_time_ms_ = time_now_ms;
- }
+ size_t bits_available = target_bitrate_sum_kbps * 1000 / framerate;
RTC_DCHECK_GT(num_simulcast_streams, 0);
for (unsigned char i = 0; i < num_simulcast_streams; ++i) {
@@ -116,18 +111,38 @@ int32_t FakeEncoder::Encode(const VideoFrame& input_image,
specifics.codecType = kVideoCodecGeneric;
specifics.codecSpecific.generic.simulcast_idx = i;
size_t min_stream_bits = static_cast<size_t>(
- simulcast_streams[i].minBitrate * time_since_last_encode_ms);
+ (simulcast_streams[i].minBitrate * 1000) / framerate);
size_t max_stream_bits = static_cast<size_t>(
- simulcast_streams[i].maxBitrate * time_since_last_encode_ms);
+ (simulcast_streams[i].maxBitrate * 1000) / framerate);
size_t stream_bits = (bits_available > max_stream_bits) ? max_stream_bits :
bits_available;
size_t stream_bytes = (stream_bits + 7) / 8;
- if (first_encode) {
+ if (keyframe) {
// The first frame is a key frame and should be larger.
- // TODO(holmer): The FakeEncoder should store the bits_available between
- // encodes so that it can compensate for oversized frames.
- stream_bytes *= 10;
+ // Store the overshoot bytes and distribute them over the coming frames,
+ // so that we on average meet the bitrate target.
+ const int kKeyframeSizeFactor = 10;
+ // Pay 1/2 of a frame debt factor every frame.
+ const int kNumDebtPayments = (kKeyframeSizeFactor - 1) * 2;
+ debt_bytes_.resize(kNumDebtPayments);
+ size_t total_debt_bytes = (kKeyframeSizeFactor - 1) * stream_bytes;
+ for (int i = 0; i < kNumDebtPayments; ++i)
+ debt_bytes_[i] += total_debt_bytes / kNumDebtPayments;
stefan-webrtc 2017/05/23 17:03:20 An option is to just keep track of a total debt an
sprang_webrtc 2017/05/24 09:07:07 Maybe, but then paying of the whole debt will take
holmer 2017/06/02 11:38:05 You could have a total_debt and a payed_debt and t
+ stream_bytes *= kKeyframeSizeFactor;
+ } else {
+ if (!debt_bytes_.empty()) {
+ size_t debt_bytes = std::min(stream_bytes, debt_bytes_[0]);
+ debt_bytes_.pop_front();
+ if (debt_bytes >= stream_bytes) {
stefan-webrtc 2017/05/23 17:03:20 This can only be true if == right? What is it that
sprang_webrtc 2017/05/24 09:07:07 Oops, the std::min above shouldn't be there. I'll
+ if (debt_bytes_.empty())
+ debt_bytes_.resize(1);
+ debt_bytes_[0] += debt_bytes - stream_bytes + 1;
+ debt_bytes = stream_bytes - 1;
+ }
+ stream_bytes -= debt_bytes;
+ }
}
+
if (stream_bytes > num_encoded_bytes)
stream_bytes = num_encoded_bytes;
@@ -175,6 +190,7 @@ int32_t FakeEncoder::SetRateAllocation(const BitrateAllocation& rate_allocation,
uint32_t framerate) {
rtc::CritScope cs(&crit_sect_);
target_bitrate_ = rate_allocation;
+ configured_input_framerate_ = framerate;
return 0;
}
@@ -183,6 +199,11 @@ const char* FakeEncoder::ImplementationName() const {
return kImplementationName;
}
+int FakeEncoder::GetConfiguredInputFramerate() {
+ rtc::CritScope cs(&crit_sect_);
+ return configured_input_framerate_;
+}
+
FakeH264Encoder::FakeH264Encoder(Clock* clock)
: FakeEncoder(clock), callback_(nullptr), idr_counter_(0) {
FakeEncoder::RegisterEncodeCompleteCallback(this);

Powered by Google App Engine
This is Rietveld 408576698