1 /*
2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "webrtc/test/testsupport/fileutils.h"
12 #include "webrtc/voice_engine/test/auto_test/fixtures/after_initialization_fixture.h"
13 
14 namespace {
15 
16 const int kSampleRateHz = 16000;
17 const int kTestDurationMs = 1000;
18 const int kSkipOutputMs = 50;
19 const int16_t kInputValue = 15000;
20 const int16_t kSilenceValue = 0;
21 
22 }  // namespace
23 
24 class FileBeforeStreamingTest : public AfterInitializationFixture {
25  protected:
FileBeforeStreamingTest()26   FileBeforeStreamingTest()
27       : input_filename_(webrtc::test::OutputPath() + "file_test_input.pcm"),
28         output_filename_(webrtc::test::OutputPath() + "file_test_output.pcm") {
29   }
30 
SetUp()31   void SetUp() {
32     channel_ = voe_base_->CreateChannel();
33   }
34 
TearDown()35   void TearDown() {
36     voe_base_->DeleteChannel(channel_);
37   }
38 
39   // TODO(andrew): consolidate below methods in a shared place?
40 
41   // Generate input file with constant values as |kInputValue|. The file
42   // will be one second longer than the duration of the test.
GenerateInputFile()43   void GenerateInputFile() {
44     FILE* input_file = fopen(input_filename_.c_str(), "wb");
45     ASSERT_TRUE(input_file != NULL);
46     for (int i = 0; i < kSampleRateHz / 1000 * (kTestDurationMs + 1000); i++) {
47       ASSERT_EQ(1u, fwrite(&kInputValue, sizeof(kInputValue), 1, input_file));
48     }
49     ASSERT_EQ(0, fclose(input_file));
50   }
51 
RecordOutput()52   void RecordOutput() {
53     // Start recording the mixed output for |kTestDurationMs| long.
54     EXPECT_EQ(0, voe_file_->StartRecordingPlayout(-1,
55         output_filename_.c_str()));
56     Sleep(kTestDurationMs);
57     EXPECT_EQ(0, voe_file_->StopRecordingPlayout(-1));
58   }
59 
VerifyOutput(int16_t target_value)60   void VerifyOutput(int16_t target_value) {
61     FILE* output_file = fopen(output_filename_.c_str(), "rb");
62     ASSERT_TRUE(output_file != NULL);
63     int16_t output_value = 0;
64     int samples_read = 0;
65 
66     // Skip the first segment to avoid initialization and ramping-in effects.
67     EXPECT_EQ(0, fseek(output_file, sizeof(output_value) *
68                        kSampleRateHz / 1000 * kSkipOutputMs, SEEK_SET));
69     while (fread(&output_value, sizeof(output_value), 1, output_file) == 1) {
70       samples_read++;
71       EXPECT_EQ(output_value, target_value);
72     }
73 
74     // Ensure that a reasonable amount was recorded. We use a loose
75     // tolerance to avoid flaky bot failures.
76     ASSERT_GE((samples_read * 1000.0) / kSampleRateHz, 0.4 * kTestDurationMs);
77 
78     // Ensure we read the entire file.
79     ASSERT_NE(0, feof(output_file));
80     ASSERT_EQ(0, fclose(output_file));
81   }
82 
VerifyEmptyOutput()83 void VerifyEmptyOutput() {
84   FILE* output_file = fopen(output_filename_.c_str(), "rb");
85   ASSERT_TRUE(output_file != NULL);
86   ASSERT_EQ(0, fseek(output_file, 0, SEEK_END));
87   EXPECT_EQ(0, ftell(output_file));
88   ASSERT_EQ(0, fclose(output_file));
89 }
90 
91   int channel_;
92   const std::string input_filename_;
93   const std::string output_filename_;
94 };
95 
96 // This test case is to ensure that StartPlayingFileLocally() and
97 // StartPlayout() can be called in any order.
98 // A DC signal is used as input. And the output of mixer is supposed to be:
99 // 1. the same DC signal if file is played out,
100 // 2. total silence if file is not played out,
101 // 3. no output if playout is not started.
TEST_F(FileBeforeStreamingTest,TestStartPlayingFileLocallyWithStartPlayout)102 TEST_F(FileBeforeStreamingTest, TestStartPlayingFileLocallyWithStartPlayout) {
103   GenerateInputFile();
104 
105   TEST_LOG("Playout is not started. File will not be played out.\n");
106   EXPECT_EQ(0, voe_file_->StartPlayingFileLocally(
107       channel_, input_filename_.c_str(), true));
108   EXPECT_EQ(1, voe_file_->IsPlayingFileLocally(channel_));
109   RecordOutput();
110   VerifyEmptyOutput();
111 
112   TEST_LOG("Playout is now started. File will be played out.\n");
113   EXPECT_EQ(0, voe_base_->StartPlayout(channel_));
114   RecordOutput();
115   VerifyOutput(kInputValue);
116 
117   TEST_LOG("Stop playing file. Only silence will be played out.\n");
118   EXPECT_EQ(0, voe_file_->StopPlayingFileLocally(channel_));
119   EXPECT_EQ(0, voe_file_->IsPlayingFileLocally(channel_));
120   RecordOutput();
121   VerifyOutput(kSilenceValue);
122 
123   TEST_LOG("Start playing file again. File will be played out.\n");
124   EXPECT_EQ(0, voe_file_->StartPlayingFileLocally(
125       channel_, input_filename_.c_str(), true));
126   EXPECT_EQ(1, voe_file_->IsPlayingFileLocally(channel_));
127   RecordOutput();
128   VerifyOutput(kInputValue);
129 
130   EXPECT_EQ(0, voe_base_->StopPlayout(channel_));
131   EXPECT_EQ(0, voe_file_->StopPlayingFileLocally(channel_));
132 }
133