/*
 *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "call/adaptation/video_source_restrictions.h"

#include "test/gtest.h"

namespace webrtc {

namespace {

const size_t kHdPixels = 1280 * 720;

const VideoSourceRestrictions kUnlimited;
const VideoSourceRestrictions k15fps(std::nullopt, std::nullopt, 15.0);
const VideoSourceRestrictions kHd(kHdPixels, kHdPixels, std::nullopt);
const VideoSourceRestrictions kHd15fps(kHdPixels, kHdPixels, 15.0);
const VideoSourceRestrictions kVga7fps(kHdPixels / 2, kHdPixels / 2, 7.0);

VideoSourceRestrictions RestrictionsFromMaxPixelsPerFrame(
    size_t max_pixels_per_frame) {
  return VideoSourceRestrictions(max_pixels_per_frame, std::nullopt,
                                 std::nullopt);
}

VideoSourceRestrictions RestrictionsFromMaxFrameRate(double max_frame_rate) {
  return VideoSourceRestrictions(std::nullopt, std::nullopt, max_frame_rate);
}

}  // namespace

TEST(VideoSourceRestrictionsTest, DidIncreaseResolution) {
  // smaller restrictions -> larger restrictions
  EXPECT_TRUE(DidIncreaseResolution(RestrictionsFromMaxPixelsPerFrame(10),
                                    RestrictionsFromMaxPixelsPerFrame(11)));
  // unrestricted -> restricted
  EXPECT_FALSE(DidIncreaseResolution(VideoSourceRestrictions(),
                                     RestrictionsFromMaxPixelsPerFrame(10)));
  // restricted -> unrestricted
  EXPECT_TRUE(DidIncreaseResolution(RestrictionsFromMaxPixelsPerFrame(10),
                                    VideoSourceRestrictions()));
  // restricted -> equally restricted
  EXPECT_FALSE(DidIncreaseResolution(RestrictionsFromMaxPixelsPerFrame(10),
                                     RestrictionsFromMaxPixelsPerFrame(10)));
  // unrestricted -> unrestricted
  EXPECT_FALSE(DidIncreaseResolution(VideoSourceRestrictions(),
                                     VideoSourceRestrictions()));
  // larger restrictions -> smaller restrictions
  EXPECT_FALSE(DidIncreaseResolution(RestrictionsFromMaxPixelsPerFrame(10),
                                     RestrictionsFromMaxPixelsPerFrame(9)));
}

TEST(VideoSourceRestrictionsTest, DidDecreaseFrameRate) {
  // samller restrictions -> larger restrictions
  EXPECT_FALSE(DidDecreaseFrameRate(RestrictionsFromMaxFrameRate(10),
                                    RestrictionsFromMaxFrameRate(11)));
  // unrestricted -> restricted
  EXPECT_TRUE(DidDecreaseFrameRate(VideoSourceRestrictions(),
                                   RestrictionsFromMaxFrameRate(10)));
  // restricted -> unrestricted
  EXPECT_FALSE(DidDecreaseFrameRate(RestrictionsFromMaxFrameRate(10),
                                    VideoSourceRestrictions()));
  // restricted -> equally restricted
  EXPECT_FALSE(DidDecreaseFrameRate(RestrictionsFromMaxFrameRate(10),
                                    RestrictionsFromMaxFrameRate(10)));
  // unrestricted -> unrestricted
  EXPECT_FALSE(DidDecreaseFrameRate(VideoSourceRestrictions(),
                                    VideoSourceRestrictions()));
  // larger restrictions -> samller restrictions
  EXPECT_TRUE(DidDecreaseFrameRate(RestrictionsFromMaxFrameRate(10),
                                   RestrictionsFromMaxFrameRate(9)));
}

TEST(VideoSourceRestrictionsTest, DidRestrictionsChangeFalseForSame) {
  EXPECT_FALSE(DidRestrictionsDecrease(kUnlimited, kUnlimited));
  EXPECT_FALSE(DidRestrictionsIncrease(kUnlimited, kUnlimited));

  // Both resolution and fps restricted.
  EXPECT_FALSE(DidRestrictionsDecrease(kHd15fps, kHd15fps));
  EXPECT_FALSE(DidRestrictionsIncrease(kHd15fps, kHd15fps));
}

TEST(VideoSourceRestrictions,
     DidRestrictionsIncreaseTrueWhenPixelsOrFrameRateDecreased) {
  // Unlimited > Limited resolution.
  EXPECT_TRUE(DidRestrictionsIncrease(kUnlimited, kHd));
  // Unlimited > limited fps.
  EXPECT_TRUE(DidRestrictionsIncrease(kUnlimited, k15fps));
  // Unlimited > limited resolution + limited fps.
  EXPECT_TRUE(DidRestrictionsIncrease(kUnlimited, kHd15fps));
  // Limited resolution > limited resolution + limited fps.
  EXPECT_TRUE(DidRestrictionsIncrease(kHd, kHd15fps));
  // Limited fps > limited resolution + limited fps.
  EXPECT_TRUE(DidRestrictionsIncrease(k15fps, kHd15fps));
  // Limited resolution + fps > More limited resolution + more limited fps
  EXPECT_TRUE(DidRestrictionsIncrease(kHd15fps, kVga7fps));
}

TEST(VideoSourceRestrictions,
     DidRestrictionsDecreaseTrueWhenPixelsOrFrameRateIncreased) {
  // Limited resolution < Unlimited.
  EXPECT_TRUE(DidRestrictionsDecrease(kHd, kUnlimited));
  // Limited fps < Unlimited.
  EXPECT_TRUE(DidRestrictionsDecrease(k15fps, kUnlimited));
  // Limited resolution + limited fps < unlimited.
  EXPECT_TRUE(DidRestrictionsDecrease(kHd15fps, kUnlimited));
  // Limited resolution + limited fps < limited resolution.
  EXPECT_TRUE(DidRestrictionsDecrease(kHd15fps, kHd));
  // Limited resolution + limited fps < limited fps.
  EXPECT_TRUE(DidRestrictionsDecrease(kHd15fps, k15fps));
  // More limited resolution + more limited fps < limited resolution + fps
  EXPECT_TRUE(DidRestrictionsDecrease(kVga7fps, kHd15fps));
}

TEST(VideoSourceRestrictions,
     DidRestrictionsChangeFalseWhenFrameRateAndPixelsChangeDifferently) {
  // One changed framerate, the other resolution; not an increase or decrease.
  EXPECT_FALSE(DidRestrictionsIncrease(kHd, k15fps));
  EXPECT_FALSE(DidRestrictionsDecrease(kHd, k15fps));
}

TEST(VideoSourceRestrictions, UpdateMin) {
  VideoSourceRestrictions one(kHdPixels / 2, kHdPixels, 7.0);
  VideoSourceRestrictions two(kHdPixels, kHdPixels / 3, 15.0);

  one.UpdateMin(two);

  EXPECT_EQ(one.max_pixels_per_frame(), kHdPixels / 2);
  EXPECT_EQ(one.target_pixels_per_frame(), kHdPixels / 3);
  EXPECT_EQ(one.max_frame_rate(), 7.0);

  two.UpdateMin(one);

  EXPECT_EQ(two.max_pixels_per_frame(), kHdPixels / 2);
  EXPECT_EQ(two.target_pixels_per_frame(), kHdPixels / 3);
  EXPECT_EQ(two.max_frame_rate(), 7.0);
}

}  // namespace webrtc
