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 3// found in the LICENSE file. 4 5#include "base/bind.h" 6#include "base/memory/ref_counted.h" 7#include "base/memory/scoped_ptr.h" 8#include "base/test/simple_test_tick_clock.h" 9#include "media/cast/audio_receiver/audio_receiver.h" 10#include "media/cast/cast_defines.h" 11#include "media/cast/cast_environment.h" 12#include "media/cast/net/pacing/mock_paced_packet_sender.h" 13#include "media/cast/rtcp/test_rtcp_packet_builder.h" 14#include "media/cast/test/fake_task_runner.h" 15#include "testing/gmock/include/gmock/gmock.h" 16 17namespace media { 18namespace cast { 19 20static const int64 kStartMillisecond = GG_INT64_C(12345678900000); 21 22namespace { 23class TestAudioEncoderCallback : 24 public base::RefCountedThreadSafe<TestAudioEncoderCallback> { 25 public: 26 TestAudioEncoderCallback() 27 : num_called_(0) {} 28 29 void SetExpectedResult(uint8 expected_frame_id, 30 const base::TimeTicks& expected_playout_time) { 31 expected_frame_id_ = expected_frame_id; 32 expected_playout_time_ = expected_playout_time; 33 } 34 35 void DeliverEncodedAudioFrame(scoped_ptr<EncodedAudioFrame> audio_frame, 36 const base::TimeTicks& playout_time) { 37 EXPECT_EQ(expected_frame_id_, audio_frame->frame_id); 38 EXPECT_EQ(kPcm16, audio_frame->codec); 39 EXPECT_EQ(expected_playout_time_, playout_time); 40 num_called_++; 41 } 42 43 int number_times_called() const { return num_called_;} 44 45 protected: 46 virtual ~TestAudioEncoderCallback() {} 47 48 private: 49 friend class base::RefCountedThreadSafe<TestAudioEncoderCallback>; 50 51 int num_called_; 52 uint8 expected_frame_id_; 53 base::TimeTicks expected_playout_time_; 54}; 55} // namespace 56 57class PeerAudioReceiver : public AudioReceiver { 58 public: 59 PeerAudioReceiver(scoped_refptr<CastEnvironment> cast_environment, 60 const AudioReceiverConfig& audio_config, 61 PacedPacketSender* const packet_sender) 62 : AudioReceiver(cast_environment, audio_config, packet_sender) {} 63 64 using AudioReceiver::IncomingParsedRtpPacket; 65}; 66 67class AudioReceiverTest : public ::testing::Test { 68 protected: 69 AudioReceiverTest() { 70 // Configure the audio receiver to use PCM16. 71 audio_config_.rtp_payload_type = 127; 72 audio_config_.frequency = 16000; 73 audio_config_.channels = 1; 74 audio_config_.codec = kPcm16; 75 audio_config_.use_external_decoder = false; 76 audio_config_.feedback_ssrc = 1234; 77 testing_clock_.Advance( 78 base::TimeDelta::FromMilliseconds(kStartMillisecond)); 79 task_runner_ = new test::FakeTaskRunner(&testing_clock_); 80 cast_environment_ = new CastEnvironment(&testing_clock_, task_runner_, 81 task_runner_, task_runner_, task_runner_, task_runner_, 82 GetDefaultCastLoggingConfig()); 83 test_audio_encoder_callback_ = new TestAudioEncoderCallback(); 84 } 85 86 void Configure(bool use_external_decoder) { 87 audio_config_.use_external_decoder = use_external_decoder; 88 receiver_.reset(new PeerAudioReceiver(cast_environment_, audio_config_, 89 &mock_transport_)); 90 } 91 92 virtual ~AudioReceiverTest() {} 93 94 static void DummyDeletePacket(const uint8* packet) {}; 95 96 virtual void SetUp() { 97 payload_.assign(kIpPacketSize, 0); 98 rtp_header_.is_key_frame = true; 99 rtp_header_.frame_id = 0; 100 rtp_header_.packet_id = 0; 101 rtp_header_.max_packet_id = 0; 102 rtp_header_.is_reference = false; 103 rtp_header_.reference_frame_id = 0; 104 rtp_header_.webrtc.header.timestamp = 0; 105 } 106 107 AudioReceiverConfig audio_config_; 108 std::vector<uint8> payload_; 109 RtpCastHeader rtp_header_; 110 base::SimpleTestTickClock testing_clock_; 111 MockPacedPacketSender mock_transport_; 112 scoped_refptr<test::FakeTaskRunner> task_runner_; 113 scoped_ptr<PeerAudioReceiver> receiver_; 114 scoped_refptr<CastEnvironment> cast_environment_; 115 scoped_refptr<TestAudioEncoderCallback> test_audio_encoder_callback_; 116}; 117 118TEST_F(AudioReceiverTest, GetOnePacketEncodedframe) { 119 Configure(true); 120 EXPECT_CALL(mock_transport_, SendRtcpPacket(testing::_)).Times(1); 121 122 receiver_->IncomingParsedRtpPacket(payload_.data(), 123 payload_.size(), rtp_header_); 124 EncodedAudioFrame audio_frame; 125 base::TimeTicks playout_time; 126 test_audio_encoder_callback_->SetExpectedResult(0, testing_clock_.NowTicks()); 127 128 AudioFrameEncodedCallback frame_encoded_callback = 129 base::Bind(&TestAudioEncoderCallback::DeliverEncodedAudioFrame, 130 test_audio_encoder_callback_.get()); 131 132 receiver_->GetEncodedAudioFrame(frame_encoded_callback); 133 task_runner_->RunTasks(); 134 EXPECT_EQ(1, test_audio_encoder_callback_->number_times_called()); 135} 136 137TEST_F(AudioReceiverTest, MultiplePendingGetCalls) { 138 Configure(true); 139 EXPECT_CALL(mock_transport_, SendRtcpPacket(testing::_)).WillRepeatedly( 140 testing::Return(true)); 141 142 AudioFrameEncodedCallback frame_encoded_callback = 143 base::Bind(&TestAudioEncoderCallback::DeliverEncodedAudioFrame, 144 test_audio_encoder_callback_.get()); 145 146 receiver_->GetEncodedAudioFrame(frame_encoded_callback); 147 148 receiver_->IncomingParsedRtpPacket(payload_.data(), payload_.size(), 149 rtp_header_); 150 151 EncodedAudioFrame audio_frame; 152 base::TimeTicks playout_time; 153 test_audio_encoder_callback_->SetExpectedResult(0, testing_clock_.NowTicks()); 154 155 task_runner_->RunTasks(); 156 EXPECT_EQ(1, test_audio_encoder_callback_->number_times_called()); 157 158 TestRtcpPacketBuilder rtcp_packet; 159 160 uint32 ntp_high; 161 uint32 ntp_low; 162 ConvertTimeTicksToNtp(testing_clock_.NowTicks(), &ntp_high, &ntp_low); 163 rtcp_packet.AddSrWithNtp(audio_config_.feedback_ssrc, ntp_high, ntp_low, 164 rtp_header_.webrtc.header.timestamp); 165 166 testing_clock_.Advance(base::TimeDelta::FromMilliseconds(20)); 167 168 receiver_->IncomingPacket(rtcp_packet.Packet(), rtcp_packet.Length(), 169 base::Bind(AudioReceiverTest::DummyDeletePacket, rtcp_packet.Packet())); 170 171 // Make sure that we are not continuous and that the RTP timestamp represent a 172 // time in the future. 173 rtp_header_.is_key_frame = false; 174 rtp_header_.frame_id = 2; 175 rtp_header_.is_reference = true; 176 rtp_header_.reference_frame_id = 0; 177 rtp_header_.webrtc.header.timestamp = 960; 178 test_audio_encoder_callback_->SetExpectedResult(2, 179 testing_clock_.NowTicks() + base::TimeDelta::FromMilliseconds(100)); 180 181 receiver_->IncomingParsedRtpPacket(payload_.data(), payload_.size(), 182 rtp_header_); 183 receiver_->GetEncodedAudioFrame(frame_encoded_callback); 184 task_runner_->RunTasks(); 185 186 // Frame 2 should not come out at this point in time. 187 EXPECT_EQ(1, test_audio_encoder_callback_->number_times_called()); 188 189 // Through on one more pending callback. 190 receiver_->GetEncodedAudioFrame(frame_encoded_callback); 191 192 testing_clock_.Advance(base::TimeDelta::FromMilliseconds(100)); 193 194 task_runner_->RunTasks(); 195 EXPECT_EQ(2, test_audio_encoder_callback_->number_times_called()); 196 197 test_audio_encoder_callback_->SetExpectedResult(3, testing_clock_.NowTicks()); 198 199 // Through on one more pending audio frame. 200 rtp_header_.frame_id = 3; 201 rtp_header_.is_reference = false; 202 rtp_header_.reference_frame_id = 0; 203 rtp_header_.webrtc.header.timestamp = 1280; 204 receiver_->IncomingParsedRtpPacket(payload_.data(), payload_.size(), 205 rtp_header_); 206 207 receiver_->GetEncodedAudioFrame(frame_encoded_callback); 208 task_runner_->RunTasks(); 209 EXPECT_EQ(3, test_audio_encoder_callback_->number_times_called()); 210} 211 212// TODO(mikhal): Add encoded frames. 213TEST_F(AudioReceiverTest, GetRawFrame) { 214} 215 216} // namespace cast 217} // namespace media 218