| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <stdint.h> |
| |
| #include <vector> |
| |
| #include "base/rand_util.h" |
| #include "base/test/simple_test_tick_clock.h" |
| #include "base/time/tick_clock.h" |
| #include "base/time/time.h" |
| #include "media/cast/logging/logging_defines.h" |
| #include "media/cast/logging/logging_impl.h" |
| #include "media/cast/logging/simple_event_subscriber.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace media { |
| namespace cast { |
| |
| // Insert frame duration- one second. |
| const int64 kIntervalTime1S = 1; |
| // Test frame rate goal - 30fps. |
| const int kFrameIntervalMs = 33; |
| |
| static const int64 kStartMillisecond = INT64_C(12345678900000); |
| |
| class LoggingImplTest : public ::testing::Test { |
| protected: |
| LoggingImplTest() { |
| testing_clock_.Advance( |
| base::TimeDelta::FromMilliseconds(kStartMillisecond)); |
| logging_.AddRawEventSubscriber(&event_subscriber_); |
| } |
| |
| virtual ~LoggingImplTest() { |
| logging_.RemoveRawEventSubscriber(&event_subscriber_); |
| } |
| |
| LoggingImpl logging_; |
| base::SimpleTestTickClock testing_clock_; |
| SimpleEventSubscriber event_subscriber_; |
| |
| DISALLOW_COPY_AND_ASSIGN(LoggingImplTest); |
| }; |
| |
| TEST_F(LoggingImplTest, BasicFrameLogging) { |
| base::TimeTicks start_time = testing_clock_.NowTicks(); |
| base::TimeDelta time_interval = testing_clock_.NowTicks() - start_time; |
| uint32 rtp_timestamp = 0; |
| uint32 frame_id = 0; |
| base::TimeTicks now; |
| do { |
| now = testing_clock_.NowTicks(); |
| logging_.InsertFrameEvent( |
| now, FRAME_CAPTURE_BEGIN, VIDEO_EVENT, rtp_timestamp, frame_id); |
| testing_clock_.Advance( |
| base::TimeDelta::FromMilliseconds(kFrameIntervalMs)); |
| rtp_timestamp += kFrameIntervalMs * 90; |
| ++frame_id; |
| time_interval = now - start_time; |
| } while (time_interval.InSeconds() < kIntervalTime1S); |
| |
| // Get logging data. |
| std::vector<FrameEvent> frame_events; |
| event_subscriber_.GetFrameEventsAndReset(&frame_events); |
| // Size of vector should be equal to the number of events logged, |
| // which equals to number of frames in this case. |
| EXPECT_EQ(frame_id, frame_events.size()); |
| } |
| |
| TEST_F(LoggingImplTest, FrameLoggingWithSize) { |
| // Average packet size. |
| const int kBaseFrameSizeBytes = 25000; |
| const int kRandomSizeInterval = 100; |
| base::TimeTicks start_time = testing_clock_.NowTicks(); |
| base::TimeDelta time_interval = testing_clock_.NowTicks() - start_time; |
| uint32 rtp_timestamp = 0; |
| uint32 frame_id = 0; |
| size_t sum_size = 0; |
| int target_bitrate = 1234; |
| do { |
| int size = kBaseFrameSizeBytes + |
| base::RandInt(-kRandomSizeInterval, kRandomSizeInterval); |
| sum_size += static_cast<size_t>(size); |
| logging_.InsertEncodedFrameEvent(testing_clock_.NowTicks(), |
| FRAME_ENCODED, VIDEO_EVENT, rtp_timestamp, |
| frame_id, size, true, target_bitrate); |
| testing_clock_.Advance(base::TimeDelta::FromMilliseconds(kFrameIntervalMs)); |
| rtp_timestamp += kFrameIntervalMs * 90; |
| ++frame_id; |
| time_interval = testing_clock_.NowTicks() - start_time; |
| } while (time_interval.InSeconds() < kIntervalTime1S); |
| // Get logging data. |
| std::vector<FrameEvent> frame_events; |
| event_subscriber_.GetFrameEventsAndReset(&frame_events); |
| // Size of vector should be equal to the number of events logged, which |
| // equals to number of frames in this case. |
| EXPECT_EQ(frame_id, frame_events.size()); |
| } |
| |
| TEST_F(LoggingImplTest, FrameLoggingWithDelay) { |
| // Average packet size. |
| const int kPlayoutDelayMs = 50; |
| const int kRandomSizeInterval = 20; |
| base::TimeTicks start_time = testing_clock_.NowTicks(); |
| base::TimeDelta time_interval = testing_clock_.NowTicks() - start_time; |
| uint32 rtp_timestamp = 0; |
| uint32 frame_id = 0; |
| do { |
| int delay = kPlayoutDelayMs + |
| base::RandInt(-kRandomSizeInterval, kRandomSizeInterval); |
| logging_.InsertFrameEventWithDelay( |
| testing_clock_.NowTicks(), |
| FRAME_CAPTURE_BEGIN, |
| VIDEO_EVENT, |
| rtp_timestamp, |
| frame_id, |
| base::TimeDelta::FromMilliseconds(delay)); |
| testing_clock_.Advance(base::TimeDelta::FromMilliseconds(kFrameIntervalMs)); |
| rtp_timestamp += kFrameIntervalMs * 90; |
| ++frame_id; |
| time_interval = testing_clock_.NowTicks() - start_time; |
| } while (time_interval.InSeconds() < kIntervalTime1S); |
| // Get logging data. |
| std::vector<FrameEvent> frame_events; |
| event_subscriber_.GetFrameEventsAndReset(&frame_events); |
| // Size of vector should be equal to the number of frames logged. |
| EXPECT_EQ(frame_id, frame_events.size()); |
| } |
| |
| TEST_F(LoggingImplTest, MultipleEventFrameLogging) { |
| base::TimeTicks start_time = testing_clock_.NowTicks(); |
| base::TimeDelta time_interval = testing_clock_.NowTicks() - start_time; |
| uint32 rtp_timestamp = 0u; |
| uint32 frame_id = 0u; |
| uint32 num_events = 0u; |
| do { |
| logging_.InsertFrameEvent(testing_clock_.NowTicks(), |
| FRAME_CAPTURE_END, |
| VIDEO_EVENT, |
| rtp_timestamp, |
| frame_id); |
| ++num_events; |
| if (frame_id % 2) { |
| logging_.InsertEncodedFrameEvent(testing_clock_.NowTicks(), |
| FRAME_ENCODED, AUDIO_EVENT, |
| rtp_timestamp, |
| frame_id, 1500, true, 0); |
| } else if (frame_id % 3) { |
| logging_.InsertFrameEvent(testing_clock_.NowTicks(), FRAME_DECODED, |
| VIDEO_EVENT, rtp_timestamp, frame_id); |
| } else { |
| logging_.InsertFrameEventWithDelay( |
| testing_clock_.NowTicks(), FRAME_PLAYOUT, VIDEO_EVENT, |
| rtp_timestamp, frame_id, base::TimeDelta::FromMilliseconds(20)); |
| } |
| ++num_events; |
| |
| testing_clock_.Advance(base::TimeDelta::FromMilliseconds(kFrameIntervalMs)); |
| rtp_timestamp += kFrameIntervalMs * 90; |
| ++frame_id; |
| time_interval = testing_clock_.NowTicks() - start_time; |
| } while (time_interval.InSeconds() < kIntervalTime1S); |
| // Get logging data. |
| std::vector<FrameEvent> frame_events; |
| event_subscriber_.GetFrameEventsAndReset(&frame_events); |
| // Size of vector should be equal to the number of frames logged. |
| EXPECT_EQ(num_events, frame_events.size()); |
| // Multiple events captured per frame. |
| } |
| |
| TEST_F(LoggingImplTest, PacketLogging) { |
| const int kNumPacketsPerFrame = 10; |
| const int kBaseSize = 2500; |
| const int kSizeInterval = 100; |
| base::TimeTicks start_time = testing_clock_.NowTicks(); |
| base::TimeTicks latest_time; |
| base::TimeDelta time_interval = testing_clock_.NowTicks() - start_time; |
| RtpTimestamp rtp_timestamp = 0; |
| int frame_id = 0; |
| int num_packets = 0; |
| int sum_size = 0u; |
| do { |
| for (int i = 0; i < kNumPacketsPerFrame; ++i) { |
| int size = kBaseSize + base::RandInt(-kSizeInterval, kSizeInterval); |
| sum_size += size; |
| latest_time = testing_clock_.NowTicks(); |
| ++num_packets; |
| logging_.InsertPacketEvent(latest_time, |
| PACKET_RECEIVED, |
| VIDEO_EVENT, |
| rtp_timestamp, |
| frame_id, |
| i, |
| kNumPacketsPerFrame, |
| size); |
| } |
| testing_clock_.Advance(base::TimeDelta::FromMilliseconds(kFrameIntervalMs)); |
| rtp_timestamp += kFrameIntervalMs * 90; |
| ++frame_id; |
| time_interval = testing_clock_.NowTicks() - start_time; |
| } while (time_interval.InSeconds() < kIntervalTime1S); |
| // Get logging data. |
| std::vector<PacketEvent> packet_events; |
| event_subscriber_.GetPacketEventsAndReset(&packet_events); |
| // Size of vector should be equal to the number of packets logged. |
| EXPECT_EQ(num_packets, static_cast<int>(packet_events.size())); |
| } |
| |
| TEST_F(LoggingImplTest, MultipleRawEventSubscribers) { |
| SimpleEventSubscriber event_subscriber_2; |
| |
| // Now logging_ has two subscribers. |
| logging_.AddRawEventSubscriber(&event_subscriber_2); |
| |
| logging_.InsertFrameEvent(testing_clock_.NowTicks(), |
| FRAME_CAPTURE_BEGIN, |
| VIDEO_EVENT, |
| /*rtp_timestamp*/ 0u, |
| /*frame_id*/ 0u); |
| |
| std::vector<FrameEvent> frame_events; |
| event_subscriber_.GetFrameEventsAndReset(&frame_events); |
| EXPECT_EQ(1u, frame_events.size()); |
| frame_events.clear(); |
| event_subscriber_2.GetFrameEventsAndReset(&frame_events); |
| EXPECT_EQ(1u, frame_events.size()); |
| |
| logging_.RemoveRawEventSubscriber(&event_subscriber_2); |
| } |
| |
| } // namespace cast |
| } // namespace media |