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

Side by Side Diff: webrtc/media/base/videoadapter.cc

Issue 2672793002: Change rtc::VideoSinkWants to have target and a max pixel count (Closed)
Patch Set: Addressed comment Created 3 years, 10 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 unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2010 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2010 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/media/base/videoadapter.h" 11 #include "webrtc/media/base/videoadapter.h"
12 12
13 #include <algorithm> 13 #include <algorithm>
14 #include <cmath> 14 #include <cmath>
15 #include <cstdlib> 15 #include <cstdlib>
16 #include <limits> 16 #include <limits>
17 17
18 #include "webrtc/base/arraysize.h" 18 #include "webrtc/base/arraysize.h"
19 #include "webrtc/base/checks.h" 19 #include "webrtc/base/checks.h"
20 #include "webrtc/base/logging.h" 20 #include "webrtc/base/logging.h"
21 #include "webrtc/base/optional.h" 21 #include "webrtc/base/optional.h"
22 #include "webrtc/media/base/mediaconstants.h" 22 #include "webrtc/media/base/mediaconstants.h"
23 #include "webrtc/media/base/videocommon.h" 23 #include "webrtc/media/base/videocommon.h"
24 24
25 namespace { 25 namespace {
26 struct Fraction { 26 struct Fraction {
27 int numerator; 27 int numerator;
28 int denominator; 28 int denominator;
29
30 // Determines number of output pixels if both width and height of an input of
31 // |input_pixels| pixels is scaled with the fraction numerator / denominator.
32 int scale_pixel_count(int input_pixels) {
33 return (numerator * numerator * input_pixels) / (denominator * denominator);
34 }
29 }; 35 };
30 36
31 // Round |value_to_round| to a multiple of |multiple|. Prefer rounding upwards, 37 // Round |value_to_round| to a multiple of |multiple|. Prefer rounding upwards,
32 // but never more than |max_value|. 38 // but never more than |max_value|.
33 int roundUp(int value_to_round, int multiple, int max_value) { 39 int roundUp(int value_to_round, int multiple, int max_value) {
34 const int rounded_value = 40 const int rounded_value =
35 (value_to_round + multiple - 1) / multiple * multiple; 41 (value_to_round + multiple - 1) / multiple * multiple;
36 return rounded_value <= max_value ? rounded_value 42 return rounded_value <= max_value ? rounded_value
37 : (max_value / multiple * multiple); 43 : (max_value / multiple * multiple);
38 } 44 }
39 45
40 // Generates a scale factor that makes |input_num_pixels| smaller or 46 // Generates a scale factor that makes |input_pixels| close to |target_pixels|,
41 // larger than |target_num_pixels|, depending on the value of |step_up|. 47 // but no higher than |max_pixels|.
42 Fraction FindScale(int input_num_pixels, int target_num_pixels, bool step_up) { 48 Fraction FindScale(int input_pixels, int target_pixels, int max_pixels) {
43 // This function only makes sense for a positive target. 49 // This function only makes sense for a positive target.
44 RTC_DCHECK_GT(target_num_pixels, 0); 50 RTC_DCHECK_GT(target_pixels, 0);
51 RTC_DCHECK_GT(max_pixels, 0);
52 RTC_DCHECK_GE(max_pixels, target_pixels);
53
54 // Don't scale up original.
55 if (target_pixels >= input_pixels)
56 return Fraction{1, 1};
57
58 Fraction current_scale = Fraction{1, 1};
45 Fraction best_scale = Fraction{1, 1}; 59 Fraction best_scale = Fraction{1, 1};
46 Fraction last_scale = Fraction{1, 1}; 60 // The minimum (absolute) difference between the number of output pixels and
47 const float target_scale = 61 // the target pixel count.
48 sqrt(target_num_pixels / static_cast<float>(input_num_pixels)); 62 int min_pixel_diff = input_pixels;
49 while (best_scale.numerator > (target_scale * best_scale.denominator)) { 63 if (input_pixels < max_pixels) {
50 last_scale = best_scale; 64 // Start condition for 1/1 case, if it is less than max.
51 if (best_scale.numerator % 3 == 0 && best_scale.denominator % 2 == 0) { 65 min_pixel_diff = std::abs(input_pixels - target_pixels);
52 // Multiply by 2/3 66 }
53 best_scale.numerator /= 3; 67 while (current_scale.scale_pixel_count(input_pixels) > target_pixels) {
54 best_scale.denominator /= 2; 68 if (current_scale.numerator % 3 == 0 &&
69 current_scale.denominator % 2 == 0) {
70 // Multiply by 2/3.
nisse-webrtc 2017/02/06 08:43:19 I think this logic deserves some explanation. But
sprang_webrtc 2017/02/06 10:34:02 I'll add a brief comment. But yes, it was not imme
71 current_scale.numerator /= 3;
72 current_scale.denominator /= 2;
55 } else { 73 } else {
56 // Multiply by 3/4 74 // Multiply by 3/4.
57 best_scale.numerator *= 3; 75 current_scale.numerator *= 3;
58 best_scale.denominator *= 4; 76 current_scale.denominator *= 4;
77 }
78
79 int output_pixels = current_scale.scale_pixel_count(input_pixels);
80 if (output_pixels <= max_pixels) {
81 int diff = std::abs(target_pixels - output_pixels);
82 if (diff < min_pixel_diff) {
83 min_pixel_diff = diff;
84 best_scale = current_scale;
85 }
59 } 86 }
60 } 87 }
61 if (step_up) 88
62 return last_scale;
63 return best_scale; 89 return best_scale;
64 } 90 }
65 } // namespace 91 } // namespace
66 92
67 namespace cricket { 93 namespace cricket {
68 94
69 VideoAdapter::VideoAdapter(int required_resolution_alignment) 95 VideoAdapter::VideoAdapter(int required_resolution_alignment)
70 : frames_in_(0), 96 : frames_in_(0),
71 frames_out_(0), 97 frames_out_(0),
72 frames_scaled_(0), 98 frames_scaled_(0),
73 adaption_changes_(0), 99 adaption_changes_(0),
74 previous_width_(0), 100 previous_width_(0),
75 previous_height_(0), 101 previous_height_(0),
76 required_resolution_alignment_(required_resolution_alignment), 102 required_resolution_alignment_(required_resolution_alignment),
77 resolution_request_max_pixel_count_(std::numeric_limits<int>::max()), 103 resolution_request_target_pixel_count_(std::numeric_limits<int>::max()),
78 step_up_(false) {} 104 resolution_request_max_pixel_count_(std::numeric_limits<int>::max()) {}
79 105
80 VideoAdapter::VideoAdapter() : VideoAdapter(1) {} 106 VideoAdapter::VideoAdapter() : VideoAdapter(1) {}
81 107
82 VideoAdapter::~VideoAdapter() {} 108 VideoAdapter::~VideoAdapter() {}
83 109
84 bool VideoAdapter::KeepFrame(int64_t in_timestamp_ns) { 110 bool VideoAdapter::KeepFrame(int64_t in_timestamp_ns) {
85 rtc::CritScope cs(&critical_section_); 111 rtc::CritScope cs(&critical_section_);
86 if (!requested_format_ || requested_format_->interval == 0) 112 if (!requested_format_ || requested_format_->interval == 0)
87 return true; 113 return true;
88 114
(...skipping 28 matching lines...) Expand all
117 int* cropped_height, 143 int* cropped_height,
118 int* out_width, 144 int* out_width,
119 int* out_height) { 145 int* out_height) {
120 rtc::CritScope cs(&critical_section_); 146 rtc::CritScope cs(&critical_section_);
121 ++frames_in_; 147 ++frames_in_;
122 148
123 // The max output pixel count is the minimum of the requests from 149 // The max output pixel count is the minimum of the requests from
124 // OnOutputFormatRequest and OnResolutionRequest. 150 // OnOutputFormatRequest and OnResolutionRequest.
125 int max_pixel_count = resolution_request_max_pixel_count_; 151 int max_pixel_count = resolution_request_max_pixel_count_;
126 if (requested_format_) { 152 if (requested_format_) {
127 // TODO(kthelgason): remove the - |step_up_| hack when we change how 153 // TODO(kthelgason): remove the - |step_up_| hack when we change how
nisse-webrtc 2017/02/06 08:43:19 Drop this TODO?
sprang_webrtc 2017/02/06 10:34:02 Done.
128 // resolution is requested from VideoSourceProxy. 154 // resolution is requested from VideoSourceProxy.
129 // This is required because we must not scale above the requested 155 // This is required because we must not scale above the requested
130 // format so we subtract one when scaling up. 156 // format so we subtract one when scaling up.
131 max_pixel_count = std::min( 157 max_pixel_count = std::min(
132 max_pixel_count, requested_format_->width * requested_format_->height - 158 max_pixel_count, requested_format_->width * requested_format_->height);
133 static_cast<int>(step_up_));
134 } 159 }
160 int target_pixel_count =
161 std::min(resolution_request_target_pixel_count_, max_pixel_count);
135 162
136 // Drop the input frame if necessary. 163 // Drop the input frame if necessary.
137 if (max_pixel_count <= 0 || !KeepFrame(in_timestamp_ns)) { 164 if (max_pixel_count <= 0 || !KeepFrame(in_timestamp_ns)) {
138 // Show VAdapt log every 90 frames dropped. (3 seconds) 165 // Show VAdapt log every 90 frames dropped. (3 seconds)
139 if ((frames_in_ - frames_out_) % 90 == 0) { 166 if ((frames_in_ - frames_out_) % 90 == 0) {
140 // TODO(fbarchard): Reduce to LS_VERBOSE when adapter info is not needed 167 // TODO(fbarchard): Reduce to LS_VERBOSE when adapter info is not needed
141 // in default calls. 168 // in default calls.
142 LOG(LS_INFO) << "VAdapt Drop Frame: scaled " << frames_scaled_ 169 LOG(LS_INFO) << "VAdapt Drop Frame: scaled " << frames_scaled_
143 << " / out " << frames_out_ 170 << " / out " << frames_out_
144 << " / in " << frames_in_ 171 << " / in " << frames_in_
(...skipping 21 matching lines...) Expand all
166 std::swap(requested_format_->width, requested_format_->height); 193 std::swap(requested_format_->width, requested_format_->height);
167 } 194 }
168 const float requested_aspect = 195 const float requested_aspect =
169 requested_format_->width / 196 requested_format_->width /
170 static_cast<float>(requested_format_->height); 197 static_cast<float>(requested_format_->height);
171 *cropped_width = 198 *cropped_width =
172 std::min(in_width, static_cast<int>(in_height * requested_aspect)); 199 std::min(in_width, static_cast<int>(in_height * requested_aspect));
173 *cropped_height = 200 *cropped_height =
174 std::min(in_height, static_cast<int>(in_width / requested_aspect)); 201 std::min(in_height, static_cast<int>(in_width / requested_aspect));
175 } 202 }
176 const Fraction scale = 203 const Fraction scale = FindScale((*cropped_width) * (*cropped_height),
177 FindScale(*cropped_width * *cropped_height, max_pixel_count, step_up_); 204 target_pixel_count, max_pixel_count);
178 // Adjust cropping slightly to get even integer output size and a perfect 205 // Adjust cropping slightly to get even integer output size and a perfect
179 // scale factor. Make sure the resulting dimensions are aligned correctly 206 // scale factor. Make sure the resulting dimensions are aligned correctly
180 // to be nice to hardware encoders. 207 // to be nice to hardware encoders.
181 *cropped_width = 208 *cropped_width =
182 roundUp(*cropped_width, 209 roundUp(*cropped_width,
183 scale.denominator * required_resolution_alignment_, in_width); 210 scale.denominator * required_resolution_alignment_, in_width);
184 *cropped_height = 211 *cropped_height =
185 roundUp(*cropped_height, 212 roundUp(*cropped_height,
186 scale.denominator * required_resolution_alignment_, in_height); 213 scale.denominator * required_resolution_alignment_, in_height);
187 RTC_DCHECK_EQ(0, *cropped_width % scale.denominator); 214 RTC_DCHECK_EQ(0, *cropped_width % scale.denominator);
(...skipping 26 matching lines...) Expand all
214 241
215 return true; 242 return true;
216 } 243 }
217 244
218 void VideoAdapter::OnOutputFormatRequest(const VideoFormat& format) { 245 void VideoAdapter::OnOutputFormatRequest(const VideoFormat& format) {
219 rtc::CritScope cs(&critical_section_); 246 rtc::CritScope cs(&critical_section_);
220 requested_format_ = rtc::Optional<VideoFormat>(format); 247 requested_format_ = rtc::Optional<VideoFormat>(format);
221 next_frame_timestamp_ns_ = rtc::Optional<int64_t>(); 248 next_frame_timestamp_ns_ = rtc::Optional<int64_t>();
222 } 249 }
223 250
224 void VideoAdapter::OnResolutionRequest( 251 void VideoAdapter::OnResolutionRequest(rtc::Optional<int> target_pixel_count,
225 rtc::Optional<int> max_pixel_count, 252 rtc::Optional<int> max_pixel_count) {
226 rtc::Optional<int> max_pixel_count_step_up) {
227 rtc::CritScope cs(&critical_section_); 253 rtc::CritScope cs(&critical_section_);
228 resolution_request_max_pixel_count_ = max_pixel_count.value_or( 254 resolution_request_target_pixel_count_ =
229 max_pixel_count_step_up.value_or(std::numeric_limits<int>::max())); 255 target_pixel_count.value_or(std::numeric_limits<int>::max());
nisse-webrtc 2017/02/06 08:43:18 You could swap order, and make max_pixel_count the
sprang_webrtc 2017/02/06 10:34:02 Done.
230 step_up_ = static_cast<bool>(max_pixel_count_step_up); 256 resolution_request_max_pixel_count_ =
257 max_pixel_count.value_or(resolution_request_target_pixel_count_);
231 } 258 }
232 259
233 } // namespace cricket 260 } // namespace cricket
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698