| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <stdint.h> | |
| 6 | |
| 7 #include "base/bind.h" | 5 #include "base/bind.h" |
| 8 #include "base/memory/ref_counted.h" | 6 #include "base/memory/ref_counted.h" |
| 9 #include "base/memory/scoped_ptr.h" | 7 #include "base/memory/scoped_ptr.h" |
| 10 #include "base/test/simple_test_tick_clock.h" | 8 #include "base/test/simple_test_tick_clock.h" |
| 11 #include "media/cast/audio_receiver/audio_receiver.h" | 9 #include "media/cast/audio_receiver/audio_receiver.h" |
| 12 #include "media/cast/cast_defines.h" | 10 #include "media/cast/cast_defines.h" |
| 13 #include "media/cast/cast_environment.h" | 11 #include "media/cast/cast_environment.h" |
| 14 #include "media/cast/logging/simple_event_subscriber.h" | 12 #include "media/cast/logging/simple_event_subscriber.h" |
| 15 #include "media/cast/rtcp/test_rtcp_packet_builder.h" | 13 #include "media/cast/rtcp/test_rtcp_packet_builder.h" |
| 16 #include "media/cast/test/fake_single_thread_task_runner.h" | 14 #include "media/cast/test/fake_single_thread_task_runner.h" |
| 17 #include "media/cast/transport/pacing/mock_paced_packet_sender.h" | 15 #include "media/cast/transport/pacing/mock_paced_packet_sender.h" |
| 18 #include "testing/gmock/include/gmock/gmock.h" | 16 #include "testing/gmock/include/gmock/gmock.h" |
| 19 | 17 |
| 20 namespace media { | 18 namespace media { |
| 21 namespace cast { | 19 namespace cast { |
| 22 | 20 |
| 23 static const int64 kStartMillisecond = INT64_C(12345678900000); | 21 using ::testing::_; |
| 24 | 22 |
| 25 namespace { | 23 namespace { |
| 24 |
| 25 const int64 kStartMillisecond = INT64_C(12345678900000); |
| 26 const uint32 kFirstFrameId = 1234; |
| 27 |
| 26 class FakeAudioClient { | 28 class FakeAudioClient { |
| 27 public: | 29 public: |
| 28 FakeAudioClient() : num_called_(0) {} | 30 FakeAudioClient() : num_called_(0) {} |
| 29 virtual ~FakeAudioClient() {} | 31 virtual ~FakeAudioClient() {} |
| 30 | 32 |
| 31 void SetNextExpectedResult(uint8 expected_frame_id, | 33 void SetNextExpectedResult(uint32 expected_frame_id, |
| 32 const base::TimeTicks& expected_playout_time) { | 34 const base::TimeTicks& expected_playout_time) { |
| 33 expected_frame_id_ = expected_frame_id; | 35 expected_frame_id_ = expected_frame_id; |
| 34 expected_playout_time_ = expected_playout_time; | 36 expected_playout_time_ = expected_playout_time; |
| 35 } | 37 } |
| 36 | 38 |
| 37 void DeliverEncodedAudioFrame( | 39 void DeliverEncodedAudioFrame( |
| 38 scoped_ptr<transport::EncodedAudioFrame> audio_frame, | 40 scoped_ptr<transport::EncodedAudioFrame> audio_frame, |
| 39 const base::TimeTicks& playout_time) { | 41 const base::TimeTicks& playout_time) { |
| 40 ASSERT_FALSE(!audio_frame) | 42 ASSERT_FALSE(!audio_frame) |
| 41 << "If at shutdown: There were unsatisfied requests enqueued."; | 43 << "If at shutdown: There were unsatisfied requests enqueued."; |
| 42 EXPECT_EQ(expected_frame_id_, audio_frame->frame_id); | 44 EXPECT_EQ(expected_frame_id_, audio_frame->frame_id); |
| 43 EXPECT_EQ(transport::kPcm16, audio_frame->codec); | 45 EXPECT_EQ(transport::kPcm16, audio_frame->codec); |
| 44 EXPECT_EQ(expected_playout_time_, playout_time); | 46 EXPECT_EQ(expected_playout_time_, playout_time); |
| 45 num_called_++; | 47 num_called_++; |
| 46 } | 48 } |
| 47 | 49 |
| 48 int number_times_called() const { return num_called_; } | 50 int number_times_called() const { return num_called_; } |
| 49 | 51 |
| 50 private: | 52 private: |
| 51 int num_called_; | 53 int num_called_; |
| 52 uint8 expected_frame_id_; | 54 uint32 expected_frame_id_; |
| 53 base::TimeTicks expected_playout_time_; | 55 base::TimeTicks expected_playout_time_; |
| 54 | 56 |
| 55 DISALLOW_COPY_AND_ASSIGN(FakeAudioClient); | 57 DISALLOW_COPY_AND_ASSIGN(FakeAudioClient); |
| 56 }; | 58 }; |
| 59 |
| 57 } // namespace | 60 } // namespace |
| 58 | 61 |
| 59 class AudioReceiverTest : public ::testing::Test { | 62 class AudioReceiverTest : public ::testing::Test { |
| 60 protected: | 63 protected: |
| 61 AudioReceiverTest() { | 64 AudioReceiverTest() { |
| 62 // Configure the audio receiver to use PCM16. | 65 // Configure the audio receiver to use PCM16. |
| 63 audio_config_.rtp_payload_type = 127; | 66 audio_config_.rtp_payload_type = 127; |
| 64 audio_config_.frequency = 16000; | 67 audio_config_.frequency = 16000; |
| 65 audio_config_.channels = 1; | 68 audio_config_.channels = 1; |
| 66 audio_config_.codec = transport::kPcm16; | 69 audio_config_.codec = transport::kPcm16; |
| 67 audio_config_.use_external_decoder = false; | 70 audio_config_.use_external_decoder = true; |
| 68 audio_config_.feedback_ssrc = 1234; | 71 audio_config_.feedback_ssrc = 1234; |
| 69 testing_clock_ = new base::SimpleTestTickClock(); | 72 testing_clock_ = new base::SimpleTestTickClock(); |
| 70 testing_clock_->Advance( | 73 testing_clock_->Advance( |
| 71 base::TimeDelta::FromMilliseconds(kStartMillisecond)); | 74 base::TimeDelta::FromMilliseconds(kStartMillisecond)); |
| 72 task_runner_ = new test::FakeSingleThreadTaskRunner(testing_clock_); | 75 task_runner_ = new test::FakeSingleThreadTaskRunner(testing_clock_); |
| 73 | 76 |
| 74 cast_environment_ = new CastEnvironment( | 77 cast_environment_ = new CastEnvironment( |
| 75 scoped_ptr<base::TickClock>(testing_clock_).Pass(), | 78 scoped_ptr<base::TickClock>(testing_clock_).Pass(), |
| 76 task_runner_, | 79 task_runner_, |
| 77 task_runner_, | 80 task_runner_, |
| 78 task_runner_); | 81 task_runner_); |
| 79 } | |
| 80 | 82 |
| 81 void Configure(bool use_external_decoder) { | |
| 82 audio_config_.use_external_decoder = use_external_decoder; | |
| 83 receiver_.reset(new AudioReceiver(cast_environment_, audio_config_, | 83 receiver_.reset(new AudioReceiver(cast_environment_, audio_config_, |
| 84 &mock_transport_)); | 84 &mock_transport_)); |
| 85 } | 85 } |
| 86 | 86 |
| 87 virtual ~AudioReceiverTest() {} | 87 virtual ~AudioReceiverTest() {} |
| 88 | 88 |
| 89 virtual void SetUp() { | 89 virtual void SetUp() { |
| 90 payload_.assign(kMaxIpPacketSize, 0); | 90 payload_.assign(kMaxIpPacketSize, 0); |
| 91 rtp_header_.is_key_frame = true; | 91 rtp_header_.is_key_frame = true; |
| 92 rtp_header_.frame_id = 0; | 92 rtp_header_.frame_id = kFirstFrameId; |
| 93 rtp_header_.packet_id = 0; | 93 rtp_header_.packet_id = 0; |
| 94 rtp_header_.max_packet_id = 0; | 94 rtp_header_.max_packet_id = 0; |
| 95 rtp_header_.is_reference = false; | 95 rtp_header_.is_reference = false; |
| 96 rtp_header_.reference_frame_id = 0; | 96 rtp_header_.reference_frame_id = 0; |
| 97 rtp_header_.webrtc.header.timestamp = 0; | 97 rtp_header_.webrtc.header.timestamp = 0; |
| 98 } | 98 } |
| 99 | 99 |
| 100 void FeedOneFrameIntoReceiver() { | 100 void FeedOneFrameIntoReceiver() { |
| 101 receiver_->OnReceivedPayloadData( | 101 receiver_->OnReceivedPayloadData( |
| 102 payload_.data(), payload_.size(), rtp_header_); | 102 payload_.data(), payload_.size(), rtp_header_); |
| 103 } | 103 } |
| 104 | 104 |
| 105 AudioReceiverConfig audio_config_; | 105 AudioReceiverConfig audio_config_; |
| 106 std::vector<uint8> payload_; | 106 std::vector<uint8> payload_; |
| 107 RtpCastHeader rtp_header_; | 107 RtpCastHeader rtp_header_; |
| 108 base::SimpleTestTickClock* testing_clock_; // Owned by CastEnvironment. | 108 base::SimpleTestTickClock* testing_clock_; // Owned by CastEnvironment. |
| 109 transport::MockPacedPacketSender mock_transport_; | 109 transport::MockPacedPacketSender mock_transport_; |
| 110 scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_; | 110 scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_; |
| 111 scoped_refptr<CastEnvironment> cast_environment_; | 111 scoped_refptr<CastEnvironment> cast_environment_; |
| 112 FakeAudioClient fake_audio_client_; | 112 FakeAudioClient fake_audio_client_; |
| 113 | 113 |
| 114 // Important for the AudioReceiver to be declared last, since its dependencies | 114 // Important for the AudioReceiver to be declared last, since its dependencies |
| 115 // must remain alive until after its destruction. | 115 // must remain alive until after its destruction. |
| 116 scoped_ptr<AudioReceiver> receiver_; | 116 scoped_ptr<AudioReceiver> receiver_; |
| 117 }; | 117 }; |
| 118 | 118 |
| 119 TEST_F(AudioReceiverTest, GetOnePacketEncodedframe) { | 119 TEST_F(AudioReceiverTest, GetOnePacketEncodedFrame) { |
| 120 SimpleEventSubscriber event_subscriber; | 120 SimpleEventSubscriber event_subscriber; |
| 121 cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber); | 121 cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber); |
| 122 | 122 |
| 123 Configure(true); | 123 EXPECT_CALL(mock_transport_, SendRtcpPacket(_)).Times(1); |
| 124 EXPECT_CALL(mock_transport_, SendRtcpPacket(testing::_)).Times(1); | |
| 125 | 124 |
| 126 // Enqueue a request for an audio frame. | 125 // Enqueue a request for an audio frame. |
| 127 receiver_->GetEncodedAudioFrame( | 126 receiver_->GetEncodedAudioFrame( |
| 128 base::Bind(&FakeAudioClient::DeliverEncodedAudioFrame, | 127 base::Bind(&FakeAudioClient::DeliverEncodedAudioFrame, |
| 129 base::Unretained(&fake_audio_client_))); | 128 base::Unretained(&fake_audio_client_))); |
| 130 | 129 |
| 131 // The request should not be satisfied since no packets have been received. | 130 // The request should not be satisfied since no packets have been received. |
| 132 task_runner_->RunTasks(); | 131 task_runner_->RunTasks(); |
| 133 EXPECT_EQ(0, fake_audio_client_.number_times_called()); | 132 EXPECT_EQ(0, fake_audio_client_.number_times_called()); |
| 134 | 133 |
| 135 // Deliver one audio frame to the receiver and expect to get one frame back. | 134 // Deliver one audio frame to the receiver and expect to get one frame back. |
| 136 fake_audio_client_.SetNextExpectedResult(0, testing_clock_->NowTicks()); | 135 fake_audio_client_.SetNextExpectedResult(kFirstFrameId, |
| 136 testing_clock_->NowTicks()); |
| 137 FeedOneFrameIntoReceiver(); | 137 FeedOneFrameIntoReceiver(); |
| 138 task_runner_->RunTasks(); | 138 task_runner_->RunTasks(); |
| 139 EXPECT_EQ(1, fake_audio_client_.number_times_called()); | 139 EXPECT_EQ(1, fake_audio_client_.number_times_called()); |
| 140 | 140 |
| 141 std::vector<FrameEvent> frame_events; | 141 std::vector<FrameEvent> frame_events; |
| 142 event_subscriber.GetFrameEventsAndReset(&frame_events); | 142 event_subscriber.GetFrameEventsAndReset(&frame_events); |
| 143 | 143 |
| 144 ASSERT_TRUE(!frame_events.empty()); | 144 ASSERT_TRUE(!frame_events.empty()); |
| 145 EXPECT_EQ(kAudioAckSent, frame_events.begin()->type); | 145 EXPECT_EQ(kAudioAckSent, frame_events.begin()->type); |
| 146 EXPECT_EQ(rtp_header_.frame_id, frame_events.begin()->frame_id); | 146 EXPECT_EQ(rtp_header_.frame_id, frame_events.begin()->frame_id); |
| 147 EXPECT_EQ(rtp_header_.webrtc.header.timestamp, | 147 EXPECT_EQ(rtp_header_.webrtc.header.timestamp, |
| 148 frame_events.begin()->rtp_timestamp); | 148 frame_events.begin()->rtp_timestamp); |
| 149 | 149 |
| 150 cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber); | 150 cast_environment_->Logging()->RemoveRawEventSubscriber(&event_subscriber); |
| 151 } | 151 } |
| 152 | 152 |
| 153 TEST_F(AudioReceiverTest, MultiplePendingGetCalls) { | 153 TEST_F(AudioReceiverTest, MultiplePendingGetCalls) { |
| 154 Configure(true); | 154 EXPECT_CALL(mock_transport_, SendRtcpPacket(_)) |
| 155 EXPECT_CALL(mock_transport_, SendRtcpPacket(testing::_)) | |
| 156 .WillRepeatedly(testing::Return(true)); | 155 .WillRepeatedly(testing::Return(true)); |
| 157 | 156 |
| 158 // Enqueue a request for an audio frame. | 157 // Enqueue a request for an audio frame. |
| 159 const AudioFrameEncodedCallback frame_encoded_callback = | 158 const AudioFrameEncodedCallback frame_encoded_callback = |
| 160 base::Bind(&FakeAudioClient::DeliverEncodedAudioFrame, | 159 base::Bind(&FakeAudioClient::DeliverEncodedAudioFrame, |
| 161 base::Unretained(&fake_audio_client_)); | 160 base::Unretained(&fake_audio_client_)); |
| 162 receiver_->GetEncodedAudioFrame(frame_encoded_callback); | 161 receiver_->GetEncodedAudioFrame(frame_encoded_callback); |
| 163 task_runner_->RunTasks(); | 162 task_runner_->RunTasks(); |
| 164 EXPECT_EQ(0, fake_audio_client_.number_times_called()); | 163 EXPECT_EQ(0, fake_audio_client_.number_times_called()); |
| 165 | 164 |
| 166 // Receive one audio frame and expect to see the first request satisfied. | 165 // Receive one audio frame and expect to see the first request satisfied. |
| 167 fake_audio_client_.SetNextExpectedResult(0, testing_clock_->NowTicks()); | 166 fake_audio_client_.SetNextExpectedResult(kFirstFrameId, |
| 167 testing_clock_->NowTicks()); |
| 168 FeedOneFrameIntoReceiver(); | 168 FeedOneFrameIntoReceiver(); |
| 169 task_runner_->RunTasks(); | 169 task_runner_->RunTasks(); |
| 170 EXPECT_EQ(1, fake_audio_client_.number_times_called()); | 170 EXPECT_EQ(1, fake_audio_client_.number_times_called()); |
| 171 | 171 |
| 172 TestRtcpPacketBuilder rtcp_packet; | 172 TestRtcpPacketBuilder rtcp_packet; |
| 173 | 173 |
| 174 uint32 ntp_high; | 174 uint32 ntp_high; |
| 175 uint32 ntp_low; | 175 uint32 ntp_low; |
| 176 ConvertTimeTicksToNtp(testing_clock_->NowTicks(), &ntp_high, &ntp_low); | 176 ConvertTimeTicksToNtp(testing_clock_->NowTicks(), &ntp_high, &ntp_low); |
| 177 rtcp_packet.AddSrWithNtp(audio_config_.feedback_ssrc, ntp_high, ntp_low, | 177 rtcp_packet.AddSrWithNtp(audio_config_.feedback_ssrc, ntp_high, ntp_low, |
| 178 rtp_header_.webrtc.header.timestamp); | 178 rtp_header_.webrtc.header.timestamp); |
| 179 | 179 |
| 180 testing_clock_->Advance(base::TimeDelta::FromMilliseconds(20)); | 180 testing_clock_->Advance(base::TimeDelta::FromMilliseconds(20)); |
| 181 | 181 |
| 182 receiver_->IncomingPacket(rtcp_packet.GetPacket().Pass()); | 182 receiver_->IncomingPacket(rtcp_packet.GetPacket().Pass()); |
| 183 | 183 |
| 184 // Enqueue a second request for an audio frame, but it should not be | 184 // Enqueue a second request for an audio frame, but it should not be |
| 185 // fulfilled yet. | 185 // fulfilled yet. |
| 186 receiver_->GetEncodedAudioFrame(frame_encoded_callback); | 186 receiver_->GetEncodedAudioFrame(frame_encoded_callback); |
| 187 task_runner_->RunTasks(); | 187 task_runner_->RunTasks(); |
| 188 EXPECT_EQ(1, fake_audio_client_.number_times_called()); | 188 EXPECT_EQ(1, fake_audio_client_.number_times_called()); |
| 189 | 189 |
| 190 // Receive one audio frame out-of-order: Make sure that we are not continuous | 190 // Receive one audio frame out-of-order: Make sure that we are not continuous |
| 191 // and that the RTP timestamp represents a time in the future. | 191 // and that the RTP timestamp represents a time in the future. |
| 192 rtp_header_.is_key_frame = false; | 192 rtp_header_.is_key_frame = false; |
| 193 rtp_header_.frame_id = 2; | 193 rtp_header_.frame_id = kFirstFrameId + 2; |
| 194 rtp_header_.is_reference = true; | 194 rtp_header_.is_reference = true; |
| 195 rtp_header_.reference_frame_id = 0; | 195 rtp_header_.reference_frame_id = 0; |
| 196 rtp_header_.webrtc.header.timestamp = 960; | 196 rtp_header_.webrtc.header.timestamp = 960; |
| 197 fake_audio_client_.SetNextExpectedResult( | 197 fake_audio_client_.SetNextExpectedResult( |
| 198 2, testing_clock_->NowTicks() + base::TimeDelta::FromMilliseconds(100)); | 198 kFirstFrameId + 2, |
| 199 testing_clock_->NowTicks() + base::TimeDelta::FromMilliseconds(100)); |
| 199 FeedOneFrameIntoReceiver(); | 200 FeedOneFrameIntoReceiver(); |
| 200 | 201 |
| 201 // Frame 2 should not come out at this point in time. | 202 // Frame 2 should not come out at this point in time. |
| 202 task_runner_->RunTasks(); | 203 task_runner_->RunTasks(); |
| 203 EXPECT_EQ(1, fake_audio_client_.number_times_called()); | 204 EXPECT_EQ(1, fake_audio_client_.number_times_called()); |
| 204 | 205 |
| 205 // Enqueue a third request for an audio frame. | 206 // Enqueue a third request for an audio frame. |
| 206 receiver_->GetEncodedAudioFrame(frame_encoded_callback); | 207 receiver_->GetEncodedAudioFrame(frame_encoded_callback); |
| 207 task_runner_->RunTasks(); | 208 task_runner_->RunTasks(); |
| 208 EXPECT_EQ(1, fake_audio_client_.number_times_called()); | 209 EXPECT_EQ(1, fake_audio_client_.number_times_called()); |
| 209 | 210 |
| 210 // After 100 ms has elapsed, Frame 2 is emitted (to satisfy the second | 211 // After 100 ms has elapsed, Frame 2 is emitted (to satisfy the second |
| 211 // request) because a decision was made to skip over the no-show Frame 1. | 212 // request) because a decision was made to skip over the no-show Frame 1. |
| 212 testing_clock_->Advance(base::TimeDelta::FromMilliseconds(100)); | 213 testing_clock_->Advance(base::TimeDelta::FromMilliseconds(100)); |
| 213 task_runner_->RunTasks(); | 214 task_runner_->RunTasks(); |
| 214 EXPECT_EQ(2, fake_audio_client_.number_times_called()); | 215 EXPECT_EQ(2, fake_audio_client_.number_times_called()); |
| 215 | 216 |
| 216 // Receive Frame 3 and expect it to fulfill the third request immediately. | 217 // Receive Frame 3 and expect it to fulfill the third request immediately. |
| 217 rtp_header_.frame_id = 3; | 218 rtp_header_.frame_id = kFirstFrameId + 3; |
| 218 rtp_header_.is_reference = false; | 219 rtp_header_.is_reference = false; |
| 219 rtp_header_.reference_frame_id = 0; | 220 rtp_header_.reference_frame_id = 0; |
| 220 rtp_header_.webrtc.header.timestamp = 1280; | 221 rtp_header_.webrtc.header.timestamp = 1280; |
| 221 fake_audio_client_.SetNextExpectedResult(3, testing_clock_->NowTicks()); | 222 fake_audio_client_.SetNextExpectedResult(kFirstFrameId + 3, |
| 223 testing_clock_->NowTicks()); |
| 222 FeedOneFrameIntoReceiver(); | 224 FeedOneFrameIntoReceiver(); |
| 223 task_runner_->RunTasks(); | 225 task_runner_->RunTasks(); |
| 224 EXPECT_EQ(3, fake_audio_client_.number_times_called()); | 226 EXPECT_EQ(3, fake_audio_client_.number_times_called()); |
| 225 | 227 |
| 226 // Move forward another 100 ms and run any pending tasks (there should be | 228 // Move forward another 100 ms and run any pending tasks (there should be |
| 227 // none). Expect no additional frames where emitted. | 229 // none). Expect no additional frames where emitted. |
| 228 testing_clock_->Advance(base::TimeDelta::FromMilliseconds(100)); | 230 testing_clock_->Advance(base::TimeDelta::FromMilliseconds(100)); |
| 229 task_runner_->RunTasks(); | 231 task_runner_->RunTasks(); |
| 230 EXPECT_EQ(3, fake_audio_client_.number_times_called()); | 232 EXPECT_EQ(3, fake_audio_client_.number_times_called()); |
| 231 } | 233 } |
| 232 | 234 |
| 233 } // namespace cast | 235 } // namespace cast |
| 234 } // namespace media | 236 } // namespace media |
| OLD | NEW |