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 <stdint.h>
6
7#include "base/bind.h"
8#include "base/bind_helpers.h"
9#include "base/memory/scoped_ptr.h"
10#include "base/test/simple_test_tick_clock.h"
11#include "media/base/media.h"
12#include "media/cast/audio_sender/audio_sender.h"
13#include "media/cast/cast_config.h"
14#include "media/cast/cast_environment.h"
15#include "media/cast/rtcp/rtcp.h"
16#include "media/cast/test/fake_single_thread_task_runner.h"
17#include "media/cast/test/utility/audio_utility.h"
18#include "media/cast/transport/cast_transport_config.h"
19#include "media/cast/transport/cast_transport_sender_impl.h"
20#include "testing/gtest/include/gtest/gtest.h"
21
22namespace media {
23namespace cast {
24
25class TestPacketSender : public transport::PacketSender {
26 public:
27  TestPacketSender() : number_of_rtp_packets_(0), number_of_rtcp_packets_(0) {}
28
29  virtual bool SendPacket(transport::PacketRef packet,
30                          const base::Closure& cb) OVERRIDE {
31    if (Rtcp::IsRtcpPacket(&packet->data[0], packet->data.size())) {
32      ++number_of_rtcp_packets_;
33    } else {
34      // Check that at least one RTCP packet was sent before the first RTP
35      // packet.  This confirms that the receiver will have the necessary lip
36      // sync info before it has to calculate the playout time of the first
37      // frame.
38      if (number_of_rtp_packets_ == 0)
39        EXPECT_LE(1, number_of_rtcp_packets_);
40      ++number_of_rtp_packets_;
41    }
42    return true;
43  }
44
45  int number_of_rtp_packets() const { return number_of_rtp_packets_; }
46
47  int number_of_rtcp_packets() const { return number_of_rtcp_packets_; }
48
49 private:
50  int number_of_rtp_packets_;
51  int number_of_rtcp_packets_;
52
53  DISALLOW_COPY_AND_ASSIGN(TestPacketSender);
54};
55
56class AudioSenderTest : public ::testing::Test {
57 protected:
58  AudioSenderTest() {
59    InitializeMediaLibraryForTesting();
60    testing_clock_ = new base::SimpleTestTickClock();
61    testing_clock_->Advance(base::TimeTicks::Now() - base::TimeTicks());
62    task_runner_ = new test::FakeSingleThreadTaskRunner(testing_clock_);
63    cast_environment_ =
64        new CastEnvironment(scoped_ptr<base::TickClock>(testing_clock_).Pass(),
65                            task_runner_,
66                            task_runner_,
67                            task_runner_);
68    audio_config_.codec = transport::kOpus;
69    audio_config_.use_external_encoder = false;
70    audio_config_.frequency = kDefaultAudioSamplingRate;
71    audio_config_.channels = 2;
72    audio_config_.bitrate = kDefaultAudioEncoderBitrate;
73    audio_config_.rtp_config.payload_type = 127;
74
75    net::IPEndPoint dummy_endpoint;
76
77    transport_sender_.reset(new transport::CastTransportSenderImpl(
78        NULL,
79        testing_clock_,
80        dummy_endpoint,
81        base::Bind(&UpdateCastTransportStatus),
82        transport::BulkRawEventsCallback(),
83        base::TimeDelta(),
84        task_runner_,
85        &transport_));
86    audio_sender_.reset(new AudioSender(
87        cast_environment_, audio_config_, transport_sender_.get()));
88    task_runner_->RunTasks();
89  }
90
91  virtual ~AudioSenderTest() {}
92
93  static void UpdateCastTransportStatus(transport::CastTransportStatus status) {
94    EXPECT_EQ(transport::TRANSPORT_AUDIO_INITIALIZED, status);
95  }
96
97  base::SimpleTestTickClock* testing_clock_;  // Owned by CastEnvironment.
98  TestPacketSender transport_;
99  scoped_ptr<transport::CastTransportSenderImpl> transport_sender_;
100  scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
101  scoped_ptr<AudioSender> audio_sender_;
102  scoped_refptr<CastEnvironment> cast_environment_;
103  AudioSenderConfig audio_config_;
104};
105
106TEST_F(AudioSenderTest, Encode20ms) {
107  const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(20);
108  scoped_ptr<AudioBus> bus(
109      TestAudioBusFactory(audio_config_.channels,
110                          audio_config_.frequency,
111                          TestAudioBusFactory::kMiddleANoteFreq,
112                          0.5f).NextAudioBus(kDuration));
113
114  audio_sender_->InsertAudio(bus.Pass(), testing_clock_->NowTicks());
115  task_runner_->RunTasks();
116  EXPECT_LE(1, transport_.number_of_rtp_packets());
117  EXPECT_LE(1, transport_.number_of_rtcp_packets());
118}
119
120TEST_F(AudioSenderTest, RtcpTimer) {
121  const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(20);
122  scoped_ptr<AudioBus> bus(
123      TestAudioBusFactory(audio_config_.channels,
124                          audio_config_.frequency,
125                          TestAudioBusFactory::kMiddleANoteFreq,
126                          0.5f).NextAudioBus(kDuration));
127
128  audio_sender_->InsertAudio(bus.Pass(), testing_clock_->NowTicks());
129  task_runner_->RunTasks();
130
131  // Make sure that we send at least one RTCP packet.
132  base::TimeDelta max_rtcp_timeout =
133      base::TimeDelta::FromMilliseconds(1 + kDefaultRtcpIntervalMs * 3 / 2);
134  testing_clock_->Advance(max_rtcp_timeout);
135  task_runner_->RunTasks();
136  EXPECT_LE(1, transport_.number_of_rtp_packets());
137  EXPECT_LE(1, transport_.number_of_rtcp_packets());
138}
139
140}  // namespace cast
141}  // namespace media
142