Home | History | Annotate | Download | only in sender
      1 // Copyright 2014 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 <sstream>
      8 #include <string>
      9 
     10 #include "base/bind.h"
     11 #include "base/bind_helpers.h"
     12 #include "base/memory/scoped_ptr.h"
     13 #include "media/base/audio_bus.h"
     14 #include "media/base/media.h"
     15 #include "media/cast/cast_environment.h"
     16 #include "media/cast/sender/audio_encoder.h"
     17 #include "media/cast/test/fake_single_thread_task_runner.h"
     18 #include "media/cast/test/utility/audio_utility.h"
     19 #include "testing/gtest/include/gtest/gtest.h"
     20 
     21 namespace media {
     22 namespace cast {
     23 
     24 static const int kNumChannels = 2;
     25 
     26 namespace {
     27 
     28 class TestEncodedAudioFrameReceiver {
     29  public:
     30   explicit TestEncodedAudioFrameReceiver(Codec codec)
     31       : codec_(codec), frames_received_(0), rtp_lower_bound_(0) {}
     32   virtual ~TestEncodedAudioFrameReceiver() {}
     33 
     34   int frames_received() const { return frames_received_; }
     35 
     36   void SetCaptureTimeBounds(const base::TimeTicks& lower_bound,
     37                             const base::TimeTicks& upper_bound) {
     38     lower_bound_ = lower_bound;
     39     upper_bound_ = upper_bound;
     40   }
     41 
     42   void FrameEncoded(scoped_ptr<EncodedFrame> encoded_frame,
     43                     int samples_skipped) {
     44     EXPECT_EQ(encoded_frame->dependency, EncodedFrame::KEY);
     45     EXPECT_EQ(static_cast<uint8>(frames_received_ & 0xff),
     46               encoded_frame->frame_id);
     47     EXPECT_EQ(encoded_frame->frame_id, encoded_frame->referenced_frame_id);
     48     // RTP timestamps should be monotonically increasing and integer multiples
     49     // of the fixed frame size.
     50     EXPECT_LE(rtp_lower_bound_, encoded_frame->rtp_timestamp);
     51     rtp_lower_bound_ = encoded_frame->rtp_timestamp;
     52     // Note: In audio_encoder.cc, 100 is the fixed audio frame rate.
     53     const int kSamplesPerFrame = kDefaultAudioSamplingRate / 100;
     54     EXPECT_EQ(0u, encoded_frame->rtp_timestamp % kSamplesPerFrame);
     55     EXPECT_TRUE(!encoded_frame->data.empty());
     56 
     57     EXPECT_LE(lower_bound_, encoded_frame->reference_time);
     58     lower_bound_ = encoded_frame->reference_time;
     59     EXPECT_GT(upper_bound_, encoded_frame->reference_time);
     60 
     61     ++frames_received_;
     62   }
     63 
     64  private:
     65   const Codec codec_;
     66   int frames_received_;
     67   uint32 rtp_lower_bound_;
     68   base::TimeTicks lower_bound_;
     69   base::TimeTicks upper_bound_;
     70 
     71   DISALLOW_COPY_AND_ASSIGN(TestEncodedAudioFrameReceiver);
     72 };
     73 
     74 struct TestScenario {
     75   const int64* durations_in_ms;
     76   size_t num_durations;
     77 
     78   TestScenario(const int64* d, size_t n)
     79       : durations_in_ms(d), num_durations(n) {}
     80 
     81   std::string ToString() const {
     82     std::ostringstream out;
     83     for (size_t i = 0; i < num_durations; ++i) {
     84       if (i > 0)
     85         out << ", ";
     86       out << durations_in_ms[i];
     87     }
     88     return out.str();
     89   }
     90 };
     91 
     92 }  // namespace
     93 
     94 class AudioEncoderTest : public ::testing::TestWithParam<TestScenario> {
     95  public:
     96   AudioEncoderTest() {
     97     InitializeMediaLibraryForTesting();
     98     testing_clock_ = new base::SimpleTestTickClock();
     99     testing_clock_->Advance(base::TimeTicks::Now() - base::TimeTicks());
    100   }
    101 
    102   virtual void SetUp() {
    103     task_runner_ = new test::FakeSingleThreadTaskRunner(testing_clock_);
    104     cast_environment_ =
    105         new CastEnvironment(scoped_ptr<base::TickClock>(testing_clock_).Pass(),
    106                             task_runner_,
    107                             task_runner_,
    108                             task_runner_);
    109   }
    110 
    111   virtual ~AudioEncoderTest() {}
    112 
    113   void RunTestForCodec(Codec codec) {
    114     const TestScenario& scenario = GetParam();
    115     SCOPED_TRACE(::testing::Message() << "Durations: " << scenario.ToString());
    116 
    117     CreateObjectsForCodec(codec);
    118 
    119     // Note: In audio_encoder.cc, 10 ms is the fixed frame duration.
    120     const base::TimeDelta frame_duration =
    121         base::TimeDelta::FromMilliseconds(10);
    122 
    123     for (size_t i = 0; i < scenario.num_durations; ++i) {
    124       const bool simulate_missing_data = scenario.durations_in_ms[i] < 0;
    125       const base::TimeDelta duration = base::TimeDelta::FromMilliseconds(
    126           std::abs(scenario.durations_in_ms[i]));
    127       receiver_->SetCaptureTimeBounds(
    128           testing_clock_->NowTicks() - frame_duration,
    129           testing_clock_->NowTicks() + duration);
    130       if (simulate_missing_data) {
    131         task_runner_->RunTasks();
    132         testing_clock_->Advance(duration);
    133       } else {
    134         audio_encoder_->InsertAudio(audio_bus_factory_->NextAudioBus(duration),
    135                                     testing_clock_->NowTicks());
    136         task_runner_->RunTasks();
    137         testing_clock_->Advance(duration);
    138       }
    139     }
    140 
    141     DVLOG(1) << "Received " << receiver_->frames_received()
    142              << " frames for this test run: " << scenario.ToString();
    143   }
    144 
    145  private:
    146   void CreateObjectsForCodec(Codec codec) {
    147     audio_bus_factory_.reset(
    148         new TestAudioBusFactory(kNumChannels,
    149                                 kDefaultAudioSamplingRate,
    150                                 TestAudioBusFactory::kMiddleANoteFreq,
    151                                 0.5f));
    152 
    153     receiver_.reset(new TestEncodedAudioFrameReceiver(codec));
    154 
    155     audio_encoder_.reset(new AudioEncoder(
    156         cast_environment_,
    157         kNumChannels,
    158         kDefaultAudioSamplingRate,
    159         kDefaultAudioEncoderBitrate,
    160         codec,
    161         base::Bind(&TestEncodedAudioFrameReceiver::FrameEncoded,
    162                    base::Unretained(receiver_.get()))));
    163   }
    164 
    165   base::SimpleTestTickClock* testing_clock_;  // Owned by CastEnvironment.
    166   scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
    167   scoped_ptr<TestAudioBusFactory> audio_bus_factory_;
    168   scoped_ptr<TestEncodedAudioFrameReceiver> receiver_;
    169   scoped_ptr<AudioEncoder> audio_encoder_;
    170   scoped_refptr<CastEnvironment> cast_environment_;
    171 
    172   DISALLOW_COPY_AND_ASSIGN(AudioEncoderTest);
    173 };
    174 
    175 TEST_P(AudioEncoderTest, EncodeOpus) {
    176   RunTestForCodec(CODEC_AUDIO_OPUS);
    177 }
    178 
    179 TEST_P(AudioEncoderTest, EncodePcm16) {
    180   RunTestForCodec(CODEC_AUDIO_PCM16);
    181 }
    182 
    183 static const int64 kOneCall_3Millis[] = {3};
    184 static const int64 kOneCall_10Millis[] = {10};
    185 static const int64 kOneCall_13Millis[] = {13};
    186 static const int64 kOneCall_20Millis[] = {20};
    187 
    188 static const int64 kTwoCalls_3Millis[] = {3, 3};
    189 static const int64 kTwoCalls_10Millis[] = {10, 10};
    190 static const int64 kTwoCalls_Mixed1[] = {3, 10};
    191 static const int64 kTwoCalls_Mixed2[] = {10, 3};
    192 static const int64 kTwoCalls_Mixed3[] = {3, 17};
    193 static const int64 kTwoCalls_Mixed4[] = {17, 3};
    194 
    195 static const int64 kManyCalls_3Millis[] = {3, 3, 3, 3, 3, 3, 3, 3,
    196                                            3, 3, 3, 3, 3, 3, 3};
    197 static const int64 kManyCalls_10Millis[] = {10, 10, 10, 10, 10, 10, 10, 10,
    198                                             10, 10, 10, 10, 10, 10, 10};
    199 static const int64 kManyCalls_Mixed1[] = {3,  10, 3,  10, 3,  10, 3,  10, 3,
    200                                           10, 3,  10, 3,  10, 3,  10, 3,  10};
    201 static const int64 kManyCalls_Mixed2[] = {10, 3, 10, 3, 10, 3, 10, 3, 10, 3,
    202                                           10, 3, 10, 3, 10, 3, 10, 3, 10, 3};
    203 static const int64 kManyCalls_Mixed3[] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8,
    204                                           9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4};
    205 static const int64 kManyCalls_Mixed4[] = {31, 4, 15, 9,  26, 53, 5,  8, 9,
    206                                           7,  9, 32, 38, 4,  62, 64, 3};
    207 static const int64 kManyCalls_Mixed5[] = {3, 14, 15, 9, 26, 53, 58, 9, 7,
    208                                           9, 3,  23, 8, 4,  6,  2,  6, 43};
    209 
    210 static const int64 kOneBigUnderrun[] = {10, 10, 10, 10, -1000, 10, 10, 10};
    211 static const int64 kTwoBigUnderruns[] = {10, 10, 10, 10, -712, 10, 10, 10,
    212                                          -1311, 10, 10, 10};
    213 static const int64 kMixedUnderruns[] = {31, -64, 4, 15, 9, 26, -53, 5,  8, -9,
    214                                         7,  9, 32, 38, -4, 62, -64, 3};
    215 
    216 INSTANTIATE_TEST_CASE_P(
    217     AudioEncoderTestScenarios,
    218     AudioEncoderTest,
    219     ::testing::Values(
    220         TestScenario(kOneCall_3Millis, arraysize(kOneCall_3Millis)),
    221         TestScenario(kOneCall_10Millis, arraysize(kOneCall_10Millis)),
    222         TestScenario(kOneCall_13Millis, arraysize(kOneCall_13Millis)),
    223         TestScenario(kOneCall_20Millis, arraysize(kOneCall_20Millis)),
    224         TestScenario(kTwoCalls_3Millis, arraysize(kTwoCalls_3Millis)),
    225         TestScenario(kTwoCalls_10Millis, arraysize(kTwoCalls_10Millis)),
    226         TestScenario(kTwoCalls_Mixed1, arraysize(kTwoCalls_Mixed1)),
    227         TestScenario(kTwoCalls_Mixed2, arraysize(kTwoCalls_Mixed2)),
    228         TestScenario(kTwoCalls_Mixed3, arraysize(kTwoCalls_Mixed3)),
    229         TestScenario(kTwoCalls_Mixed4, arraysize(kTwoCalls_Mixed4)),
    230         TestScenario(kManyCalls_3Millis, arraysize(kManyCalls_3Millis)),
    231         TestScenario(kManyCalls_10Millis, arraysize(kManyCalls_10Millis)),
    232         TestScenario(kManyCalls_Mixed1, arraysize(kManyCalls_Mixed1)),
    233         TestScenario(kManyCalls_Mixed2, arraysize(kManyCalls_Mixed2)),
    234         TestScenario(kManyCalls_Mixed3, arraysize(kManyCalls_Mixed3)),
    235         TestScenario(kManyCalls_Mixed4, arraysize(kManyCalls_Mixed4)),
    236         TestScenario(kManyCalls_Mixed5, arraysize(kManyCalls_Mixed5)),
    237         TestScenario(kOneBigUnderrun, arraysize(kOneBigUnderrun)),
    238         TestScenario(kTwoBigUnderruns, arraysize(kTwoBigUnderruns)),
    239         TestScenario(kMixedUnderruns, arraysize(kMixedUnderruns))));
    240 
    241 }  // namespace cast
    242 }  // namespace media
    243