capture_resolution_chooser_unittest.cc 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. // Copyright 2015 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "media/capture/content/capture_resolution_chooser.h"
  5. #include <stddef.h>
  6. #include "base/location.h"
  7. #include "testing/gtest/include/gtest/gtest.h"
  8. #include "ui/gfx/geometry/size.h"
  9. using base::Location;
  10. namespace media {
  11. namespace {
  12. // 16:9 maximum and minimum frame sizes.
  13. constexpr int kMaxFrameWidth = 3840;
  14. constexpr int kMaxFrameHeight = 2160;
  15. constexpr int kMinFrameWidth = 320;
  16. constexpr int kMinFrameHeight = 180;
  17. // Smallest non-empty size for I420 video.
  18. constexpr int kSmallestNonEmptyWidth = 2;
  19. constexpr int kSmallestNonEmptyHeight = 2;
  20. // Checks whether |size| is strictly between (inclusive) |min_size| and
  21. // |max_size| and has the same aspect ratio as |max_size|.
  22. void ExpectIsWithinBoundsAndSameAspectRatio(const Location& location,
  23. const gfx::Size& min_size,
  24. const gfx::Size& max_size,
  25. const gfx::Size& size) {
  26. SCOPED_TRACE(::testing::Message() << "From here: " << location.ToString());
  27. EXPECT_LE(min_size.width(), size.width());
  28. EXPECT_LE(min_size.height(), size.height());
  29. EXPECT_GE(max_size.width(), size.width());
  30. EXPECT_GE(max_size.height(), size.height());
  31. EXPECT_NEAR(static_cast<double>(max_size.width()) / max_size.height(),
  32. static_cast<double>(size.width()) / size.height(), 0.01);
  33. }
  34. // Test that the correct snapped frame sizes are computed for a |chooser|
  35. // configured with either of the variable-resolution change policies, and are
  36. // correctly found when searched.
  37. void TestSnappedFrameSizes(CaptureResolutionChooser* chooser,
  38. const gfx::Size& smallest_size) {
  39. const int kSizes[17][2] = {
  40. {kMaxFrameWidth, kMaxFrameHeight},
  41. {3520, 1980},
  42. {3200, 1800},
  43. {2880, 1620},
  44. {2560, 1440},
  45. {2240, 1260},
  46. {1920, 1080},
  47. {1760, 990},
  48. {1600, 900},
  49. {1440, 810},
  50. {1280, 720},
  51. {1120, 630},
  52. {960, 540},
  53. {800, 450},
  54. {640, 360},
  55. {480, 270},
  56. {320, 180},
  57. };
  58. const gfx::Size largest_size(kMaxFrameWidth, kMaxFrameHeight);
  59. chooser->SetSourceSize(largest_size);
  60. // There should be no size larger than the largest size.
  61. for (int i = 1; i < 4; ++i) {
  62. EXPECT_EQ(largest_size,
  63. chooser->FindLargerFrameSize(largest_size.GetArea(), i));
  64. EXPECT_EQ(largest_size,
  65. chooser->FindLargerFrameSize(largest_size.GetArea() * 2, +i));
  66. }
  67. // There should be no size smaller than the smallest size.
  68. for (int i = 1; i < 4; ++i) {
  69. EXPECT_EQ(smallest_size,
  70. chooser->FindSmallerFrameSize(smallest_size.GetArea(), i));
  71. EXPECT_EQ(smallest_size,
  72. chooser->FindSmallerFrameSize(smallest_size.GetArea() / 2, i));
  73. }
  74. // Test the "find Nth lower size" logic.
  75. for (size_t skips = 1; skips < 4; ++skips) {
  76. for (size_t i = skips; i < std::size(kSizes); ++i) {
  77. EXPECT_EQ(
  78. gfx::Size(kSizes[i][0], kSizes[i][1]),
  79. chooser->FindSmallerFrameSize(
  80. gfx::Size(kSizes[i - skips][0], kSizes[i - skips][1]).GetArea(),
  81. skips));
  82. }
  83. }
  84. // Test the "find Nth higher size" logic.
  85. for (size_t skips = 1; skips < 4; ++skips) {
  86. for (size_t i = skips; i < std::size(kSizes); ++i) {
  87. EXPECT_EQ(gfx::Size(kSizes[i - skips][0], kSizes[i - skips][1]),
  88. chooser->FindLargerFrameSize(
  89. gfx::Size(kSizes[i][0], kSizes[i][1]).GetArea(), skips));
  90. }
  91. }
  92. // Test the "find nearest size" logic.
  93. for (size_t i = 1; i < std::size(kSizes) - 1; ++i) {
  94. const gfx::Size size(kSizes[i][0], kSizes[i][1]);
  95. const int a_somewhat_smaller_area =
  96. gfx::Size((kSizes[i - 1][0] + 3 * kSizes[i][0]) / 4,
  97. (kSizes[i - 1][1] + 3 * kSizes[i][1]) / 4).GetArea();
  98. EXPECT_EQ(size, chooser->FindNearestFrameSize(a_somewhat_smaller_area));
  99. const int a_smidge_smaller_area = size.GetArea() - 1;
  100. EXPECT_EQ(size, chooser->FindNearestFrameSize(a_smidge_smaller_area));
  101. const int a_smidge_larger_area = size.GetArea() + 1;
  102. EXPECT_EQ(size, chooser->FindNearestFrameSize(a_smidge_larger_area));
  103. const int a_somewhat_larger_area =
  104. gfx::Size((kSizes[i + 1][0] + 3 * kSizes[i][0]) / 4,
  105. (kSizes[i + 1][1] + 3 * kSizes[i][1]) / 4).GetArea();
  106. EXPECT_EQ(size, chooser->FindNearestFrameSize(a_somewhat_larger_area));
  107. }
  108. }
  109. // Test that setting the target frame area results in the correct capture sizes
  110. // being computed for a |chooser| configured with either of the
  111. // variable-resolution change policies.
  112. void TestTargetedFrameAreas(CaptureResolutionChooser* chooser,
  113. const gfx::Size& smallest_size) {
  114. chooser->SetSourceSize(gfx::Size(1280, 720));
  115. // The computed capture size cannot be larger than the source size, even
  116. // though the |chooser| is configured with a larger max frame size.
  117. chooser->SetTargetFrameArea(kMaxFrameWidth * kMaxFrameHeight);
  118. EXPECT_EQ(gfx::Size(1280, 720), chooser->capture_size());
  119. chooser->SetTargetFrameArea(1280 * 720 + 1);
  120. EXPECT_EQ(gfx::Size(1280, 720), chooser->capture_size());
  121. chooser->SetTargetFrameArea(1280 * 720 - 1);
  122. EXPECT_EQ(gfx::Size(1280, 720), chooser->capture_size());
  123. chooser->SetTargetFrameArea(1120 * 630 + 1);
  124. EXPECT_EQ(gfx::Size(1120, 630), chooser->capture_size());
  125. chooser->SetTargetFrameArea(1120 * 630 - 1);
  126. EXPECT_EQ(gfx::Size(1120, 630), chooser->capture_size());
  127. chooser->SetTargetFrameArea(800 * 450 + 1);
  128. EXPECT_EQ(gfx::Size(800, 450), chooser->capture_size());
  129. chooser->SetTargetFrameArea(800 * 450 - 1);
  130. EXPECT_EQ(gfx::Size(800, 450), chooser->capture_size());
  131. chooser->SetTargetFrameArea(640 * 360 + 1);
  132. EXPECT_EQ(gfx::Size(640, 360), chooser->capture_size());
  133. chooser->SetTargetFrameArea(640 * 360 - 1);
  134. EXPECT_EQ(gfx::Size(640, 360), chooser->capture_size());
  135. chooser->SetTargetFrameArea(smallest_size.GetArea() + 1);
  136. EXPECT_EQ(smallest_size, chooser->capture_size());
  137. chooser->SetTargetFrameArea(smallest_size.GetArea() - 1);
  138. EXPECT_EQ(smallest_size, chooser->capture_size());
  139. chooser->SetTargetFrameArea(smallest_size.GetArea() / 2);
  140. EXPECT_EQ(smallest_size, chooser->capture_size());
  141. chooser->SetTargetFrameArea(0);
  142. EXPECT_EQ(smallest_size, chooser->capture_size());
  143. // If the source size has increased, the |chooser| is now permitted to compute
  144. // higher capture sizes.
  145. chooser->SetSourceSize(gfx::Size(kMaxFrameWidth, kMaxFrameHeight));
  146. chooser->SetTargetFrameArea(kMaxFrameWidth * kMaxFrameHeight);
  147. EXPECT_EQ(gfx::Size(kMaxFrameWidth, kMaxFrameHeight),
  148. chooser->capture_size());
  149. chooser->SetTargetFrameArea(3200 * 1800 + 1);
  150. EXPECT_EQ(gfx::Size(3200, 1800), chooser->capture_size());
  151. chooser->SetTargetFrameArea(3200 * 1800 - 1);
  152. EXPECT_EQ(gfx::Size(3200, 1800), chooser->capture_size());
  153. chooser->SetTargetFrameArea(640 * 360 + 1);
  154. EXPECT_EQ(gfx::Size(640, 360), chooser->capture_size());
  155. chooser->SetTargetFrameArea(640 * 360 - 1);
  156. EXPECT_EQ(gfx::Size(640, 360), chooser->capture_size());
  157. chooser->SetTargetFrameArea(0);
  158. EXPECT_EQ(smallest_size, chooser->capture_size());
  159. }
  160. // Determines that there is only one snapped frame size by implication: This
  161. // function searches for the nearest/larger/smaller frame sizes around
  162. // |the_one_size| and checks that there is only ever one result.
  163. void ExpectOnlyOneSnappedFrameSize(const CaptureResolutionChooser& chooser,
  164. const gfx::Size& the_one_size) {
  165. for (int i = 1; i < 4; ++i) {
  166. EXPECT_EQ(the_one_size,
  167. chooser.FindNearestFrameSize(the_one_size.GetArea() * i));
  168. EXPECT_EQ(the_one_size,
  169. chooser.FindSmallerFrameSize(the_one_size.GetArea(), i));
  170. EXPECT_EQ(the_one_size,
  171. chooser.FindLargerFrameSize(the_one_size.GetArea(), i));
  172. }
  173. }
  174. } // namespace
  175. // While clients should always strive to set their own constraints before
  176. // querying the CaptureResolutionChooser, do test that the reasonable "default"
  177. // behavior is exhibited beforehand.
  178. TEST(CaptureResolutionChooserTest, DefaultCaptureSizeIfNeverSetConstraints) {
  179. CaptureResolutionChooser chooser;
  180. EXPECT_EQ(CaptureResolutionChooser::kDefaultCaptureSize,
  181. chooser.capture_size());
  182. chooser.SetSourceSize(gfx::Size(kMinFrameWidth, kMinFrameHeight));
  183. EXPECT_EQ(CaptureResolutionChooser::kDefaultCaptureSize,
  184. chooser.capture_size());
  185. chooser.SetSourceSize(gfx::Size());
  186. EXPECT_EQ(CaptureResolutionChooser::kDefaultCaptureSize,
  187. chooser.capture_size());
  188. chooser.SetSourceSize(gfx::Size(kMaxFrameWidth, kMaxFrameHeight));
  189. EXPECT_EQ(CaptureResolutionChooser::kDefaultCaptureSize,
  190. chooser.capture_size());
  191. ExpectOnlyOneSnappedFrameSize(chooser,
  192. CaptureResolutionChooser::kDefaultCaptureSize);
  193. }
  194. // While clients should always strive to set the source size before querying the
  195. // CaptureResolutionChooser, do test that the reasonable "default" behavior is
  196. // exhibited beforehand.
  197. TEST(CaptureResolutionChooserTest, ReasonableCaptureSizeWhenMissingSourceSize) {
  198. CaptureResolutionChooser chooser;
  199. // CaptureResolutionChooser starts out with capture size set to
  200. // kDefaultCaptureSize.
  201. EXPECT_EQ(CaptureResolutionChooser::kDefaultCaptureSize,
  202. chooser.capture_size());
  203. // Setting constraints around kDefaultCaptureSize means the capture size
  204. // should remain as kDefaultCaptureSize.
  205. chooser.SetConstraints(gfx::Size(kMinFrameWidth, kMinFrameHeight),
  206. gfx::Size(kMaxFrameWidth, kMaxFrameHeight), false);
  207. EXPECT_EQ(CaptureResolutionChooser::kDefaultCaptureSize,
  208. chooser.capture_size());
  209. // Setting constraints to a fixed size less than kDefaultCaptureSize will
  210. // change the capture size, to meet the required constraints range.
  211. chooser.SetConstraints(gfx::Size(kMinFrameWidth, kMinFrameHeight),
  212. gfx::Size(kMinFrameWidth, kMinFrameHeight), false);
  213. EXPECT_EQ(gfx::Size(kMinFrameWidth, kMinFrameHeight), chooser.capture_size());
  214. // Setting the constraints back to the wide range should not change the
  215. // capture size, since the new range includes the former capture size.
  216. chooser.SetConstraints(gfx::Size(kMinFrameWidth, kMinFrameHeight),
  217. gfx::Size(kMaxFrameWidth, kMaxFrameHeight), false);
  218. EXPECT_EQ(gfx::Size(kMinFrameWidth, kMinFrameHeight), chooser.capture_size());
  219. // Finally, updating the source size to be exactly in the middle of the
  220. // constraints range should result in the capture size being updated to that
  221. // same size.
  222. const gfx::Size middle_size((kMinFrameWidth + kMaxFrameWidth) / 2,
  223. (kMinFrameHeight + kMaxFrameHeight) / 2);
  224. chooser.SetSourceSize(middle_size);
  225. EXPECT_EQ(middle_size, chooser.capture_size());
  226. }
  227. TEST(CaptureResolutionChooserTest,
  228. FixedResolutionPolicy_CaptureSizeAlwaysFixed) {
  229. const gfx::Size the_one_frame_size(kMaxFrameWidth, kMaxFrameHeight);
  230. CaptureResolutionChooser chooser;
  231. chooser.SetConstraints(the_one_frame_size, the_one_frame_size, false);
  232. EXPECT_EQ(the_one_frame_size, chooser.capture_size());
  233. chooser.SetSourceSize(the_one_frame_size);
  234. EXPECT_EQ(the_one_frame_size, chooser.capture_size());
  235. chooser.SetSourceSize(gfx::Size(kMaxFrameWidth + 424, kMaxFrameHeight - 101));
  236. EXPECT_EQ(the_one_frame_size, chooser.capture_size());
  237. chooser.SetSourceSize(gfx::Size(kMaxFrameWidth - 202, kMaxFrameHeight + 56));
  238. EXPECT_EQ(the_one_frame_size, chooser.capture_size());
  239. chooser.SetSourceSize(gfx::Size(kMinFrameWidth, kMinFrameHeight));
  240. EXPECT_EQ(the_one_frame_size, chooser.capture_size());
  241. ExpectOnlyOneSnappedFrameSize(chooser, the_one_frame_size);
  242. // Ensure that changing the target frame area does not change the computed
  243. // frame size.
  244. chooser.SetTargetFrameArea(0);
  245. EXPECT_EQ(the_one_frame_size, chooser.capture_size());
  246. chooser.SetTargetFrameArea(the_one_frame_size.GetArea() / 2);
  247. EXPECT_EQ(the_one_frame_size, chooser.capture_size());
  248. }
  249. TEST(CaptureResolutionChooserTest,
  250. FixedAspectRatioPolicy_CaptureSizeHasSameAspectRatio) {
  251. const gfx::Size min_size(kMinFrameWidth, kMinFrameHeight);
  252. const gfx::Size max_size(kMaxFrameWidth, kMaxFrameHeight);
  253. CaptureResolutionChooser chooser;
  254. chooser.SetConstraints(min_size, max_size, true);
  255. // Starting condition.
  256. ExpectIsWithinBoundsAndSameAspectRatio(FROM_HERE, min_size, max_size,
  257. chooser.capture_size());
  258. // Max size in --> max size out.
  259. chooser.SetSourceSize(gfx::Size(kMaxFrameWidth, kMaxFrameHeight));
  260. ExpectIsWithinBoundsAndSameAspectRatio(FROM_HERE, min_size, max_size,
  261. chooser.capture_size());
  262. // Various source sizes within bounds.
  263. chooser.SetSourceSize(gfx::Size(640, 480));
  264. ExpectIsWithinBoundsAndSameAspectRatio(FROM_HERE, min_size, max_size,
  265. chooser.capture_size());
  266. chooser.SetSourceSize(gfx::Size(480, 640));
  267. ExpectIsWithinBoundsAndSameAspectRatio(FROM_HERE, min_size, max_size,
  268. chooser.capture_size());
  269. chooser.SetSourceSize(gfx::Size(640, 640));
  270. ExpectIsWithinBoundsAndSameAspectRatio(FROM_HERE, min_size, max_size,
  271. chooser.capture_size());
  272. // Bad source size results in no update.
  273. const gfx::Size unchanged_size = chooser.capture_size();
  274. chooser.SetSourceSize(gfx::Size(0, 0));
  275. EXPECT_EQ(unchanged_size, chooser.capture_size());
  276. // Downscaling size (preserving aspect ratio) when source size exceeds the
  277. // upper bounds.
  278. chooser.SetSourceSize(gfx::Size(kMaxFrameWidth * 2, kMaxFrameHeight * 2));
  279. ExpectIsWithinBoundsAndSameAspectRatio(FROM_HERE, min_size, max_size,
  280. chooser.capture_size());
  281. chooser.SetSourceSize(gfx::Size(kMaxFrameWidth * 2, kMaxFrameHeight));
  282. ExpectIsWithinBoundsAndSameAspectRatio(FROM_HERE, min_size, max_size,
  283. chooser.capture_size());
  284. chooser.SetSourceSize(gfx::Size(kMaxFrameWidth, kMaxFrameHeight * 2));
  285. ExpectIsWithinBoundsAndSameAspectRatio(FROM_HERE, min_size, max_size,
  286. chooser.capture_size());
  287. // Upscaling size (preserving aspect ratio) when source size is under the
  288. // lower bounds.
  289. chooser.SetSourceSize(gfx::Size(kMinFrameWidth / 2, kMinFrameHeight / 2));
  290. ExpectIsWithinBoundsAndSameAspectRatio(FROM_HERE, min_size, max_size,
  291. chooser.capture_size());
  292. chooser.SetSourceSize(gfx::Size(kMinFrameWidth / 2, kMaxFrameHeight));
  293. ExpectIsWithinBoundsAndSameAspectRatio(FROM_HERE, min_size, max_size,
  294. chooser.capture_size());
  295. chooser.SetSourceSize(gfx::Size(kMinFrameWidth, kMinFrameHeight / 2));
  296. ExpectIsWithinBoundsAndSameAspectRatio(FROM_HERE, min_size, max_size,
  297. chooser.capture_size());
  298. // For a chooser configured with the "fixed aspect ratio" policy, the smallest
  299. // possible computed size is the one with 180 lines of resolution and the same
  300. // aspect ratio.
  301. const gfx::Size smallest_size(180 * kMaxFrameWidth / kMaxFrameHeight, 180);
  302. TestSnappedFrameSizes(&chooser, smallest_size);
  303. TestTargetedFrameAreas(&chooser, smallest_size);
  304. }
  305. TEST(CaptureResolutionChooserTest,
  306. AnyWithinLimitPolicy_CaptureSizeIsAnythingWithinLimits) {
  307. const gfx::Size min_size(kSmallestNonEmptyWidth, kSmallestNonEmptyHeight);
  308. const gfx::Size max_size(kMaxFrameWidth, kMaxFrameHeight);
  309. CaptureResolutionChooser chooser;
  310. chooser.SetConstraints(min_size, max_size, false);
  311. // Starting condition.
  312. EXPECT_EQ(CaptureResolutionChooser::kDefaultCaptureSize,
  313. chooser.capture_size());
  314. // Max size in --> max size out.
  315. chooser.SetSourceSize(max_size);
  316. EXPECT_EQ(max_size, chooser.capture_size());
  317. // Various source sizes within bounds.
  318. chooser.SetSourceSize(gfx::Size(640, 480));
  319. EXPECT_EQ(gfx::Size(640, 480), chooser.capture_size());
  320. chooser.SetSourceSize(gfx::Size(480, 640));
  321. EXPECT_EQ(gfx::Size(480, 640), chooser.capture_size());
  322. chooser.SetSourceSize(gfx::Size(640, 640));
  323. EXPECT_EQ(gfx::Size(640, 640), chooser.capture_size());
  324. chooser.SetSourceSize(gfx::Size(2, 2));
  325. EXPECT_EQ(gfx::Size(2, 2), chooser.capture_size());
  326. // Bad source size results in no update.
  327. const gfx::Size unchanged_size = chooser.capture_size();
  328. chooser.SetSourceSize(gfx::Size(0, 0));
  329. EXPECT_EQ(unchanged_size, chooser.capture_size());
  330. // Downscaling size (preserving aspect ratio) when source size exceeds the
  331. // upper bounds.
  332. chooser.SetSourceSize(gfx::Size(kMaxFrameWidth * 2, kMaxFrameHeight * 2));
  333. EXPECT_EQ(max_size, chooser.capture_size());
  334. chooser.SetSourceSize(gfx::Size(kMaxFrameWidth * 2, kMaxFrameHeight));
  335. EXPECT_EQ(gfx::Size(kMaxFrameWidth, kMaxFrameHeight / 2),
  336. chooser.capture_size());
  337. chooser.SetSourceSize(gfx::Size(kMaxFrameWidth, kMaxFrameHeight * 2));
  338. EXPECT_EQ(gfx::Size(kMaxFrameWidth / 2, kMaxFrameHeight),
  339. chooser.capture_size());
  340. // For a chooser configured with the "any within limit" policy, the smallest
  341. // possible computed size is smallest non-empty snapped size (which is 90
  342. // lines of resolution) with the same aspect ratio as the maximum size.
  343. const gfx::Size smallest_size(90 * kMaxFrameWidth / kMaxFrameHeight, 90);
  344. TestSnappedFrameSizes(&chooser, smallest_size);
  345. TestTargetedFrameAreas(&chooser, smallest_size);
  346. }
  347. } // namespace media