1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "TwoWayCommunication.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <stdio.h>
14*d9f75844SAndroid Build Coastguard Worker #include <string.h>
15*d9f75844SAndroid Build Coastguard Worker
16*d9f75844SAndroid Build Coastguard Worker #include <memory>
17*d9f75844SAndroid Build Coastguard Worker
18*d9f75844SAndroid Build Coastguard Worker #include "api/audio_codecs/builtin_audio_decoder_factory.h"
19*d9f75844SAndroid Build Coastguard Worker #include "api/audio_codecs/builtin_audio_encoder_factory.h"
20*d9f75844SAndroid Build Coastguard Worker #include "modules/audio_coding/test/PCMFile.h"
21*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
22*d9f75844SAndroid Build Coastguard Worker #include "test/testsupport/file_utils.h"
23*d9f75844SAndroid Build Coastguard Worker
24*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
25*d9f75844SAndroid Build Coastguard Worker
26*d9f75844SAndroid Build Coastguard Worker #define MAX_FILE_NAME_LENGTH_BYTE 500
27*d9f75844SAndroid Build Coastguard Worker
TwoWayCommunication()28*d9f75844SAndroid Build Coastguard Worker TwoWayCommunication::TwoWayCommunication()
29*d9f75844SAndroid Build Coastguard Worker : _acmA(AudioCodingModule::Create(
30*d9f75844SAndroid Build Coastguard Worker AudioCodingModule::Config(CreateBuiltinAudioDecoderFactory()))),
31*d9f75844SAndroid Build Coastguard Worker _acmRefA(AudioCodingModule::Create(
32*d9f75844SAndroid Build Coastguard Worker AudioCodingModule::Config(CreateBuiltinAudioDecoderFactory()))) {
33*d9f75844SAndroid Build Coastguard Worker AudioCodingModule::Config config;
34*d9f75844SAndroid Build Coastguard Worker // The clicks will be more obvious if time-stretching is not allowed.
35*d9f75844SAndroid Build Coastguard Worker // TODO(henrik.lundin) Really?
36*d9f75844SAndroid Build Coastguard Worker config.neteq_config.for_test_no_time_stretching = true;
37*d9f75844SAndroid Build Coastguard Worker config.decoder_factory = CreateBuiltinAudioDecoderFactory();
38*d9f75844SAndroid Build Coastguard Worker _acmB.reset(AudioCodingModule::Create(config));
39*d9f75844SAndroid Build Coastguard Worker _acmRefB.reset(AudioCodingModule::Create(config));
40*d9f75844SAndroid Build Coastguard Worker }
41*d9f75844SAndroid Build Coastguard Worker
~TwoWayCommunication()42*d9f75844SAndroid Build Coastguard Worker TwoWayCommunication::~TwoWayCommunication() {
43*d9f75844SAndroid Build Coastguard Worker delete _channel_A2B;
44*d9f75844SAndroid Build Coastguard Worker delete _channel_B2A;
45*d9f75844SAndroid Build Coastguard Worker delete _channelRef_A2B;
46*d9f75844SAndroid Build Coastguard Worker delete _channelRef_B2A;
47*d9f75844SAndroid Build Coastguard Worker _inFileA.Close();
48*d9f75844SAndroid Build Coastguard Worker _inFileB.Close();
49*d9f75844SAndroid Build Coastguard Worker _outFileA.Close();
50*d9f75844SAndroid Build Coastguard Worker _outFileB.Close();
51*d9f75844SAndroid Build Coastguard Worker _outFileRefA.Close();
52*d9f75844SAndroid Build Coastguard Worker _outFileRefB.Close();
53*d9f75844SAndroid Build Coastguard Worker }
54*d9f75844SAndroid Build Coastguard Worker
SetUpAutotest(AudioEncoderFactory * const encoder_factory,const SdpAudioFormat & format1,const int payload_type1,const SdpAudioFormat & format2,const int payload_type2)55*d9f75844SAndroid Build Coastguard Worker void TwoWayCommunication::SetUpAutotest(
56*d9f75844SAndroid Build Coastguard Worker AudioEncoderFactory* const encoder_factory,
57*d9f75844SAndroid Build Coastguard Worker const SdpAudioFormat& format1,
58*d9f75844SAndroid Build Coastguard Worker const int payload_type1,
59*d9f75844SAndroid Build Coastguard Worker const SdpAudioFormat& format2,
60*d9f75844SAndroid Build Coastguard Worker const int payload_type2) {
61*d9f75844SAndroid Build Coastguard Worker //--- Set A codecs
62*d9f75844SAndroid Build Coastguard Worker _acmA->SetEncoder(
63*d9f75844SAndroid Build Coastguard Worker encoder_factory->MakeAudioEncoder(payload_type1, format1, absl::nullopt));
64*d9f75844SAndroid Build Coastguard Worker _acmA->SetReceiveCodecs({{payload_type2, format2}});
65*d9f75844SAndroid Build Coastguard Worker
66*d9f75844SAndroid Build Coastguard Worker //--- Set ref-A codecs
67*d9f75844SAndroid Build Coastguard Worker _acmRefA->SetEncoder(
68*d9f75844SAndroid Build Coastguard Worker encoder_factory->MakeAudioEncoder(payload_type1, format1, absl::nullopt));
69*d9f75844SAndroid Build Coastguard Worker _acmRefA->SetReceiveCodecs({{payload_type2, format2}});
70*d9f75844SAndroid Build Coastguard Worker
71*d9f75844SAndroid Build Coastguard Worker //--- Set B codecs
72*d9f75844SAndroid Build Coastguard Worker _acmB->SetEncoder(
73*d9f75844SAndroid Build Coastguard Worker encoder_factory->MakeAudioEncoder(payload_type2, format2, absl::nullopt));
74*d9f75844SAndroid Build Coastguard Worker _acmB->SetReceiveCodecs({{payload_type1, format1}});
75*d9f75844SAndroid Build Coastguard Worker
76*d9f75844SAndroid Build Coastguard Worker //--- Set ref-B codecs
77*d9f75844SAndroid Build Coastguard Worker _acmRefB->SetEncoder(
78*d9f75844SAndroid Build Coastguard Worker encoder_factory->MakeAudioEncoder(payload_type2, format2, absl::nullopt));
79*d9f75844SAndroid Build Coastguard Worker _acmRefB->SetReceiveCodecs({{payload_type1, format1}});
80*d9f75844SAndroid Build Coastguard Worker
81*d9f75844SAndroid Build Coastguard Worker uint16_t frequencyHz;
82*d9f75844SAndroid Build Coastguard Worker
83*d9f75844SAndroid Build Coastguard Worker //--- Input A and B
84*d9f75844SAndroid Build Coastguard Worker std::string in_file_name =
85*d9f75844SAndroid Build Coastguard Worker webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
86*d9f75844SAndroid Build Coastguard Worker frequencyHz = 16000;
87*d9f75844SAndroid Build Coastguard Worker _inFileA.Open(in_file_name, frequencyHz, "rb");
88*d9f75844SAndroid Build Coastguard Worker _inFileB.Open(in_file_name, frequencyHz, "rb");
89*d9f75844SAndroid Build Coastguard Worker
90*d9f75844SAndroid Build Coastguard Worker //--- Output A
91*d9f75844SAndroid Build Coastguard Worker std::string output_file_a = webrtc::test::OutputPath() + "outAutotestA.pcm";
92*d9f75844SAndroid Build Coastguard Worker frequencyHz = 16000;
93*d9f75844SAndroid Build Coastguard Worker _outFileA.Open(output_file_a, frequencyHz, "wb");
94*d9f75844SAndroid Build Coastguard Worker std::string output_ref_file_a =
95*d9f75844SAndroid Build Coastguard Worker webrtc::test::OutputPath() + "ref_outAutotestA.pcm";
96*d9f75844SAndroid Build Coastguard Worker _outFileRefA.Open(output_ref_file_a, frequencyHz, "wb");
97*d9f75844SAndroid Build Coastguard Worker
98*d9f75844SAndroid Build Coastguard Worker //--- Output B
99*d9f75844SAndroid Build Coastguard Worker std::string output_file_b = webrtc::test::OutputPath() + "outAutotestB.pcm";
100*d9f75844SAndroid Build Coastguard Worker frequencyHz = 16000;
101*d9f75844SAndroid Build Coastguard Worker _outFileB.Open(output_file_b, frequencyHz, "wb");
102*d9f75844SAndroid Build Coastguard Worker std::string output_ref_file_b =
103*d9f75844SAndroid Build Coastguard Worker webrtc::test::OutputPath() + "ref_outAutotestB.pcm";
104*d9f75844SAndroid Build Coastguard Worker _outFileRefB.Open(output_ref_file_b, frequencyHz, "wb");
105*d9f75844SAndroid Build Coastguard Worker
106*d9f75844SAndroid Build Coastguard Worker //--- Set A-to-B channel
107*d9f75844SAndroid Build Coastguard Worker _channel_A2B = new Channel;
108*d9f75844SAndroid Build Coastguard Worker _acmA->RegisterTransportCallback(_channel_A2B);
109*d9f75844SAndroid Build Coastguard Worker _channel_A2B->RegisterReceiverACM(_acmB.get());
110*d9f75844SAndroid Build Coastguard Worker //--- Do the same for the reference
111*d9f75844SAndroid Build Coastguard Worker _channelRef_A2B = new Channel;
112*d9f75844SAndroid Build Coastguard Worker _acmRefA->RegisterTransportCallback(_channelRef_A2B);
113*d9f75844SAndroid Build Coastguard Worker _channelRef_A2B->RegisterReceiverACM(_acmRefB.get());
114*d9f75844SAndroid Build Coastguard Worker
115*d9f75844SAndroid Build Coastguard Worker //--- Set B-to-A channel
116*d9f75844SAndroid Build Coastguard Worker _channel_B2A = new Channel;
117*d9f75844SAndroid Build Coastguard Worker _acmB->RegisterTransportCallback(_channel_B2A);
118*d9f75844SAndroid Build Coastguard Worker _channel_B2A->RegisterReceiverACM(_acmA.get());
119*d9f75844SAndroid Build Coastguard Worker //--- Do the same for reference
120*d9f75844SAndroid Build Coastguard Worker _channelRef_B2A = new Channel;
121*d9f75844SAndroid Build Coastguard Worker _acmRefB->RegisterTransportCallback(_channelRef_B2A);
122*d9f75844SAndroid Build Coastguard Worker _channelRef_B2A->RegisterReceiverACM(_acmRefA.get());
123*d9f75844SAndroid Build Coastguard Worker }
124*d9f75844SAndroid Build Coastguard Worker
Perform()125*d9f75844SAndroid Build Coastguard Worker void TwoWayCommunication::Perform() {
126*d9f75844SAndroid Build Coastguard Worker const SdpAudioFormat format1("ISAC", 16000, 1);
127*d9f75844SAndroid Build Coastguard Worker const SdpAudioFormat format2("L16", 8000, 1);
128*d9f75844SAndroid Build Coastguard Worker constexpr int payload_type1 = 17, payload_type2 = 18;
129*d9f75844SAndroid Build Coastguard Worker
130*d9f75844SAndroid Build Coastguard Worker auto encoder_factory = CreateBuiltinAudioEncoderFactory();
131*d9f75844SAndroid Build Coastguard Worker
132*d9f75844SAndroid Build Coastguard Worker SetUpAutotest(encoder_factory.get(), format1, payload_type1, format2,
133*d9f75844SAndroid Build Coastguard Worker payload_type2);
134*d9f75844SAndroid Build Coastguard Worker
135*d9f75844SAndroid Build Coastguard Worker unsigned int msecPassed = 0;
136*d9f75844SAndroid Build Coastguard Worker unsigned int secPassed = 0;
137*d9f75844SAndroid Build Coastguard Worker
138*d9f75844SAndroid Build Coastguard Worker int32_t outFreqHzA = _outFileA.SamplingFrequency();
139*d9f75844SAndroid Build Coastguard Worker int32_t outFreqHzB = _outFileB.SamplingFrequency();
140*d9f75844SAndroid Build Coastguard Worker
141*d9f75844SAndroid Build Coastguard Worker AudioFrame audioFrame;
142*d9f75844SAndroid Build Coastguard Worker
143*d9f75844SAndroid Build Coastguard Worker // In the following loop we tests that the code can handle misuse of the APIs.
144*d9f75844SAndroid Build Coastguard Worker // In the middle of a session with data flowing between two sides, called A
145*d9f75844SAndroid Build Coastguard Worker // and B, APIs will be called, and the code should continue to run, and be
146*d9f75844SAndroid Build Coastguard Worker // able to recover.
147*d9f75844SAndroid Build Coastguard Worker while (!_inFileA.EndOfFile() && !_inFileB.EndOfFile()) {
148*d9f75844SAndroid Build Coastguard Worker msecPassed += 10;
149*d9f75844SAndroid Build Coastguard Worker EXPECT_GT(_inFileA.Read10MsData(audioFrame), 0);
150*d9f75844SAndroid Build Coastguard Worker EXPECT_GE(_acmA->Add10MsData(audioFrame), 0);
151*d9f75844SAndroid Build Coastguard Worker EXPECT_GE(_acmRefA->Add10MsData(audioFrame), 0);
152*d9f75844SAndroid Build Coastguard Worker
153*d9f75844SAndroid Build Coastguard Worker EXPECT_GT(_inFileB.Read10MsData(audioFrame), 0);
154*d9f75844SAndroid Build Coastguard Worker
155*d9f75844SAndroid Build Coastguard Worker EXPECT_GE(_acmB->Add10MsData(audioFrame), 0);
156*d9f75844SAndroid Build Coastguard Worker EXPECT_GE(_acmRefB->Add10MsData(audioFrame), 0);
157*d9f75844SAndroid Build Coastguard Worker bool muted;
158*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, _acmA->PlayoutData10Ms(outFreqHzA, &audioFrame, &muted));
159*d9f75844SAndroid Build Coastguard Worker ASSERT_FALSE(muted);
160*d9f75844SAndroid Build Coastguard Worker _outFileA.Write10MsData(audioFrame);
161*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, _acmRefA->PlayoutData10Ms(outFreqHzA, &audioFrame, &muted));
162*d9f75844SAndroid Build Coastguard Worker ASSERT_FALSE(muted);
163*d9f75844SAndroid Build Coastguard Worker _outFileRefA.Write10MsData(audioFrame);
164*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, _acmB->PlayoutData10Ms(outFreqHzB, &audioFrame, &muted));
165*d9f75844SAndroid Build Coastguard Worker ASSERT_FALSE(muted);
166*d9f75844SAndroid Build Coastguard Worker _outFileB.Write10MsData(audioFrame);
167*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, _acmRefB->PlayoutData10Ms(outFreqHzB, &audioFrame, &muted));
168*d9f75844SAndroid Build Coastguard Worker ASSERT_FALSE(muted);
169*d9f75844SAndroid Build Coastguard Worker _outFileRefB.Write10MsData(audioFrame);
170*d9f75844SAndroid Build Coastguard Worker
171*d9f75844SAndroid Build Coastguard Worker // Update time counters each time a second of data has passed.
172*d9f75844SAndroid Build Coastguard Worker if (msecPassed >= 1000) {
173*d9f75844SAndroid Build Coastguard Worker msecPassed = 0;
174*d9f75844SAndroid Build Coastguard Worker secPassed++;
175*d9f75844SAndroid Build Coastguard Worker }
176*d9f75844SAndroid Build Coastguard Worker // Re-register send codec on side B.
177*d9f75844SAndroid Build Coastguard Worker if (((secPassed % 5) == 4) && (msecPassed >= 990)) {
178*d9f75844SAndroid Build Coastguard Worker _acmB->SetEncoder(encoder_factory->MakeAudioEncoder(
179*d9f75844SAndroid Build Coastguard Worker payload_type2, format2, absl::nullopt));
180*d9f75844SAndroid Build Coastguard Worker }
181*d9f75844SAndroid Build Coastguard Worker // Initialize receiver on side A.
182*d9f75844SAndroid Build Coastguard Worker if (((secPassed % 7) == 6) && (msecPassed == 0))
183*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0, _acmA->InitializeReceiver());
184*d9f75844SAndroid Build Coastguard Worker // Re-register codec on side A.
185*d9f75844SAndroid Build Coastguard Worker if (((secPassed % 7) == 6) && (msecPassed >= 990)) {
186*d9f75844SAndroid Build Coastguard Worker _acmA->SetReceiveCodecs({{payload_type2, format2}});
187*d9f75844SAndroid Build Coastguard Worker }
188*d9f75844SAndroid Build Coastguard Worker }
189*d9f75844SAndroid Build Coastguard Worker }
190*d9f75844SAndroid Build Coastguard Worker
191*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc
192