blob: f74e5eba8573617f60387ee325978ba3481dca70 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/video_coding/media_optimization.h"
stefan@webrtc.orge0d6fa42012-03-20 22:10:56 +000012
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <string.h>
14#include <algorithm>
Stefan Holmer144475b2017-03-10 15:08:26 +010015#include <limits>
16
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "modules/video_coding/utility/frame_dropper.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "system_wrappers/include/clock.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000019
20namespace webrtc {
stefan@webrtc.orga64300a2013-03-04 15:24:40 +000021namespace media_optimization {
Åsa Perssonb52a4d92017-11-08 11:33:37 +010022namespace {
23const int64_t kFrameHistoryWinMs = 2000;
24} // namespace
niklase@google.com470e71d2011-07-07 08:21:25 +000025
stefan@webrtc.org34c5da62014-04-11 14:08:35 +000026MediaOptimization::MediaOptimization(Clock* clock)
kthelgasond701dfd2017-03-27 07:24:57 -070027 : clock_(clock),
henrik.lundin@webrtc.orgbec11ef2013-09-23 19:54:25 +000028 max_bit_rate_(0),
Åsa Perssonb52a4d92017-11-08 11:33:37 +010029 max_frame_rate_(0),
Rasmus Brandt3613fef2018-09-03 16:19:29 +020030 frame_dropper_(),
Åsa Persson0122e842017-10-16 12:19:23 +020031 incoming_frame_rate_(0) {
henrik.lundin@webrtc.orgbec11ef2013-09-23 19:54:25 +000032 memset(incoming_frame_times_, -1, sizeof(incoming_frame_times_));
Rasmus Brandt3613fef2018-09-03 16:19:29 +020033 frame_dropper_.SetRates(0, 0);
niklase@google.com470e71d2011-07-07 08:21:25 +000034}
35
Rasmus Brandt3613fef2018-09-03 16:19:29 +020036MediaOptimization::~MediaOptimization() = default;
niklase@google.com470e71d2011-07-07 08:21:25 +000037
Per69b332d2016-06-02 15:45:42 +020038void MediaOptimization::SetEncodingData(int32_t max_bit_rate,
andresp@webrtc.orge682aa52013-12-19 10:59:48 +000039 uint32_t target_bitrate,
Åsa Perssonb52a4d92017-11-08 11:33:37 +010040 uint32_t max_frame_rate) {
kthelgasond701dfd2017-03-27 07:24:57 -070041 rtc::CritScope lock(&crit_sect_);
Åsa Perssoneb450072017-11-13 10:24:22 +010042 // Everything codec specific should be reset here since the codec has changed.
andresp@webrtc.orge682aa52013-12-19 10:59:48 +000043 max_bit_rate_ = max_bit_rate;
Åsa Perssonb52a4d92017-11-08 11:33:37 +010044 max_frame_rate_ = static_cast<float>(max_frame_rate);
andresp@webrtc.orge682aa52013-12-19 10:59:48 +000045 float target_bitrate_kbps = static_cast<float>(target_bitrate) / 1000.0f;
Rasmus Brandt3613fef2018-09-03 16:19:29 +020046 frame_dropper_.Reset();
47 frame_dropper_.SetRates(target_bitrate_kbps, max_frame_rate_);
andresp@webrtc.orge682aa52013-12-19 10:59:48 +000048}
49
asapersson9abd2752016-12-08 02:19:40 -080050uint32_t MediaOptimization::SetTargetRates(uint32_t target_bitrate) {
kthelgasond701dfd2017-03-27 07:24:57 -070051 rtc::CritScope lock(&crit_sect_);
niklase@google.com470e71d2011-07-07 08:21:25 +000052
pbos73674632015-10-29 15:45:00 -070053 // Cap target video bitrate to codec maximum.
Åsa Perssonb52a4d92017-11-08 11:33:37 +010054 int video_target_bitrate = target_bitrate;
55 if (max_bit_rate_ > 0 && video_target_bitrate > max_bit_rate_) {
56 video_target_bitrate = max_bit_rate_;
pbos73674632015-10-29 15:45:00 -070057 }
henrik.lundin@webrtc.orgbec11ef2013-09-23 19:54:25 +000058 float target_video_bitrate_kbps =
Åsa Perssonb52a4d92017-11-08 11:33:37 +010059 static_cast<float>(video_target_bitrate) / 1000.0f;
Åsa Perssoneb450072017-11-13 10:24:22 +010060
sprang4847ae62017-06-27 07:06:52 -070061 float framerate = incoming_frame_rate_;
62 if (framerate == 0.0) {
63 // No framerate estimate available, use configured max framerate instead.
Åsa Perssonb52a4d92017-11-08 11:33:37 +010064 framerate = max_frame_rate_;
sprang4847ae62017-06-27 07:06:52 -070065 }
66
Rasmus Brandt3613fef2018-09-03 16:19:29 +020067 frame_dropper_.SetRates(target_video_bitrate_kbps, framerate);
henrik.lundin@webrtc.orgbec11ef2013-09-23 19:54:25 +000068
Åsa Perssonb52a4d92017-11-08 11:33:37 +010069 return video_target_bitrate;
niklase@google.com470e71d2011-07-07 08:21:25 +000070}
71
henrik.lundin@webrtc.orgbec11ef2013-09-23 19:54:25 +000072uint32_t MediaOptimization::InputFrameRate() {
kthelgasond701dfd2017-03-27 07:24:57 -070073 rtc::CritScope lock(&crit_sect_);
wuchengli@chromium.orgae7cfd72014-06-30 08:01:47 +000074 return InputFrameRateInternal();
75}
76
77uint32_t MediaOptimization::InputFrameRateInternal() {
henrik.lundin@webrtc.orgbec11ef2013-09-23 19:54:25 +000078 ProcessIncomingFrameRate(clock_->TimeInMilliseconds());
Stefan Holmer144475b2017-03-10 15:08:26 +010079 uint32_t framerate = static_cast<uint32_t>(std::min<float>(
80 std::numeric_limits<uint32_t>::max(), incoming_frame_rate_ + 0.5f));
81 return framerate;
henrik.lundin@webrtc.orgbec11ef2013-09-23 19:54:25 +000082}
83
Åsa Perssonb52a4d92017-11-08 11:33:37 +010084void MediaOptimization::UpdateWithEncodedData(
Ying Wang0dd1b0a2018-02-20 12:50:27 +010085 const size_t encoded_image_length,
86 const FrameType encoded_image_frametype) {
87 size_t encoded_length = encoded_image_length;
kthelgasond701dfd2017-03-27 07:24:57 -070088 rtc::CritScope lock(&crit_sect_);
henrik.lundin@webrtc.orgbec11ef2013-09-23 19:54:25 +000089 if (encoded_length > 0) {
Ying Wang0dd1b0a2018-02-20 12:50:27 +010090 const bool delta_frame = encoded_image_frametype != kVideoFrameKey;
Rasmus Brandt3613fef2018-09-03 16:19:29 +020091 frame_dropper_.Fill(encoded_length, delta_frame);
henrik.lundin@webrtc.orgbec11ef2013-09-23 19:54:25 +000092 }
henrik.lundin@webrtc.orgbec11ef2013-09-23 19:54:25 +000093}
94
henrik.lundin@webrtc.orgbec11ef2013-09-23 19:54:25 +000095void MediaOptimization::EnableFrameDropper(bool enable) {
kthelgasond701dfd2017-03-27 07:24:57 -070096 rtc::CritScope lock(&crit_sect_);
Rasmus Brandt3613fef2018-09-03 16:19:29 +020097 frame_dropper_.Enable(enable);
henrik.lundin@webrtc.orgbec11ef2013-09-23 19:54:25 +000098}
99
100bool MediaOptimization::DropFrame() {
kthelgasond701dfd2017-03-27 07:24:57 -0700101 rtc::CritScope lock(&crit_sect_);
andresp@webrtc.orge682aa52013-12-19 10:59:48 +0000102 UpdateIncomingFrameRate();
henrik.lundin@webrtc.orgbec11ef2013-09-23 19:54:25 +0000103 // Leak appropriate number of bytes.
Rasmus Brandt3613fef2018-09-03 16:19:29 +0200104 frame_dropper_.Leak(static_cast<uint32_t>(InputFrameRateInternal() + 0.5f));
105 return frame_dropper_.DropFrame();
henrik.lundin@webrtc.orgbec11ef2013-09-23 19:54:25 +0000106}
107
henrik.lundin@webrtc.orgbec11ef2013-09-23 19:54:25 +0000108void MediaOptimization::UpdateIncomingFrameRate() {
109 int64_t now = clock_->TimeInMilliseconds();
110 if (incoming_frame_times_[0] == 0) {
111 // No shifting if this is the first time.
112 } else {
113 // Shift all times one step.
114 for (int32_t i = (kFrameCountHistorySize - 2); i >= 0; i--) {
115 incoming_frame_times_[i + 1] = incoming_frame_times_[i];
116 }
117 }
118 incoming_frame_times_[0] = now;
119 ProcessIncomingFrameRate(now);
120}
121
henrik.lundin@webrtc.orgbec11ef2013-09-23 19:54:25 +0000122// Allowing VCM to keep track of incoming frame rate.
123void MediaOptimization::ProcessIncomingFrameRate(int64_t now) {
124 int32_t num = 0;
125 int32_t nr_of_frames = 0;
126 for (num = 1; num < (kFrameCountHistorySize - 1); ++num) {
127 if (incoming_frame_times_[num] <= 0 ||
asapersson60dfbdb2017-08-07 00:03:03 -0700128 // Don't use data older than 2 s.
henrik.lundin@webrtc.orgbec11ef2013-09-23 19:54:25 +0000129 now - incoming_frame_times_[num] > kFrameHistoryWinMs) {
130 break;
131 } else {
132 nr_of_frames++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000133 }
henrik.lundin@webrtc.orgbec11ef2013-09-23 19:54:25 +0000134 }
135 if (num > 1) {
Erik Språng66a641a2015-06-11 14:20:07 +0200136 const int64_t diff =
137 incoming_frame_times_[0] - incoming_frame_times_[num - 1];
138 incoming_frame_rate_ = 0.0; // No frame rate estimate available.
henrik.lundin@webrtc.orgbec11ef2013-09-23 19:54:25 +0000139 if (diff > 0) {
140 incoming_frame_rate_ = nr_of_frames * 1000.0f / static_cast<float>(diff);
niklase@google.com470e71d2011-07-07 08:21:25 +0000141 }
henrik.lundin@webrtc.orgbec11ef2013-09-23 19:54:25 +0000142 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000143}
stefan@webrtc.orga64300a2013-03-04 15:24:40 +0000144} // namespace media_optimization
145} // namespace webrtc