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