#include <gtest/gtest.h>

#include "FrameDelayCalculator.h"
#include "video.h"
#include "audio.h"
#include "rtp/RTPPacket.h"
#include "data/FramesArrivalInfo.h"
#include "TestCommon.h"

using namespace std::chrono;

namespace
{
	
constexpr uint64_t MediaTypeToSsrc(MediaFrame::Type type)
{
	return type == MediaFrame::Audio ? 1 : 2;
}

}

class TestFrameDelayCalculator : public testing::Test
{
public:
	/**
	 * Test frame delay calculator.
	 * 
	 * @param framesInfo	The frame arrival info
	 * @param references 	The expected latencies of the reference time and timestamps againt the first arrived frame
	 * @param delays	The expected delay to be set for each stream. The first element of the pair is the ssrc of the stream.
	 *                      If nullptr, the delays wouldn't be checked.
	 */
	void TestDelayCalculator(const std::vector<std::tuple<MediaFrame::Type, uint64_t, uint64_t, uint32_t>>& framesInfo, 
			const std::vector<int64_t>& expectedLatencies, 
			const std::vector<std::pair<uint64_t, int64_t>>* delays);
	
protected:
	
	/**
	 * Calculate the latencies again the first reference time and timestamps. The negative value
	 * means the references used has a less latency than the first reference (which is basing on 
	 * first frame).
	 */
	std::vector<int64_t> calcLatency(const std::vector<std::pair<std::chrono::milliseconds, uint64_t>>& references);

	TestTimeService timeService;
	std::shared_ptr<FrameDelayCalculator> calculator;
};

void TestFrameDelayCalculator::TestDelayCalculator(const std::vector<std::tuple<MediaFrame::Type, uint64_t, uint64_t, uint32_t>>& framesInfo,
						const std::vector<int64_t>& expectedLatencies,
						const std::vector<std::pair<uint64_t, int64_t>>* expectedDelays)
{
	std::queue<std::pair<RTPPacket::shared, std::chrono::milliseconds>> audioPackets;
	std::queue<std::pair<RTPPacket::shared, std::chrono::milliseconds>> videoPackets;
	
	std::vector<std::pair<std::chrono::milliseconds, uint64_t>> references;
	std::vector<std::pair<uint64_t, int64_t>> delays;

	// Loop through all frames
	for (auto& f : framesInfo)
	{	
		auto now = std::chrono::milliseconds(std::get<1>(f));
				
		auto mediaType = std::get<0>(f);
		auto ssrc = MediaTypeToSsrc(mediaType);
		auto delayMs = calculator->OnFrame(ssrc, now, std::get<2>(f), std::get<3>(f));
		delays.emplace_back(ssrc, delayMs.count());
		
		auto [refTime, refTs] = calculator->reference.Get();
		
		if (references.empty())
		{
			references.emplace_back(refTime, refTs);
		}
		else
		{
			auto lastRef = references.back();
			if (lastRef.first != refTime || lastRef.second != refTs)
			{
				references.emplace_back(refTime, refTs);
			}
		}
		
	}

	auto latencies = calcLatency(references);
	
	ASSERT_EQ(expectedLatencies, latencies);
	
	if (expectedDelays != nullptr)
		ASSERT_EQ(*expectedDelays, delays);
}


std::vector<int64_t> TestFrameDelayCalculator::calcLatency(const std::vector<std::pair<std::chrono::milliseconds, uint64_t>>& references)
{
	std::vector<int64_t> latencies;
	
	if (references.empty()) return {};
	
	auto& first = references.front();

	for (auto& r : references)
	{
		auto calculatedTimeDiffMs = (r.second - first.second) * 1000 / 90000;
		auto timeDiffMs = r.first - first.first;
		
		latencies.push_back(timeDiffMs.count() - int64_t(calculatedTimeDiffMs));
	}
	
	return latencies;
}

TEST_F(TestFrameDelayCalculator, TestNormal)
{
	calculator = FrameDelayCalculator::Create(0, std::chrono::milliseconds(20), timeService);

	std::vector<int64_t> expectedLatencies = {0, 18, 18, 24, 27, 28};
	
	std::vector<std::pair<uint64_t, int64_t>> expectedDelays = {
		{ 1, 0 }, { 1, 21 }, { 1, 42 }, { 1, 64 }, { 1, 85 }, { 1, 96 }, { 1, 118 }, { 1, 139 },
		{ 1, 7 }, { 1, 29 }, { 1, 50 }, { 1, 71 }, { 1, 93 }, { 1, 101 }, { 1, 122 }, { 1, 144 },
		{ 2, 153 }, { 2, 135 }, { 2, 149 }, { 1, 0 }, { 1, 21 }, { 1, 42 }, { 1, 64 }, { 1, 85 },
		{ 1, 106 }, { 1, 128 }, { 1, 139 }, { 2, 159 }, { 2, 165 }, { 2, 168 }, { 2, 151 }, { 2, 163 },
		{ 1, 1 }, { 1, 23 }, { 1, 44 }, { 1, 65 }, { 1, 87 }, { 1, 108 }, { 1, 129 }, { 1, 151 },
		{ 2, 156 }, { 2, 169 }, { 2, 163 }, { 2, 166 }, { 2, 158 }, { 1, 0 }, { 1, 21 }, { 1, 43 },
		{ 1, 64 }, { 1, 85 }, { 1, 107 }, { 1, 118 }, { 1, 138 }, { 2, 150 }, { 2, 164 }, { 2, 156 },
		{ 2, 159 }, { 2, 156 }, { 1, 12 }, { 1, 33 }, { 1, 54 }, { 1, 76 }, { 1, 97 }, { 1, 118 },
		{ 1, 140 }, { 1, 161 }, { 2, 169 }, { 2, 163 }, { 2, 146 }, { 2, 158 }, { 2, 152 }, { 1, 10 },
		{ 1, 32 }, { 1, 53 }, { 1, 74 }, { 1, 96 }, { 1, 117 }, { 1, 138 }, { 1, 160 }, { 2, 164 },
		{ 2, 156 }, { 2, 160 }, { 2, 152 }, { 2, 165 }, { 1, 10 }, { 1, 30 }, { 1, 52 }, { 1, 73 },
		{ 1, 94 }, { 1, 116 }, { 1, 137 }, { 1, 158 }, { 2, 159 }, { 2, 152 }, { 2, 158 }, { 2, 151 },
		{ 2, 164 }, { 1, 12 }, { 1, 33 }, { 1, 54 }, { 1, 76 }, { 1, 97 }, { 1, 118 }, { 1, 140 },
		{ 1, 161 }, { 2, 158 }, { 2, 163 }, { 2, 156 }, { 2, 150 }, { 2, 162 }, { 1, 23 }, { 1, 45 },
		{ 1, 66 }, { 1, 87 }, { 1, 109 }, { 1, 130 }, { 1, 141 }, { 2, 155 }, { 2, 159 }, { 2, 152 },
		{ 2, 166 }, { 2, 159 }, { 1, 2 }, { 1, 23 }, { 1, 44 }, { 1, 66 }, { 1, 87 }, { 1, 108 },
		{ 1, 130 }, { 1, 151 }, { 2, 161 }, { 2, 164 }, { 2, 147 }, { 2, 159 }, { 2, 152 }, { 1, 0 },
		{ 1, 21 }, { 1, 42 }, { 1, 64 }, { 1, 85 }, { 1, 106 }, { 1, 128 }, { 1, 149 }, { 2, 155 },
		{ 2, 148 }, { 2, 161 }, { 2, 164 }, { 2, 153 }, { 1, 14 }, { 1, 36 }, { 1, 56 }, { 1, 77 },
		{ 1, 99 }, { 1, 120 }, { 1, 141 }, { 1, 163 }, { 2, 165 }, { 2, 149 }, { 2, 161 }, { 2, 154 },
		{ 2, 157 }, { 1, 11 }, { 1, 32 }, { 1, 54 }, { 1, 75 }, { 1, 96 }, { 1, 118 }, { 1, 139 },
		{ 2, 159 }, { 2, 147 }, { 2, 160 }, { 2, 153 }, { 2, 167 }, { 1, 0 }, { 1, 21 }, { 1, 41 },
		{ 1, 63 }, { 1, 84 }, { 1, 105 }, { 1, 127 }, { 1, 148 }, { 2, 164 }, { 2, 168 }, { 2, 160 },
		{ 2, 163 }, { 2, 166 }, { 1, 11 }, { 1, 33 }, { 1, 54 }, { 1, 75 }, { 1, 97 }, { 1, 118 },
		{ 1, 119 }, { 1, 141 }, { 2, 153 }, { 2, 167 }, { 2, 159 }, { 2, 172 }, { 2, 165 }, { 1, 9 },
		{ 1, 30 }, { 1, 52 }, { 1, 73 }, { 1, 94 }, { 1, 116 }, { 1, 137 }, { 1, 158 }, { 2, 167 },
		{ 2, 160 }, { 2, 154 }, { 2, 167 }, { 2, 160 }, { 1, 12 }, { 1, 33 }, { 1, 53 }, { 1, 75 },
		{ 1, 96 }, { 1, 117 }, { 1, 139 }, { 1, 160 }, { 2, 165 }, { 2, 158 }, { 2, 172 }, { 2, 164 },
		{ 2, 167 }, { 1, 19 }, { 1, 41 }, { 1, 62 }, { 1, 83 }, { 1, 105 }, { 1, 126 }, { 1, 147 },
		{ 1, 169 }, { 2, 161 }, { 2, 154 }, { 2, 167 }, { 2, 165 }, { 2, 167 }, { 1, 23 }, { 1, 44 },
		{ 1, 66 }, { 1, 87 }, { 1, 108 }, { 1, 130 }, { 1, 141 }, { 1, 162 }, { 2, 159 }, { 2, 173 },
		{ 2, 165 }, { 2, 159 }, { 2, 172 }, { 1, 27 }, { 1, 48 }, { 1, 69 }, { 1, 91 }, { 1, 112 },
		{ 1, 133 }, { 1, 135 }, { 1, 156 }, { 2, 149 }, { 2, 173 }, { 2, 167 }, { 2, 170 }, { 2, 159 },
		{ 1, 33 }, { 1, 55 }, { 1, 75 }, { 1, 96 }, { 1, 118 }, { 1, 139 }, { 1, 160 }, { 1, 163 },
		{ 2, 152 }, { 2, 166 }, { 2, 159 }, { 2, 172 }, { 2, 158 }, { 2, 161 }, { 1, 5 }, { 1, 26 },
		{ 1, 48 }, { 1, 69 }, { 1, 90 }, { 1, 103 }, { 1, 124 }, { 1, 145 }, { 2, 164 }, { 2, 168 },
		{ 2, 171 }, { 2, 154 }, { 2, 167 }, { 1, 6 }, { 1, 27 }, { 1, 48 }, { 1, 70 }, { 1, 91 },
		{ 1, 112 }, { 1, 134 }, { 1, 144 }, { 2, 159 }, { 2, 176 }, { 2, 168 }, { 2, 170 }, { 2, 164 },
		{ 1, 7 }, { 1, 29 }, { 1, 50 }, { 1, 71 }, { 1, 93 }, { 1, 114 }, { 1, 135 }, { 1, 157 },
		{ 2, 158 }, { 2, 174 }, { 2, 157 }, { 2, 170 }, { 2, 163 }, { 1, 20 }, { 1, 41 }, { 1, 63 },
		{ 1, 84 }, { 1, 105 }, { 1, 127 }, { 1, 148 }, { 1, 169 }, { 2, 177 }, { 2, 169 }, { 2, 172 },
		{ 2, 165 }, { 2, 157 }, { 1, 18 }, { 1, 39 }, { 1, 60 }, { 1, 82 }, { 1, 102 }, { 1, 123 },
		{ 1, 145 }, { 1, 166 }, { 2, 170 }, { 2, 163 }, { 2, 165 }, { 2, 159 }, { 2, 171 }, { 1, 15 },
		{ 1, 37 }, { 1, 58 }, { 1, 79 }, { 1, 101 }, { 1, 121 }, { 1, 142 }, { 1, 164 }, { 2, 164 },
		{ 2, 160 }, { 2, 163 }, { 2, 156 }, { 2, 169 }, { 1, 26 }, { 1, 47 }, { 1, 69 }, { 1, 90 },
		{ 1, 111 }, { 1, 133 }, { 1, 154 }, { 1, 166 }, { 2, 161 }, { 2, 167 }, { 2, 161 }, { 2, 153 },
		{ 2, 167 }, { 1, 29 }, { 1, 50 }, { 1, 71 }, { 1, 93 }, { 1, 114 }, { 1, 126 }, { 1, 147 },
		{ 1, 168 }, { 2, 160 }, { 2, 174 }, { 2, 156 }, { 2, 169 }, { 2, 162 }, { 2, 164 }, { 1, 0 },
		{ 1, 21 }, { 1, 42 }, { 1, 64 }, { 1, 85 }, { 1, 106 }, { 1, 128 }, { 1, 139 }, { 2, 161 },
		{ 2, 157 }, { 2, 170 }, { 2, 164 }, { 2, 157 }, { 1, 3 }, { 1, 25 }, { 1, 46 }, { 1, 67 },
		{ 1, 89 }, { 1, 110 }, { 1, 131 }, { 1, 143 }, { 2, 161 }, { 2, 173 }, { 2, 166 }, { 2, 159 },
		{ 2, 171 }, { 1, 1 }, { 1, 22 }, { 1, 44 }, { 1, 65 }, { 1, 86 }, { 1, 108 }, { 1, 129 },
		{ 1, 140 }, { 2, 154 }, { 2, 171 }, { 2, 164 }, { 2, 169 }, { 2, 173 }, { 1, 16 }, { 1, 37 },
		{ 1, 58 }, { 1, 80 }, { 1, 101 }, { 1, 122 }, { 1, 144 }, { 1, 165 }, { 2, 175 }, { 2, 168 },
		{ 2, 163 }, { 2, 176 }, { 2, 160 }, { 1, 16 }, { 1, 38 }, { 1, 59 }, { 1, 80 }, { 1, 102 },
		{ 1, 123 }, { 1, 144 }, { 1, 166 }, { 2, 172 }, { 2, 165 }, { 2, 168 }, { 2, 170 }, { 2, 153 },
		{ 1, 14 }, { 1, 35 }, { 1, 57 }, { 1, 78 }, { 1, 99 }, { 1, 121 }, { 1, 142 }, { 1, 163 },
		{ 2, 166 }, { 2, 163 }, { 2, 177 }, { 2, 170 }, { 2, 173 }, { 1, 28 }, { 1, 49 }, { 1, 70 },
		{ 1, 92 }, { 1, 113 }, { 1, 134 }, { 1, 156 }, { 1, 167 }, { 2, 166 }, { 2, 159 }, { 2, 171 },
		{ 2, 164 }, { 2, 170 }, { 1, 31 }, { 1, 53 }, { 1, 73 }, { 1, 94 }, { 1, 116 }, { 1, 137 },
		{ 1, 148 }, { 1, 170 }, { 2, 165 }, { 2, 157 }, { 2, 173 }, { 2, 177 }, { 2, 170 }, { 1, 33 },
		{ 1, 54 }, { 1, 76 }, { 1, 97 }, { 1, 118 }, { 1, 140 }, { 1, 161 }, { 1, 162 }, { 2, 153 },
		{ 2, 177 }, { 2, 170 }, { 2, 168 }, { 2, 164 }, { 2, 178 }, { 1, 2 }, { 1, 22 }, { 1, 43 },
		{ 1, 65 }, { 1, 86 }, { 1, 107 }, { 1, 129 }, { 1, 150 }, { 2, 171 }, { 2, 164 }, { 2, 167 },
		{ 2, 160 }, { 2, 173 }, { 1, 9 }, { 1, 31 }, { 1, 52 }, { 1, 73 }, { 1, 95 }, { 1, 107 },
		{ 1, 128 }, { 1, 150 }, { 2, 166 }, { 2, 164 }, { 2, 178 }, { 2, 170 }, { 1, 10 }, { 1, 31 },
		{ 1, 53 }, { 1, 74 }, { 1, 95 }, { 1, 117 }, { 1, 130 }, { 1, 151 }, { 2, 164 }, { 2, 180 },
		{ 2, 163 }, { 2, 175 }, { 1, 54 }, { 1, 75 }, { 1, 96 }, { 1, 118 }, { 1, 129 }, { 1, 149 },
		{ 1, 171 }, { 2, 168 }, { 2, 173 }, { 2, 176 }, { 2, 159 }, { 2, 174 }, { 1, 35 }, { 1, 56 },
		{ 1, 78 }, { 1, 99 }, { 1, 120 }, { 1, 141 }, { 1, 152 }, { 1, 173 }, { 2, 167 }, { 2, 180 },
		{ 2, 162 }, { 2, 175 }, { 2, 168 }, { 1, 32 }, { 1, 53 }, { 1, 74 }, { 1, 96 }, { 1, 117 },
		{ 1, 138 }, { 1, 160 }, { 1, 171 }, { 2, 160 }, { 2, 174 }, { 2, 156 }, { 2, 168 }, { 2, 162 },
		{ 2, 174 }, { 1, 0 }, { 1, 21 }, { 1, 42 }, { 1, 64 }, { 1, 85 }, { 1, 106 }, { 1, 128 },
		{ 1, 149 }, { 2, 168 }, { 2, 171 }, { 2, 164 }, { 2, 161 }, { 2, 174 }, { 1, 13 }, { 1, 35 },
		{ 1, 55 }, { 1, 76 }, { 1, 98 }, { 1, 119 }, { 1, 140 }, { 1, 158 }, { 2, 173 }, { 2, 176 },
		{ 2, 166 }, { 2, 180 }, { 2, 172 }, { 1, 15 }, { 1, 36 }, { 1, 57 }, { 1, 78 }, { 1, 99 },
		{ 1, 121 }, { 1, 142 }, { 1, 163 }, { 2, 155 }, { 2, 168 }, { 2, 160 }, { 2, 175 }, { 2, 169 },
		{ 1, 15 }, { 1, 36 }, { 1, 57 }, { 1, 79 }, { 1, 100 }, { 1, 121 }, { 1, 143 }, { 1, 164 },
		{ 2, 171 }, { 2, 164 }, { 2, 177 }, { 2, 160 }, { 2, 162 }, { 1, 22 }, { 1, 44 }, { 1, 65 },
		{ 1, 86 }, { 1, 108 }, { 1, 123 }, { 1, 143 }, { 1, 165 }, { 2, 168 }, { 2, 162 }, { 2, 175 },
		{ 2, 168 }, { 2, 172 }, { 1, 26 }, { 1, 47 }, { 1, 69 }, { 1, 90 }, { 1, 111 }, { 1, 133 },
		{ 1, 144 }, { 1, 165 }, { 2, 165 }, { 2, 158 }, { 2, 171 }, { 2, 153 }, { 2, 170 }, { 1, 27 },
		{ 1, 48 }, { 1, 69 }, { 1, 91 }, { 1, 112 }, { 1, 124 }, { 1, 145 }, { 2, 162 }, { 2, 176 },
		{ 2, 170 }, { 2, 172 }, { 1, 5 }, { 1, 26 }, { 1, 48 }, { 1, 69 }, { 1, 90 }, { 1, 112 },
		{ 1, 133 }, { 1, 148 }, { 2, 162 }, { 2, 175 }, { 2, 164 }, { 2, 170 }, { 2, 163 }, { 1, 17 },
		{ 1, 38 }, { 1, 59 }, { 1, 81 }, { 1, 102 }, { 1, 123 }, { 1, 145 }, { 1, 166 }, { 2, 176 },
		{ 2, 168 }, { 2, 161 }, { 2, 168 }, { 2, 160 }, { 1, 18 }, { 1, 40 }, { 1, 61 }, { 1, 82 },
		{ 1, 104 }, { 1, 125 }, { 1, 146 }, { 1, 168 }, { 2, 173 }, { 2, 166 }, { 2, 170 }, { 2, 163 },
		{ 2, 156 }, { 1, 18 }, { 1, 39 }, { 1, 61 }, { 1, 82 }, { 1, 103 }, { 1, 125 }, { 1, 146 },
		{ 1, 167 }, { 2, 169 }, { 2, 163 }, { 2, 177 }, { 2, 169 }, { 2, 172 }, { 1, 28 }, { 1, 49 },
		{ 1, 70 }, { 1, 92 }, { 1, 113 }, { 1, 134 }, { 1, 146 }, { 1, 166 }, { 2, 164 }, { 2, 167 },
		{ 2, 170 }, { 2, 153 }, { 2, 171 }, { 1, 29 }, { 1, 51 }, { 1, 72 }, { 1, 93 }, { 1, 115 },
		{ 1, 126 }, { 1, 147 }, { 1, 169 }, { 2, 163 }, { 2, 175 }, { 2, 169 }, { 2, 171 }, { 2, 163 },
		{ 1, 27 }, { 1, 48 }, { 1, 70 }, { 1, 91 }, { 1, 112 }, { 1, 134 }, { 1, 155 }, { 1, 176 },
		{ 2, 156 }, { 2, 169 }, { 2, 161 }, { 2, 165 }
	};
	
	ASSERT_NO_FATAL_FAILURE(TestDelayCalculator(TestData::FramesArrivalInfo, expectedLatencies, &expectedDelays));
}

TEST_F(TestFrameDelayCalculator, testLatencyReduction)
{	
	calculator = FrameDelayCalculator::Create(0, std::chrono::milliseconds(3), timeService);
	
	std::vector<int64_t> expectedLatencies = {
		0, 18, 18, 24, 21, 27, 28, 25
	};

	std::vector<std::pair<uint64_t, int64_t>> expectedDelays = {
		{ 1, 0 }, { 1, 21 }, { 1, 42 }, { 1, 64 }, { 1, 85 }, { 1, 96 }, { 1, 118 }, { 1, 139 }, 
		{ 1, 7 }, { 1, 29 }, { 1, 50 }, { 1, 71 }, { 1, 93 }, { 1, 101 }, { 1, 122 }, { 1, 144 }, 
		{ 2, 153 }, { 2, 135 }, { 2, 149 }, { 1, 0 }, { 1, 21 }, { 1, 42 }, { 1, 64 }, { 1, 85 }, 
		{ 1, 106 }, { 1, 128 }, { 1, 139 }, { 2, 159 }, { 2, 165 }, { 2, 168 }, { 2, 151 }, { 2, 163 }, 
		{ 1, 1 }, { 1, 23 }, { 1, 44 }, { 1, 65 }, { 1, 87 }, { 1, 108 }, { 1, 129 }, { 1, 151 }, 
		{ 2, 156 }, { 2, 169 }, { 2, 163 }, { 2, 166 }, { 2, 158 }, { 1, 0 }, { 1, 21 }, { 1, 43 }, 
		{ 1, 64 }, { 1, 85 }, { 1, 107 }, { 1, 118 }, { 1, 138 }, { 2, 150 }, { 2, 164 }, { 2, 156 }, 
		{ 2, 159 }, { 2, 156 }, { 1, 12 }, { 1, 33 }, { 1, 54 }, { 1, 76 }, { 1, 97 }, { 1, 118 }, 
		{ 1, 140 }, { 1, 161 }, { 2, 169 }, { 2, 163 }, { 2, 146 }, { 2, 158 }, { 2, 152 }, { 1, 10 }, 
		{ 1, 32 }, { 1, 53 }, { 1, 74 }, { 1, 96 }, { 1, 117 }, { 1, 138 }, { 1, 160 }, { 2, 164 }, 
		{ 2, 156 }, { 2, 160 }, { 2, 152 }, { 2, 165 }, { 1, 10 }, { 1, 30 }, { 1, 52 }, { 1, 73 }, 
		{ 1, 94 }, { 1, 116 }, { 1, 137 }, { 1, 158 }, { 2, 159 }, { 2, 152 }, { 2, 158 }, { 2, 151 }, 
		{ 2, 164 }, { 1, 12 }, { 1, 33 }, { 1, 54 }, { 1, 76 }, { 1, 97 }, { 1, 118 }, { 1, 140 }, 
		{ 1, 161 }, { 2, 158 }, { 2, 163 }, { 2, 156 }, { 2, 150 }, { 2, 162 }, { 1, 23 }, { 1, 45 }, 
		{ 1, 66 }, { 1, 87 }, { 1, 109 }, { 1, 130 }, { 1, 141 }, { 2, 155 }, { 2, 159 }, { 2, 152 }, 
		{ 2, 166 }, { 2, 159 }, { 1, 2 }, { 1, 23 }, { 1, 44 }, { 1, 66 }, { 1, 87 }, { 1, 108 }, 
		{ 1, 130 }, { 1, 151 }, { 2, 161 }, { 2, 164 }, { 2, 147 }, { 2, 159 }, { 2, 152 }, { 1, 0 }, 
		{ 1, 21 }, { 1, 42 }, { 1, 64 }, { 1, 85 }, { 1, 106 }, { 1, 128 }, { 1, 149 }, { 2, 155 }, 
		{ 2, 148 }, { 2, 161 }, { 2, 164 }, { 2, 153 }, { 1, 14 }, { 1, 36 }, { 1, 56 }, { 1, 77 }, 
		{ 1, 99 }, { 1, 120 }, { 1, 141 }, { 1, 163 }, { 2, 165 }, { 2, 149 }, { 2, 161 }, { 2, 154 }, 
		{ 2, 157 }, { 1, 11 }, { 1, 32 }, { 1, 54 }, { 1, 75 }, { 1, 96 }, { 1, 118 }, { 1, 139 }, 
		{ 2, 159 }, { 2, 147 }, { 2, 160 }, { 2, 153 }, { 2, 167 }, { 1, 0 }, { 1, 21 }, { 1, 41 }, 
		{ 1, 63 }, { 1, 84 }, { 1, 105 }, { 1, 127 }, { 1, 148 }, { 2, 164 }, { 2, 168 }, { 2, 160 }, 
		{ 2, 163 }, { 2, 166 }, { 1, 11 }, { 1, 33 }, { 1, 54 }, { 1, 75 }, { 1, 97 }, { 1, 118 }, 
		{ 1, 119 }, { 1, 141 }, { 2, 153 }, { 2, 167 }, { 2, 159 }, { 2, 172 }, { 2, 165 }, { 1, 9 }, 
		{ 1, 30 }, { 1, 52 }, { 1, 73 }, { 1, 94 }, { 1, 116 }, { 1, 137 }, { 1, 158 }, { 2, 167 }, 
		{ 2, 160 }, { 2, 154 }, { 2, 167 }, { 2, 160 }, { 1, 12 }, { 1, 33 }, { 1, 53 }, { 1, 75 }, 
		{ 1, 96 }, { 1, 117 }, { 1, 139 }, { 1, 160 }, { 2, 165 }, { 2, 158 }, { 2, 172 }, { 2, 164 }, 
		{ 2, 167 }, { 1, 19 }, { 1, 41 }, { 1, 62 }, { 1, 83 }, { 1, 105 }, { 1, 126 }, { 1, 147 }, 
		{ 1, 169 }, { 2, 161 }, { 2, 154 }, { 2, 167 }, { 2, 165 }, { 2, 167 }, { 1, 23 }, { 1, 44 }, 
		{ 1, 66 }, { 1, 87 }, { 1, 108 }, { 1, 130 }, { 1, 141 }, { 1, 162 }, { 2, 159 }, { 2, 173 }, 
		{ 2, 165 }, { 2, 159 }, { 2, 172 }, { 1, 27 }, { 1, 48 }, { 1, 69 }, { 1, 91 }, { 1, 112 }, 
		{ 1, 133 }, { 1, 135 }, { 1, 156 }, { 2, 149 }, { 2, 173 }, { 2, 167 }, { 2, 170 }, { 2, 159 }, 
		{ 1, 33 }, { 1, 55 }, { 1, 75 }, { 1, 96 }, { 1, 118 }, { 1, 139 }, { 1, 160 }, { 1, 163 }, 
		{ 2, 152 }, { 2, 166 }, { 2, 159 }, { 2, 172 }, { 2, 158 }, { 2, 161 }, { 1, 5 }, { 1, 26 }, 
		{ 1, 48 }, { 1, 69 }, { 1, 90 }, { 1, 103 }, { 1, 124 }, { 1, 145 }, { 2, 164 }, { 2, 168 }, 
		{ 2, 171 }, { 2, 154 }, { 2, 167 }, { 1, 6 }, { 1, 27 }, { 1, 48 }, { 1, 70 }, { 1, 91 }, 
		{ 1, 112 }, { 1, 134 }, { 1, 144 }, { 2, 159 }, { 2, 176 }, { 2, 168 }, { 2, 170 }, { 2, 164 }, 
		{ 1, 7 }, { 1, 29 }, { 1, 50 }, { 1, 71 }, { 1, 93 }, { 1, 114 }, { 1, 135 }, { 1, 157 }, 
		{ 2, 158 }, { 2, 174 }, { 2, 157 }, { 2, 170 }, { 2, 163 }, { 1, 20 }, { 1, 41 }, { 1, 63 }, 
		{ 1, 84 }, { 1, 105 }, { 1, 127 }, { 1, 148 }, { 1, 169 }, { 2, 177 }, { 2, 169 }, { 2, 172 }, 
		{ 2, 165 }, { 2, 157 }, { 1, 15 }, { 1, 36 }, { 1, 57 }, { 1, 79 }, { 1, 99 }, { 1, 120 }, 
		{ 1, 142 }, { 1, 163 }, { 2, 167 }, { 2, 160 }, { 2, 162 }, { 2, 156 }, { 2, 168 }, { 1, 12 }, 
		{ 1, 34 }, { 1, 55 }, { 1, 76 }, { 1, 98 }, { 1, 118 }, { 1, 139 }, { 1, 161 }, { 2, 161 }, 
		{ 2, 157 }, { 2, 160 }, { 2, 153 }, { 2, 166 }, { 1, 23 }, { 1, 44 }, { 1, 66 }, { 1, 87 }, 
		{ 1, 108 }, { 1, 130 }, { 1, 151 }, { 1, 163 }, { 2, 158 }, { 2, 164 }, { 2, 158 }, { 2, 150 }, 
		{ 2, 164 }, { 1, 26 }, { 1, 47 }, { 1, 68 }, { 1, 90 }, { 1, 111 }, { 1, 123 }, { 1, 144 }, 
		{ 1, 165 }, { 2, 157 }, { 2, 171 }, { 2, 153 }, { 2, 166 }, { 2, 159 }, { 2, 161 }, { 1, 0 }, 
		{ 1, 21 }, { 1, 42 }, { 1, 64 }, { 1, 85 }, { 1, 106 }, { 1, 128 }, { 1, 139 }, { 2, 161 }, 
		{ 2, 157 }, { 2, 170 }, { 2, 164 }, { 2, 157 }, { 1, 3 }, { 1, 25 }, { 1, 46 }, { 1, 67 }, 
		{ 1, 89 }, { 1, 110 }, { 1, 131 }, { 1, 143 }, { 2, 161 }, { 2, 173 }, { 2, 166 }, { 2, 159 }, 
		{ 2, 171 }, { 1, 1 }, { 1, 22 }, { 1, 44 }, { 1, 65 }, { 1, 86 }, { 1, 108 }, { 1, 129 }, 
		{ 1, 140 }, { 2, 154 }, { 2, 171 }, { 2, 164 }, { 2, 169 }, { 2, 173 }, { 1, 16 }, { 1, 37 }, 
		{ 1, 58 }, { 1, 80 }, { 1, 101 }, { 1, 122 }, { 1, 144 }, { 1, 165 }, { 2, 175 }, { 2, 168 }, 
		{ 2, 163 }, { 2, 176 }, { 2, 160 }, { 1, 16 }, { 1, 38 }, { 1, 59 }, { 1, 80 }, { 1, 102 }, 
		{ 1, 123 }, { 1, 144 }, { 1, 166 }, { 2, 172 }, { 2, 165 }, { 2, 168 }, { 2, 170 }, { 2, 153 }, 
		{ 1, 14 }, { 1, 35 }, { 1, 57 }, { 1, 78 }, { 1, 99 }, { 1, 121 }, { 1, 142 }, { 1, 163 }, 
		{ 2, 166 }, { 2, 163 }, { 2, 177 }, { 2, 170 }, { 2, 173 }, { 1, 28 }, { 1, 49 }, { 1, 70 }, 
		{ 1, 92 }, { 1, 113 }, { 1, 134 }, { 1, 156 }, { 1, 167 }, { 2, 166 }, { 2, 159 }, { 2, 171 }, 
		{ 2, 164 }, { 2, 170 }, { 1, 31 }, { 1, 53 }, { 1, 73 }, { 1, 94 }, { 1, 116 }, { 1, 137 }, 
		{ 1, 148 }, { 1, 170 }, { 2, 165 }, { 2, 157 }, { 2, 173 }, { 2, 177 }, { 2, 170 }, { 1, 33 }, 
		{ 1, 54 }, { 1, 76 }, { 1, 97 }, { 1, 118 }, { 1, 140 }, { 1, 161 }, { 1, 162 }, { 2, 153 }, 
		{ 2, 177 }, { 2, 170 }, { 2, 168 }, { 2, 164 }, { 2, 178 }, { 1, 2 }, { 1, 22 }, { 1, 43 }, 
		{ 1, 65 }, { 1, 86 }, { 1, 107 }, { 1, 129 }, { 1, 150 }, { 2, 171 }, { 2, 164 }, { 2, 167 }, 
		{ 2, 160 }, { 2, 173 }, { 1, 9 }, { 1, 31 }, { 1, 52 }, { 1, 73 }, { 1, 95 }, { 1, 107 }, 
		{ 1, 128 }, { 1, 150 }, { 2, 166 }, { 2, 164 }, { 2, 178 }, { 2, 170 }, { 1, 10 }, { 1, 31 }, 
		{ 1, 53 }, { 1, 74 }, { 1, 95 }, { 1, 117 }, { 1, 130 }, { 1, 151 }, { 2, 164 }, { 2, 180 }, 
		{ 2, 163 }, { 2, 175 }, { 1, 54 }, { 1, 75 }, { 1, 96 }, { 1, 118 }, { 1, 129 }, { 1, 149 }, 
		{ 1, 171 }, { 2, 168 }, { 2, 173 }, { 2, 176 }, { 2, 159 }, { 2, 174 }, { 1, 35 }, { 1, 56 }, 
		{ 1, 78 }, { 1, 99 }, { 1, 120 }, { 1, 141 }, { 1, 152 }, { 1, 173 }, { 2, 167 }, { 2, 180 }, 
		{ 2, 162 }, { 2, 175 }, { 2, 168 }, { 1, 32 }, { 1, 53 }, { 1, 74 }, { 1, 96 }, { 1, 117 }, 
		{ 1, 138 }, { 1, 160 }, { 1, 171 }, { 2, 160 }, { 2, 174 }, { 2, 156 }, { 2, 168 }, { 2, 162 }, 
		{ 2, 174 }, { 1, 0 }, { 1, 21 }, { 1, 42 }, { 1, 64 }, { 1, 85 }, { 1, 106 }, { 1, 128 }, 
		{ 1, 149 }, { 2, 168 }, { 2, 171 }, { 2, 164 }, { 2, 161 }, { 2, 174 }, { 1, 13 }, { 1, 35 }, 
		{ 1, 55 }, { 1, 76 }, { 1, 98 }, { 1, 119 }, { 1, 140 }, { 1, 158 }, { 2, 173 }, { 2, 176 }, 
		{ 2, 166 }, { 2, 180 }, { 2, 172 }, { 1, 15 }, { 1, 36 }, { 1, 57 }, { 1, 78 }, { 1, 99 }, 
		{ 1, 121 }, { 1, 142 }, { 1, 163 }, { 2, 155 }, { 2, 168 }, { 2, 160 }, { 2, 175 }, { 2, 169 }, 
		{ 1, 15 }, { 1, 36 }, { 1, 57 }, { 1, 79 }, { 1, 100 }, { 1, 121 }, { 1, 143 }, { 1, 164 }, 
		{ 2, 171 }, { 2, 164 }, { 2, 177 }, { 2, 160 }, { 2, 162 }, { 1, 22 }, { 1, 44 }, { 1, 65 }, 
		{ 1, 86 }, { 1, 108 }, { 1, 123 }, { 1, 143 }, { 1, 165 }, { 2, 168 }, { 2, 162 }, { 2, 175 }, 
		{ 2, 168 }, { 2, 172 }, { 1, 26 }, { 1, 47 }, { 1, 69 }, { 1, 90 }, { 1, 111 }, { 1, 133 }, 
		{ 1, 144 }, { 1, 165 }, { 2, 165 }, { 2, 158 }, { 2, 171 }, { 2, 153 }, { 2, 170 }, { 1, 27 }, 
		{ 1, 48 }, { 1, 69 }, { 1, 91 }, { 1, 112 }, { 1, 124 }, { 1, 145 }, { 2, 162 }, { 2, 176 }, 
		{ 2, 170 }, { 2, 172 }, { 1, 5 }, { 1, 26 }, { 1, 48 }, { 1, 69 }, { 1, 90 }, { 1, 112 }, 
		{ 1, 133 }, { 1, 148 }, { 2, 162 }, { 2, 175 }, { 2, 164 }, { 2, 170 }, { 2, 163 }, { 1, 17 }, 
		{ 1, 38 }, { 1, 59 }, { 1, 81 }, { 1, 102 }, { 1, 123 }, { 1, 145 }, { 1, 166 }, { 2, 176 }, 
		{ 2, 168 }, { 2, 161 }, { 2, 168 }, { 2, 160 }, { 1, 18 }, { 1, 40 }, { 1, 61 }, { 1, 82 }, 
		{ 1, 104 }, { 1, 125 }, { 1, 146 }, { 1, 168 }, { 2, 173 }, { 2, 166 }, { 2, 170 }, { 2, 163 }, 
		{ 2, 156 }, { 1, 18 }, { 1, 39 }, { 1, 61 }, { 1, 82 }, { 1, 103 }, { 1, 125 }, { 1, 146 }, 
		{ 1, 167 }, { 2, 169 }, { 2, 163 }, { 2, 177 }, { 2, 169 }, { 2, 172 }, { 1, 28 }, { 1, 49 }, 
		{ 1, 70 }, { 1, 92 }, { 1, 113 }, { 1, 134 }, { 1, 146 }, { 1, 166 }, { 2, 164 }, { 2, 167 }, 
		{ 2, 170 }, { 2, 153 }, { 2, 171 }, { 1, 29 }, { 1, 51 }, { 1, 72 }, { 1, 93 }, { 1, 115 }, 
		{ 1, 126 }, { 1, 144 }, { 1, 166 }, { 2, 160 }, { 2, 172 }, { 2, 166 }, { 2, 168 }, { 2, 160 }, 
		{ 1, 24 }, { 1, 45 }, { 1, 67 }, { 1, 88 }, { 1, 109 }, { 1, 131 }, { 1, 152 }, { 1, 173 }, 
		{ 2, 153 }, { 2, 166 }, { 2, 158 }, { 2, 162 }
	};
	
	ASSERT_NO_FATAL_FAILURE(TestDelayCalculator(TestData::FramesArrivalInfo, expectedLatencies, &expectedDelays));
}


TEST_F(TestFrameDelayCalculator, testLatencyReduction2)
{	
	{
		calculator = FrameDelayCalculator::Create(10, std::chrono::milliseconds(20), timeService);
		// No reference time change in this case
		std::vector<int64_t> expectedLatencies = {
			0
		};

		ASSERT_NO_FATAL_FAILURE(TestDelayCalculator(TestData::FramesArrivalInfoLargeAVDesync, expectedLatencies, nullptr));
	}
	
	{
		calculator = FrameDelayCalculator::Create(10, std::chrono::milliseconds(5), timeService);	
		// There are reference changes due to reducing the threshold (step)
		std::vector<int64_t> expectedLatencies = {
			0, -5, -10
		};

		ASSERT_NO_FATAL_FAILURE(TestDelayCalculator(TestData::FramesArrivalInfoLargeAVDesync, expectedLatencies, nullptr));
	}
	
	{
		calculator = FrameDelayCalculator::Create(0, std::chrono::milliseconds(5), timeService);
		// There are more reference changes since we reduce the "late" threshold
		std::vector<int64_t> expectedLatencies = {
			0, 2, 5, 0, 1, 3, 6, 1, -4, -9, -7, -12, -6, -6, -5, -4, -3, -8, -6, -5, -4, -4, -9, -8, -4, -3
		};

		ASSERT_NO_FATAL_FAILURE(TestDelayCalculator(TestData::FramesArrivalInfoLargeAVDesync, expectedLatencies, nullptr));
	}
}


TEST_F(TestFrameDelayCalculator, testNoSameClock)
{
	auto calculator = FrameDelayCalculator::Create(0, std::chrono::milliseconds(3), timeService);

	uint64_t clockrate = 1000;
	
	ASSERT_EQ(calculator->OnFrame(1, 1000ms, 86000020, clockrate).count(), 0);
	ASSERT_EQ(calculator->OnFrame(2, 1000ms, 86000000, clockrate).count(), 0);

	ASSERT_EQ(calculator->OnFrame(1, 1020ms, 86000040, clockrate).count(), 20);
	ASSERT_EQ(calculator->OnFrame(2, 1020ms,       40, clockrate).count(), 0);

	ASSERT_EQ(calculator->OnFrame(1, 1020ms, 86000060, clockrate).count(), 0);
	ASSERT_EQ(calculator->OnFrame(2, 1020ms,       60, clockrate).count(), 0);

	ASSERT_EQ(calculator->OnFrame(1, 2020ms, 86001060, clockrate).count(), 0);
	ASSERT_EQ(calculator->OnFrame(2, 2020ms,     1060, clockrate).count(), 0);

	ASSERT_EQ(calculator->OnFrame(1, 2020ms, 86001080, clockrate).count(), 0);
	ASSERT_EQ(calculator->OnFrame(2, 2020ms,     1080, clockrate).count(), 0);
	ASSERT_EQ(calculator->OnFrame(2, 2040ms,     1100, clockrate).count(), 0);

}
