Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / audio_coding / main / test / dual_stream_unittest.cc
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 "gtest/gtest.h"
12 #include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
13 #include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
14 #include "webrtc/modules/audio_coding/main/test/PCMFile.h"
15 #include "webrtc/modules/audio_coding/main/test/utility.h"
16 #include "webrtc/modules/interface/module_common_types.h"
17 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
18 #include "webrtc/typedefs.h"
19 #include "webrtc/test/testsupport/fileutils.h"
20 #include "webrtc/test/testsupport/gtest_disable.h"
21
22 namespace webrtc {
23
24 class DualStreamTest : public AudioPacketizationCallback,
25                        public ::testing::Test {
26  protected:
27   DualStreamTest();
28   ~DualStreamTest();
29
30   void RunTest(int frame_size_primary_samples,
31                int num_channels_primary,
32                int sampling_rate,
33                bool start_in_sync,
34                int num_channels_input);
35
36   void ApiTest();
37
38   int32_t SendData(FrameType frameType, uint8_t payload_type,
39                    uint32_t timestamp, const uint8_t* payload_data,
40                    uint16_t payload_size,
41                    const RTPFragmentationHeader* fragmentation);
42
43   void Perform(bool start_in_sync, int num_channels_input);
44
45   void InitializeSender(int frame_size_primary_samples,
46                         int num_channels_primary, int sampling_rate);
47
48   void PopulateCodecInstances(int frame_size_primary_ms,
49                               int num_channels_primary, int sampling_rate);
50
51   void Validate(bool start_in_sync, int tolerance);
52   bool EqualTimestamp(int stream, int position);
53   int EqualPayloadLength(int stream, int position);
54   bool EqualPayloadData(int stream, int position);
55
56   static const int kMaxNumStoredPayloads = 2;
57
58   enum {
59     kPrimary = 0,
60     kSecondary,
61     kMaxNumStreams
62   };
63
64   scoped_ptr<AudioCodingModule> acm_dual_stream_;
65   scoped_ptr<AudioCodingModule> acm_ref_primary_;
66   scoped_ptr<AudioCodingModule> acm_ref_secondary_;
67
68   CodecInst primary_encoder_;
69   CodecInst secondary_encoder_;
70
71   CodecInst red_encoder_;
72
73   int payload_ref_is_stored_[kMaxNumStreams][kMaxNumStoredPayloads];
74   int payload_dual_is_stored_[kMaxNumStreams][kMaxNumStoredPayloads];
75
76   uint32_t timestamp_ref_[kMaxNumStreams][kMaxNumStoredPayloads];
77   uint32_t timestamp_dual_[kMaxNumStreams][kMaxNumStoredPayloads];
78
79   int payload_len_ref_[kMaxNumStreams][kMaxNumStoredPayloads];
80   int payload_len_dual_[kMaxNumStreams][kMaxNumStoredPayloads];
81
82   uint8_t payload_data_ref_[kMaxNumStreams][MAX_PAYLOAD_SIZE_BYTE
83       * kMaxNumStoredPayloads];
84   uint8_t payload_data_dual_[kMaxNumStreams][MAX_PAYLOAD_SIZE_BYTE
85       * kMaxNumStoredPayloads];
86   int num_received_payloads_dual_[kMaxNumStreams];
87   int num_received_payloads_ref_[kMaxNumStreams];
88
89   int num_compared_payloads_[kMaxNumStreams];
90   uint32_t last_timestamp_[kMaxNumStreams];
91   bool received_payload_[kMaxNumStreams];
92 };
93
94 DualStreamTest::DualStreamTest()
95     : acm_dual_stream_(AudioCodingModule::Create(0)),
96       acm_ref_primary_(AudioCodingModule::Create(1)),
97       acm_ref_secondary_(AudioCodingModule::Create(2)),
98       payload_ref_is_stored_(),
99       payload_dual_is_stored_(),
100       timestamp_ref_(),
101       num_received_payloads_dual_(),
102       num_received_payloads_ref_(),
103       num_compared_payloads_(),
104       last_timestamp_(),
105       received_payload_() {}
106
107 DualStreamTest::~DualStreamTest() {}
108
109 void DualStreamTest::PopulateCodecInstances(int frame_size_primary_ms,
110                                             int num_channels_primary,
111                                             int sampling_rate) {
112   CodecInst my_codec;
113
114   // Invalid values. To check later on if the codec are found in the database.
115   primary_encoder_.pltype = -1;
116   secondary_encoder_.pltype = -1;
117   red_encoder_.pltype = -1;
118
119   for (int n = 0; n < AudioCodingModule::NumberOfCodecs(); n++) {
120     AudioCodingModule::Codec(n, &my_codec);
121     if (strcmp(my_codec.plname, "ISAC") == 0
122         && my_codec.plfreq == sampling_rate) {
123       my_codec.rate = 32000;
124       my_codec.pacsize = 30 * sampling_rate / 1000;
125       memcpy(&secondary_encoder_, &my_codec, sizeof(my_codec));
126     } else if (strcmp(my_codec.plname, "L16") == 0
127         && my_codec.channels == num_channels_primary
128         && my_codec.plfreq == sampling_rate) {
129       my_codec.pacsize = frame_size_primary_ms * sampling_rate / 1000;
130       memcpy(&primary_encoder_, &my_codec, sizeof(my_codec));
131     } else if (strcmp(my_codec.plname, "red") == 0) {
132       memcpy(&red_encoder_, &my_codec, sizeof(my_codec));
133     }
134   }
135
136   ASSERT_GE(primary_encoder_.pltype, 0);
137   ASSERT_GE(secondary_encoder_.pltype, 0);
138   ASSERT_GE(red_encoder_.pltype, 0);
139 }
140
141 void DualStreamTest::InitializeSender(int frame_size_primary_samples,
142                                       int num_channels_primary,
143                                       int sampling_rate) {
144   ASSERT_TRUE(acm_dual_stream_.get() != NULL);
145   ASSERT_TRUE(acm_ref_primary_.get() != NULL);
146   ASSERT_TRUE(acm_ref_secondary_.get() != NULL);
147
148   ASSERT_EQ(0, acm_dual_stream_->InitializeSender());
149   ASSERT_EQ(0, acm_ref_primary_->InitializeSender());
150   ASSERT_EQ(0, acm_ref_secondary_->InitializeSender());
151
152   PopulateCodecInstances(frame_size_primary_samples, num_channels_primary,
153                          sampling_rate);
154
155   ASSERT_EQ(0, acm_ref_primary_->RegisterSendCodec(primary_encoder_));
156   ASSERT_EQ(0, acm_ref_secondary_->RegisterSendCodec(secondary_encoder_));
157   ASSERT_EQ(0, acm_dual_stream_->RegisterSendCodec(primary_encoder_));
158   ASSERT_EQ(0,
159             acm_dual_stream_->RegisterSecondarySendCodec(secondary_encoder_));
160
161   ASSERT_EQ(0, acm_ref_primary_->RegisterTransportCallback(this));
162   ASSERT_EQ(0, acm_ref_secondary_->RegisterTransportCallback(this));
163   ASSERT_EQ(0, acm_dual_stream_->RegisterTransportCallback(this));
164 }
165
166 void DualStreamTest::Perform(bool start_in_sync, int num_channels_input) {
167   PCMFile pcm_file;
168   std::string file_name = test::ResourcePath(
169       (num_channels_input == 1) ?
170           "audio_coding/testfile32kHz" : "audio_coding/teststereo32kHz",
171       "pcm");
172   pcm_file.Open(file_name, 32000, "rb");
173   pcm_file.ReadStereo(num_channels_input == 2);
174   AudioFrame audio_frame;
175
176   int tolerance = 0;
177   if (num_channels_input == 2 && primary_encoder_.channels == 2
178       && secondary_encoder_.channels == 1) {
179     tolerance = 12;
180   }
181
182   if (!start_in_sync) {
183     pcm_file.Read10MsData(audio_frame);
184     // Unregister secondary codec and feed only the primary
185     acm_dual_stream_->UnregisterSecondarySendCodec();
186     EXPECT_EQ(0, acm_dual_stream_->Add10MsData(audio_frame));
187     EXPECT_EQ(0, acm_ref_primary_->Add10MsData(audio_frame));
188     ASSERT_EQ(0,
189               acm_dual_stream_->RegisterSecondarySendCodec(secondary_encoder_));
190   }
191
192   const int kNumFramesToProcess = 100;
193   int frame_cntr = 0;
194   while (!pcm_file.EndOfFile() && frame_cntr < kNumFramesToProcess) {
195     pcm_file.Read10MsData(audio_frame);
196     frame_cntr++;
197     EXPECT_EQ(0, acm_dual_stream_->Add10MsData(audio_frame));
198     EXPECT_EQ(0, acm_ref_primary_->Add10MsData(audio_frame));
199     EXPECT_EQ(0, acm_ref_secondary_->Add10MsData(audio_frame));
200
201     EXPECT_GE(acm_dual_stream_->Process(), 0);
202     EXPECT_GE(acm_ref_primary_->Process(), 0);
203     EXPECT_GE(acm_ref_secondary_->Process(), 0);
204
205     if (start_in_sync || frame_cntr > 7) {
206       // If we haven't started in sync the first few audio frames might
207       // slightly differ due to the difference in the state of the resamplers
208       // of dual-ACM and reference-ACM.
209       Validate(start_in_sync, tolerance);
210     } else {
211       // SendData stores the payloads, if we are not comparing we have to free
212       // the space by resetting these flags.
213       memset(payload_ref_is_stored_, 0, sizeof(payload_ref_is_stored_));
214       memset(payload_dual_is_stored_, 0, sizeof(payload_dual_is_stored_));
215     }
216   }
217   pcm_file.Close();
218
219   // Make sure that number of received payloads match. In case of secondary
220   // encoder, the dual-stream might deliver one lesser payload. The reason is
221   // that some secondary payloads are stored to be sent with a payload generated
222   // later and the input file may end before the "next" payload .
223   EXPECT_EQ(num_received_payloads_ref_[kPrimary],
224             num_received_payloads_dual_[kPrimary]);
225   EXPECT_TRUE(
226       num_received_payloads_ref_[kSecondary]
227           == num_received_payloads_dual_[kSecondary]
228           || num_received_payloads_ref_[kSecondary]
229               == (num_received_payloads_dual_[kSecondary] + 1));
230
231   // Make sure all received payloads are compared.
232   if (start_in_sync) {
233     EXPECT_EQ(num_received_payloads_dual_[kPrimary],
234               num_compared_payloads_[kPrimary]);
235     EXPECT_EQ(num_received_payloads_dual_[kSecondary],
236               num_compared_payloads_[kSecondary]);
237   } else {
238     // In asynchronous test we don't compare couple of first frames, so we
239     // should account for them in our counting.
240     EXPECT_GE(num_compared_payloads_[kPrimary],
241               num_received_payloads_dual_[kPrimary] - 4);
242     EXPECT_GE(num_compared_payloads_[kSecondary],
243               num_received_payloads_dual_[kSecondary] - 4);
244   }
245 }
246
247 bool DualStreamTest::EqualTimestamp(int stream_index, int position) {
248   if (timestamp_dual_[stream_index][position]
249       != timestamp_ref_[stream_index][position]) {
250     return false;
251   }
252   return true;
253 }
254
255 int DualStreamTest::EqualPayloadLength(int stream_index, int position) {
256   return abs(
257       payload_len_dual_[stream_index][position]
258           - payload_len_ref_[stream_index][position]);
259 }
260
261 bool DualStreamTest::EqualPayloadData(int stream_index, int position) {
262   assert(
263       payload_len_dual_[stream_index][position]
264           == payload_len_ref_[stream_index][position]);
265   int offset = position * MAX_PAYLOAD_SIZE_BYTE;
266   for (int n = 0; n < payload_len_dual_[stream_index][position]; n++) {
267     if (payload_data_dual_[stream_index][offset + n]
268         != payload_data_ref_[stream_index][offset + n]) {
269       return false;
270     }
271   }
272   return true;
273 }
274
275 void DualStreamTest::Validate(bool start_in_sync, int tolerance) {
276   for (int stream_index = 0; stream_index < kMaxNumStreams; stream_index++) {
277     int my_tolerance = stream_index == kPrimary ? 0 : tolerance;
278     for (int position = 0; position < kMaxNumStoredPayloads; position++) {
279       if (payload_ref_is_stored_[stream_index][position] == 1
280           && payload_dual_is_stored_[stream_index][position] == 1) {
281         // Check timestamps only if codecs started in sync or it is primary.
282         if (start_in_sync || stream_index == 0)
283           EXPECT_TRUE(EqualTimestamp(stream_index, position));
284         EXPECT_LE(EqualPayloadLength(stream_index, position), my_tolerance);
285         if (my_tolerance == 0)
286           EXPECT_TRUE(EqualPayloadData(stream_index, position));
287         num_compared_payloads_[stream_index]++;
288         payload_ref_is_stored_[stream_index][position] = 0;
289         payload_dual_is_stored_[stream_index][position] = 0;
290       }
291     }
292   }
293 }
294
295 int32_t DualStreamTest::SendData(FrameType frameType, uint8_t payload_type,
296                                  uint32_t timestamp,
297                                  const uint8_t* payload_data,
298                                  uint16_t payload_size,
299                                  const RTPFragmentationHeader* fragmentation) {
300   int position;
301   int stream_index;
302
303   if (payload_type == red_encoder_.pltype) {
304     if (fragmentation == NULL) {
305       assert(false);
306       return -1;
307     }
308     // As the oldest payloads are in the higher indices of fragmentation,
309     // to be able to check the increment of timestamps are correct we loop
310     // backward.
311     for (int n = fragmentation->fragmentationVectorSize - 1; n >= 0; --n) {
312       if (fragmentation->fragmentationPlType[n] == primary_encoder_.pltype) {
313         // Received primary payload from dual stream.
314         stream_index = kPrimary;
315       } else if (fragmentation->fragmentationPlType[n]
316           == secondary_encoder_.pltype) {
317         // Received secondary payload from dual stream.
318         stream_index = kSecondary;
319       } else {
320         assert(false);
321         return -1;
322       }
323       num_received_payloads_dual_[stream_index]++;
324       if (payload_dual_is_stored_[stream_index][0] == 0) {
325         position = 0;
326       } else if (payload_dual_is_stored_[stream_index][1] == 0) {
327         position = 1;
328       } else {
329         assert(false);
330         return -1;
331       }
332       timestamp_dual_[stream_index][position] = timestamp
333           - fragmentation->fragmentationTimeDiff[n];
334       payload_len_dual_[stream_index][position] = fragmentation
335           ->fragmentationLength[n];
336       memcpy(
337           &payload_data_dual_[stream_index][position * MAX_PAYLOAD_SIZE_BYTE],
338           &payload_data[fragmentation->fragmentationOffset[n]],
339           fragmentation->fragmentationLength[n]);
340       payload_dual_is_stored_[stream_index][position] = 1;
341       // Check if timestamps are incremented correctly.
342       if (received_payload_[stream_index]) {
343         int t = timestamp_dual_[stream_index][position]
344             - last_timestamp_[stream_index];
345         if ((stream_index == kPrimary) && (t != primary_encoder_.pacsize)) {
346           assert(false);
347           return -1;
348         }
349         if ((stream_index == kSecondary) && (t != secondary_encoder_.pacsize)) {
350           assert(false);
351           return -1;
352         }
353       } else {
354         received_payload_[stream_index] = true;
355       }
356       last_timestamp_[stream_index] = timestamp_dual_[stream_index][position];
357     }
358   } else {
359     if (fragmentation != NULL) {
360       assert(false);
361       return -1;
362     }
363     if (payload_type == primary_encoder_.pltype) {
364       stream_index = kPrimary;
365     } else if (payload_type == secondary_encoder_.pltype) {
366       stream_index = kSecondary;
367     } else {
368       assert(false);
369       return -1;
370     }
371     num_received_payloads_ref_[stream_index]++;
372     if (payload_ref_is_stored_[stream_index][0] == 0) {
373       position = 0;
374     } else if (payload_ref_is_stored_[stream_index][1] == 0) {
375       position = 1;
376     } else {
377       assert(false);
378       return -1;
379     }
380     timestamp_ref_[stream_index][position] = timestamp;
381     payload_len_ref_[stream_index][position] = payload_size;
382     memcpy(&payload_data_ref_[stream_index][position * MAX_PAYLOAD_SIZE_BYTE],
383            payload_data, payload_size);
384     payload_ref_is_stored_[stream_index][position] = 1;
385   }
386   return 0;
387 }
388
389 // Mono input, mono primary WB 20 ms frame.
390 TEST_F(DualStreamTest,
391        DISABLED_ON_ANDROID(BitExactSyncMonoInputMonoPrimaryWb20Ms)) {
392   InitializeSender(20, 1, 16000);
393   Perform(true, 1);
394 }
395
396 // Mono input, stereo primary WB 20 ms frame.
397 TEST_F(DualStreamTest,
398        DISABLED_ON_ANDROID(BitExactSyncMonoInput_StereoPrimaryWb20Ms)) {
399   InitializeSender(20, 2, 16000);
400   Perform(true, 1);
401 }
402
403 // Mono input, mono primary SWB 20 ms frame.
404 TEST_F(DualStreamTest,
405        DISABLED_ON_ANDROID(BitExactSyncMonoInputMonoPrimarySwb20Ms)) {
406   InitializeSender(20, 1, 32000);
407   Perform(true, 1);
408 }
409
410 // Mono input, stereo primary SWB 20 ms frame.
411 TEST_F(DualStreamTest,
412        DISABLED_ON_ANDROID(BitExactSyncMonoInputStereoPrimarySwb20Ms)) {
413   InitializeSender(20, 2, 32000);
414   Perform(true, 1);
415 }
416
417 // Mono input, mono primary WB 40 ms frame.
418 TEST_F(DualStreamTest,
419        DISABLED_ON_ANDROID(BitExactSyncMonoInputMonoPrimaryWb40Ms)) {
420   InitializeSender(40, 1, 16000);
421   Perform(true, 1);
422 }
423
424 // Mono input, stereo primary WB 40 ms frame
425 TEST_F(DualStreamTest,
426        DISABLED_ON_ANDROID(BitExactSyncMonoInputStereoPrimaryWb40Ms)) {
427   InitializeSender(40, 2, 16000);
428   Perform(true, 1);
429 }
430
431 // Stereo input, mono primary WB 20 ms frame.
432 TEST_F(DualStreamTest,
433        DISABLED_ON_ANDROID(BitExactSyncStereoInputMonoPrimaryWb20Ms)) {
434   InitializeSender(20, 1, 16000);
435   Perform(true, 2);
436 }
437
438 // Stereo input, stereo primary WB 20 ms frame.
439 TEST_F(DualStreamTest,
440        DISABLED_ON_ANDROID(BitExactSyncStereoInputStereoPrimaryWb20Ms)) {
441   InitializeSender(20, 2, 16000);
442   Perform(true, 2);
443 }
444
445 // Stereo input, mono primary SWB 20 ms frame.
446 TEST_F(DualStreamTest,
447        DISABLED_ON_ANDROID(BitExactSyncStereoInputMonoPrimarySwb20Ms)) {
448   InitializeSender(20, 1, 32000);
449   Perform(true, 2);
450 }
451
452 // Stereo input, stereo primary SWB 20 ms frame.
453 TEST_F(DualStreamTest,
454        DISABLED_ON_ANDROID(BitExactSyncStereoInputStereoPrimarySwb20Ms)) {
455   InitializeSender(20, 2, 32000);
456   Perform(true, 2);
457 }
458
459 // Stereo input, mono primary WB 40 ms frame.
460 TEST_F(DualStreamTest,
461        DISABLED_ON_ANDROID(BitExactSyncStereoInputMonoPrimaryWb40Ms)) {
462   InitializeSender(40, 1, 16000);
463   Perform(true, 2);
464 }
465
466 // Stereo input, stereo primary WB 40 ms frame.
467 TEST_F(DualStreamTest,
468        DISABLED_ON_ANDROID(BitExactSyncStereoInputStereoPrimaryWb40Ms)) {
469   InitializeSender(40, 2, 16000);
470   Perform(true, 2);
471 }
472
473 // Asynchronous test, ACM is fed with data then secondary coder is registered.
474 // Mono input, mono primary WB 20 ms frame.
475 TEST_F(DualStreamTest,
476        DISABLED_ON_ANDROID(BitExactAsyncMonoInputMonoPrimaryWb20Ms)) {
477   InitializeSender(20, 1, 16000);
478   Perform(false, 1);
479 }
480
481 // Mono input, mono primary WB 20 ms frame.
482 TEST_F(DualStreamTest,
483        DISABLED_ON_ANDROID(BitExactAsyncMonoInputMonoPrimaryWb40Ms)) {
484   InitializeSender(40, 1, 16000);
485   Perform(false, 1);
486 }
487
488 TEST_F(DualStreamTest, DISABLED_ON_ANDROID(Api)) {
489   PopulateCodecInstances(20, 1, 16000);
490   CodecInst my_codec;
491   ASSERT_EQ(0, acm_dual_stream_->InitializeSender());
492   ASSERT_EQ(-1, acm_dual_stream_->SecondarySendCodec(&my_codec));
493
494   // Not allowed to register secondary codec if primary is not registered yet.
495   ASSERT_EQ(-1,
496       acm_dual_stream_->RegisterSecondarySendCodec(secondary_encoder_));
497   ASSERT_EQ(-1, acm_dual_stream_->SecondarySendCodec(&my_codec));
498
499   ASSERT_EQ(0, acm_dual_stream_->RegisterSendCodec(primary_encoder_));
500
501   ASSERT_EQ(0, acm_dual_stream_->SetVAD(true, true, VADNormal));
502
503   // Make sure vad is activated.
504   bool vad_status;
505   bool dtx_status;
506   ACMVADMode vad_mode;
507   EXPECT_EQ(0, acm_dual_stream_->VAD(&vad_status, &dtx_status, &vad_mode));
508   EXPECT_TRUE(vad_status);
509   EXPECT_TRUE(dtx_status);
510   EXPECT_EQ(VADNormal, vad_mode);
511
512   ASSERT_EQ(0,
513       acm_dual_stream_->RegisterSecondarySendCodec(secondary_encoder_));
514
515   ASSERT_EQ(0, acm_dual_stream_->SecondarySendCodec(&my_codec));
516   ASSERT_EQ(0, memcmp(&my_codec, &secondary_encoder_, sizeof(my_codec)));
517
518   // Test if VAD get disabled after registering secondary codec.
519   EXPECT_EQ(0, acm_dual_stream_->VAD(&vad_status, &dtx_status, &vad_mode));
520   EXPECT_FALSE(vad_status);
521   EXPECT_FALSE(dtx_status);
522
523   // Activating VAD should fail.
524   ASSERT_EQ(-1, acm_dual_stream_->SetVAD(true, true, VADNormal));
525
526   // Unregister secondary encoder and it should be possible to activate VAD.
527   acm_dual_stream_->UnregisterSecondarySendCodec();
528   // Should fail.
529   ASSERT_EQ(-1, acm_dual_stream_->SecondarySendCodec(&my_codec));
530
531   ASSERT_EQ(0, acm_dual_stream_->SetVAD(true, true, VADVeryAggr));
532   // Make sure VAD is activated.
533   EXPECT_EQ(0, acm_dual_stream_->VAD(&vad_status, &dtx_status, &vad_mode));
534   EXPECT_TRUE(vad_status);
535   EXPECT_TRUE(dtx_status);
536   EXPECT_EQ(VADVeryAggr, vad_mode);
537 }
538
539 }  // namespace webrtc