예제 #1
0
    def setUp(self):
        self.timestamp_to_ms = 1 / 90
        self.detector = OveruseDetector()
        self.estimator = OveruseEstimator()
        self.inter_arrival = InterArrival(5 * 90, 1 / 9)

        self.packet_size = 1200
        self.now_ms = 0
        self.receive_time_ms = 0
        self.rtp_timestamp = 900

        random.seed(21)
예제 #2
0
 def setUp(self):
     self.inter_arrival_ast = InterArrival(
         abs_send_time(TIMESTAMP_GROUP_LENGTH_US), 1000 / (1 << 26))
     self.inter_arrival_rtp = InterArrival(
         rtp_timestamp(TIMESTAMP_GROUP_LENGTH_US), 1 / 9)
예제 #3
0
class OveruseDetectorTest(TestCase):
    def setUp(self):
        self.timestamp_to_ms = 1 / 90
        self.detector = OveruseDetector()
        self.estimator = OveruseEstimator()
        self.inter_arrival = InterArrival(5 * 90, 1 / 9)

        self.packet_size = 1200
        self.now_ms = 0
        self.receive_time_ms = 0
        self.rtp_timestamp = 900

        random.seed(21)

    def test_simple_non_overuse_30fps(self):
        frame_duration_ms = 33

        for i in range(1000):
            self.update_detector(self.rtp_timestamp, self.now_ms)
            self.now_ms += frame_duration_ms
            self.rtp_timestamp += frame_duration_ms * 90
        self.assertEqual(self.detector.state(), BandwidthUsage.NORMAL)

    def test_simple_non_overuse_with_receive_variance(self):
        frame_duration_ms = 10

        for i in range(1000):
            self.update_detector(self.rtp_timestamp, self.now_ms)
            self.rtp_timestamp += frame_duration_ms * 90
            if i % 2:
                self.now_ms += frame_duration_ms - 5
            else:
                self.now_ms += frame_duration_ms + 5
            self.assertEqual(self.detector.state(), BandwidthUsage.NORMAL)

    def test_simple_non_overuse_with_rtp_timestamp_variance(self):
        frame_duration_ms = 10

        for i in range(1000):
            self.update_detector(self.rtp_timestamp, self.now_ms)
            self.now_ms += frame_duration_ms
            if i % 2:
                self.rtp_timestamp += (frame_duration_ms - 5) * 90
            else:
                self.rtp_timestamp += (frame_duration_ms + 5) * 90
            self.assertEqual(self.detector.state(), BandwidthUsage.NORMAL)

    def test_simple_overuse_2000Kbit_30fps(self):
        packets_per_frame = 6
        frame_duration_ms = 33
        drift_per_frame_ms = 1
        sigma_ms = 0

        unique_overuse = self.run_100000_samples(packets_per_frame,
                                                 frame_duration_ms, sigma_ms)
        self.assertEqual(unique_overuse, 0)

        frames_until_overuse = self.run_until_overuse(packets_per_frame,
                                                      frame_duration_ms,
                                                      sigma_ms,
                                                      drift_per_frame_ms)
        self.assertEqual(frames_until_overuse, 7)

    def test_simple_overuse_100Kbit_10fps(self):
        packets_per_frame = 1
        frame_duration_ms = 100
        drift_per_frame_ms = 1
        sigma_ms = 0

        unique_overuse = self.run_100000_samples(packets_per_frame,
                                                 frame_duration_ms, sigma_ms)
        self.assertEqual(unique_overuse, 0)

        frames_until_overuse = self.run_until_overuse(packets_per_frame,
                                                      frame_duration_ms,
                                                      sigma_ms,
                                                      drift_per_frame_ms)
        self.assertEqual(frames_until_overuse, 7)

    def test_overuse_with_low_variance_2000Kbit_30fps(self):
        frame_duration_ms = 33
        drift_per_frame_ms = 1
        self.rtp_timestamp = frame_duration_ms * 90
        offset = 0

        # run 1000 samples to reach steady state
        for i in range(1000):
            for j in range(6):
                self.update_detector(self.rtp_timestamp, self.now_ms)
            self.rtp_timestamp += frame_duration_ms * 90
            if i % 2:
                offset = random.randint(0, 1)
                self.now_ms += frame_duration_ms - offset
            else:
                self.now_ms += frame_duration_ms + offset
            self.assertEqual(self.detector.state(), BandwidthUsage.NORMAL)

        # simulate a higher send pace, that is too high.
        for i in range(3):
            for j in range(6):
                self.update_detector(self.rtp_timestamp, self.now_ms)
            self.now_ms += frame_duration_ms + drift_per_frame_ms * 6
            self.rtp_timestamp += frame_duration_ms * 90
            self.assertEqual(self.detector.state(), BandwidthUsage.NORMAL)

        self.update_detector(self.rtp_timestamp, self.now_ms)
        self.assertEqual(self.detector.state(), BandwidthUsage.OVERUSING)

    def test_low_gaussian_variance_fast_drift_30Kbit_3fps(self):
        packets_per_frame = 1
        frame_duration_ms = 333
        drift_per_frame_ms = 100
        sigma_ms = 3

        unique_overuse = self.run_100000_samples(packets_per_frame,
                                                 frame_duration_ms, sigma_ms)
        self.assertEqual(unique_overuse, 0)

        frames_until_overuse = self.run_until_overuse(packets_per_frame,
                                                      frame_duration_ms,
                                                      sigma_ms,
                                                      drift_per_frame_ms)
        self.assertEqual(frames_until_overuse, 4)

    def test_high_haussian_variance_30Kbit_3fps(self):
        packets_per_frame = 1
        frame_duration_ms = 333
        drift_per_frame_ms = 1
        sigma_ms = 10

        unique_overuse = self.run_100000_samples(packets_per_frame,
                                                 frame_duration_ms, sigma_ms)
        self.assertEqual(unique_overuse, 0)

        frames_until_overuse = self.run_until_overuse(packets_per_frame,
                                                      frame_duration_ms,
                                                      sigma_ms,
                                                      drift_per_frame_ms)
        self.assertEqual(frames_until_overuse, 44)

    def run_100000_samples(self, packets_per_frame, mean_ms,
                           standard_deviation_ms):
        unique_overuse = 0
        last_overuse = -1

        for i in range(100000):
            for j in range(packets_per_frame):
                self.update_detector(self.rtp_timestamp, self.receive_time_ms)
            self.rtp_timestamp += mean_ms * 90
            self.now_ms += mean_ms
            self.receive_time_ms = max(
                self.receive_time_ms,
                int(self.now_ms + random.normal(0, standard_deviation_ms) +
                    0.5),
            )

            if self.detector.state() == BandwidthUsage.OVERUSING:
                if last_overuse + 1 != i:
                    unique_overuse += 1
                last_overuse = i

        return unique_overuse

    def run_until_overuse(self, packets_per_frame, mean_ms,
                          standard_deviation_ms, drift_per_frame_ms):
        for i in range(100000):
            for j in range(packets_per_frame):
                self.update_detector(self.rtp_timestamp, self.receive_time_ms)
            self.rtp_timestamp += mean_ms * 90
            self.now_ms += mean_ms + drift_per_frame_ms
            self.receive_time_ms = max(
                self.receive_time_ms,
                int(self.now_ms + random.normal(0, standard_deviation_ms) +
                    0.5),
            )

            if self.detector.state() == BandwidthUsage.OVERUSING:
                return i + 1
        return -1

    def update_detector(self, timestamp, receive_time_ms):
        deltas = self.inter_arrival.compute_deltas(timestamp, receive_time_ms,
                                                   self.packet_size)
        if deltas is not None:
            timestamp_delta_ms = deltas.timestamp / 90
            self.estimator.update(
                deltas.arrival_time,
                timestamp_delta_ms,
                deltas.size,
                self.detector.state(),
                receive_time_ms,
            )
            self.detector.detect(
                self.estimator.offset(),
                timestamp_delta_ms,
                self.estimator.num_of_deltas(),
                receive_time_ms,
            )
예제 #4
0
class InterArrivalTest(TestCase):
    def setUp(self):
        self.inter_arrival_ast = InterArrival(
            abs_send_time(TIMESTAMP_GROUP_LENGTH_US), 1000 / (1 << 26))
        self.inter_arrival_rtp = InterArrival(
            rtp_timestamp(TIMESTAMP_GROUP_LENGTH_US), 1 / 9)

    def assertComputed(
        self,
        timestamp_us,
        arrival_time_ms,
        packet_size,
        timestamp_delta_us,
        arrival_time_delta_ms,
        packet_size_delta,
        timestamp_near=0,
    ):
        # AbsSendTime
        deltas = self.inter_arrival_ast.compute_deltas(
            abs_send_time(timestamp_us), arrival_time_ms, packet_size)
        self.assertIsNotNone(deltas)
        self.assertAlmostEqual(
            deltas.timestamp,
            abs_send_time(timestamp_delta_us),
            delta=timestamp_near << 8,
        )
        self.assertEqual(deltas.arrival_time, arrival_time_delta_ms)
        self.assertEqual(deltas.size, packet_size_delta)

        # RtpTimestamp
        deltas = self.inter_arrival_rtp.compute_deltas(
            rtp_timestamp(timestamp_us), arrival_time_ms, packet_size)
        self.assertIsNotNone(deltas)
        self.assertAlmostEqual(deltas.timestamp,
                               rtp_timestamp(timestamp_delta_us),
                               delta=timestamp_near)
        self.assertEqual(deltas.arrival_time, arrival_time_delta_ms)
        self.assertEqual(deltas.size, packet_size_delta)

    def assertNotComputed(self, timestamp_us, arrival_time_ms, packet_size):
        self.assertIsNone(
            self.inter_arrival_ast.compute_deltas(abs_send_time(timestamp_us),
                                                  arrival_time_ms,
                                                  packet_size))
        self.assertIsNone(
            self.inter_arrival_rtp.compute_deltas(rtp_timestamp(timestamp_us),
                                                  arrival_time_ms,
                                                  packet_size))

    def wrapTest(self, wrap_start_us, unorderly_within_group):
        timestamp_near = 1

        # G1
        arrival_time = 17
        self.assertNotComputed(0, arrival_time, 1)

        # G2
        arrival_time += BURST_THRESHOLD_MS + 1
        self.assertNotComputed(wrap_start_us // 4, arrival_time, 1)

        # G3
        arrival_time += BURST_THRESHOLD_MS + 1
        self.assertComputed(wrap_start_us // 2, arrival_time, 1,
                            wrap_start_us // 4, 6, 0)

        # G4
        arrival_time += BURST_THRESHOLD_MS + 1
        self.assertComputed(
            wrap_start_us // 2 + wrap_start_us // 4,
            arrival_time,
            1,
            wrap_start_us // 4,
            6,
            0,
            timestamp_near,
        )
        g4_arrival_time = arrival_time

        # G5
        arrival_time += BURST_THRESHOLD_MS + 1
        self.assertComputed(wrap_start_us, arrival_time, 2, wrap_start_us // 4,
                            6, 0, timestamp_near)
        for i in range(10):
            arrival_time += BURST_THRESHOLD_MS + 1
            if unorderly_within_group:
                self.assertNotComputed(wrap_start_us + (9 - i) * MIN_STEP_US,
                                       arrival_time, 1)
            else:
                self.assertNotComputed(wrap_start_us + i * MIN_STEP_US,
                                       arrival_time, 1)
        g5_arrival_time = arrival_time

        # out of order
        arrival_time += BURST_THRESHOLD_MS + 1
        self.assertNotComputed(wrap_start_us - 100, arrival_time, 100)

        # G6
        arrival_time += BURST_THRESHOLD_MS + 1
        self.assertComputed(
            wrap_start_us + TRIGGER_NEW_GROUP_US,
            arrival_time,
            10,
            wrap_start_us // 4 + 9 * MIN_STEP_US,
            g5_arrival_time - g4_arrival_time,
            11,
            timestamp_near,
        )
        g6_arrival_time = arrival_time

        # out of order
        arrival_time += BURST_THRESHOLD_MS + 1
        self.assertNotComputed(wrap_start_us + TIMESTAMP_GROUP_LENGTH_US,
                               arrival_time, 100)

        # G7
        arrival_time += BURST_THRESHOLD_MS + 1
        self.assertComputed(
            wrap_start_us + 2 * TRIGGER_NEW_GROUP_US,
            arrival_time,
            10,
            TRIGGER_NEW_GROUP_US - 9 * MIN_STEP_US,
            g6_arrival_time - g5_arrival_time,
            -2,
            timestamp_near,
        )

    def test_first_packet(self):
        self.assertNotComputed(0, 17, 1)

    def test_first_group(self):
        # G1
        timestamp = 0
        arrival_time = 17
        self.assertNotComputed(timestamp, arrival_time, 1)
        g1_arrival_time = arrival_time

        # G2
        timestamp += TRIGGER_NEW_GROUP_US
        arrival_time += BURST_THRESHOLD_MS + 1
        self.assertNotComputed(timestamp, arrival_time, 2)
        g2_arrival_time = arrival_time

        # G3
        timestamp += TRIGGER_NEW_GROUP_US
        arrival_time += BURST_THRESHOLD_MS + 1
        self.assertComputed(
            timestamp,
            arrival_time,
            1,
            TRIGGER_NEW_GROUP_US,
            g2_arrival_time - g1_arrival_time,
            1,
        )

    def test_second_group(self):
        # G1
        timestamp = 0
        arrival_time = 17
        self.assertNotComputed(timestamp, arrival_time, 1)
        g1_arrival_time = arrival_time

        # G2
        timestamp += TRIGGER_NEW_GROUP_US
        arrival_time += BURST_THRESHOLD_MS + 1
        self.assertNotComputed(timestamp, arrival_time, 2)
        g2_arrival_time = arrival_time

        # G3
        timestamp += TRIGGER_NEW_GROUP_US
        arrival_time += BURST_THRESHOLD_MS + 1
        self.assertComputed(
            timestamp,
            arrival_time,
            1,
            TRIGGER_NEW_GROUP_US,
            g2_arrival_time - g1_arrival_time,
            1,
        )
        g3_arrival_time = arrival_time

        # G4
        timestamp += TRIGGER_NEW_GROUP_US
        arrival_time += BURST_THRESHOLD_MS + 1
        self.assertComputed(
            timestamp,
            arrival_time,
            2,
            TRIGGER_NEW_GROUP_US,
            g3_arrival_time - g2_arrival_time,
            -1,
        )

    def test_accumulated_group(self):
        # G1
        timestamp = 0
        arrival_time = 17
        self.assertNotComputed(timestamp, arrival_time, 1)
        g1_timestamp = timestamp
        g1_arrival_time = arrival_time

        # G2
        timestamp += TRIGGER_NEW_GROUP_US
        arrival_time += BURST_THRESHOLD_MS + 1
        self.assertNotComputed(timestamp, 28, 2)
        for i in range(10):
            timestamp += MIN_STEP_US
            arrival_time += BURST_THRESHOLD_MS + 1
            self.assertNotComputed(timestamp, arrival_time, 1)
        g2_timestamp = timestamp
        g2_arrival_time = arrival_time

        # G3
        timestamp = 2 * TRIGGER_NEW_GROUP_US
        arrival_time = 500
        self.assertComputed(
            timestamp,
            arrival_time,
            100,
            g2_timestamp - g1_timestamp,
            g2_arrival_time - g1_arrival_time,
            11,
        )

    def test_out_of_order_packet(self):
        # G1
        timestamp = 0
        arrival_time = 17
        self.assertNotComputed(timestamp, arrival_time, 1)
        g1_timestamp = timestamp
        g1_arrival_time = arrival_time

        # G2
        timestamp += TRIGGER_NEW_GROUP_US
        arrival_time += 11
        self.assertNotComputed(timestamp, 28, 2)
        for i in range(10):
            timestamp += MIN_STEP_US
            arrival_time += BURST_THRESHOLD_MS + 1
            self.assertNotComputed(timestamp, arrival_time, 1)
        g2_timestamp = timestamp
        g2_arrival_time = arrival_time

        # out of order packet
        arrival_time = 281
        self.assertNotComputed(g1_timestamp, arrival_time, 1)

        # G3
        timestamp = 2 * TRIGGER_NEW_GROUP_US
        arrival_time = 500
        self.assertComputed(
            timestamp,
            arrival_time,
            100,
            g2_timestamp - g1_timestamp,
            g2_arrival_time - g1_arrival_time,
            11,
        )

    def test_out_of_order_within_group(self):
        # G1
        timestamp = 0
        arrival_time = 17
        self.assertNotComputed(timestamp, arrival_time, 1)
        g1_timestamp = timestamp
        g1_arrival_time = arrival_time

        # G2
        timestamp += TRIGGER_NEW_GROUP_US
        arrival_time += 11
        self.assertNotComputed(timestamp, 28, 2)
        timestamp += 10 * MIN_STEP_US
        g2_timestamp = timestamp
        for i in range(10):
            arrival_time += BURST_THRESHOLD_MS + 1
            self.assertNotComputed(timestamp, arrival_time, 1)
            timestamp -= MIN_STEP_US
        g2_arrival_time = arrival_time

        # out of order packet
        arrival_time = 281
        self.assertNotComputed(g1_timestamp, arrival_time, 1)

        # G3
        timestamp = 2 * TRIGGER_NEW_GROUP_US
        arrival_time = 500
        self.assertComputed(
            timestamp,
            arrival_time,
            100,
            g2_timestamp - g1_timestamp,
            g2_arrival_time - g1_arrival_time,
            11,
        )

    def test_two_bursts(self):
        # G1
        timestamp = 0
        arrival_time = 17
        self.assertNotComputed(timestamp, arrival_time, 1)
        g1_timestamp = timestamp
        g1_arrival_time = arrival_time

        # G2
        timestamp += TRIGGER_NEW_GROUP_US
        arrival_time = 100
        for i in range(10):
            timestamp += 30000
            arrival_time += BURST_THRESHOLD_MS
            self.assertNotComputed(timestamp, arrival_time, 1)
        g2_timestamp = timestamp
        g2_arrival_time = arrival_time

        # G3
        timestamp += 30000
        arrival_time += BURST_THRESHOLD_MS + 1
        self.assertComputed(
            timestamp,
            arrival_time,
            100,
            g2_timestamp - g1_timestamp,
            g2_arrival_time - g1_arrival_time,
            9,
        )

    def test_no_bursts(self):
        # G1
        timestamp = 0
        arrival_time = 17
        self.assertNotComputed(timestamp, arrival_time, 1)
        g1_timestamp = timestamp
        g1_arrival_time = arrival_time

        # G2
        timestamp += TRIGGER_NEW_GROUP_US
        arrival_time = 28
        self.assertNotComputed(timestamp, arrival_time, 2)
        g2_timestamp = timestamp
        g2_arrival_time = arrival_time

        # G3
        timestamp += 30000
        arrival_time += BURST_THRESHOLD_MS + 1
        self.assertComputed(
            timestamp,
            arrival_time,
            100,
            g2_timestamp - g1_timestamp,
            g2_arrival_time - g1_arrival_time,
            1,
        )

    def test_wrap_abs_send_time(self):
        self.wrapTest(START_ABS_SEND_TIME_WRAP_US, False)

    def test_wrap_abs_send_time_out_of_order_within_group(self):
        self.wrapTest(START_ABS_SEND_TIME_WRAP_US, True)

    def test_wrap_rtp_timestamp(self):
        self.wrapTest(START_RTP_TIMESTAMP_WRAP_US, False)

    def test_wrap_rtp_timestamp_out_of_order_within_group(self):
        self.wrapTest(START_RTP_TIMESTAMP_WRAP_US, True)