Home | History | Annotate | Download | only in tools
      1 /*
      2  *  Copyright (c) 2014 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/modules/audio_coding/neteq/tools/neteq_performance_test.h"
     12 
     13 #include "webrtc/modules/audio_coding/codecs/pcm16b/include/pcm16b.h"
     14 #include "webrtc/modules/audio_coding/neteq/interface/neteq.h"
     15 #include "webrtc/modules/audio_coding/neteq/tools/audio_loop.h"
     16 #include "webrtc/modules/audio_coding/neteq/tools/rtp_generator.h"
     17 #include "webrtc/system_wrappers/interface/clock.h"
     18 #include "webrtc/test/testsupport/fileutils.h"
     19 #include "webrtc/typedefs.h"
     20 
     21 using webrtc::NetEq;
     22 using webrtc::test::AudioLoop;
     23 using webrtc::test::RtpGenerator;
     24 using webrtc::WebRtcRTPHeader;
     25 
     26 namespace webrtc {
     27 namespace test {
     28 
     29 int64_t NetEqPerformanceTest::Run(int runtime_ms,
     30                                   int lossrate,
     31                                   double drift_factor) {
     32   const std::string kInputFileName =
     33       webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
     34   const int kSampRateHz = 32000;
     35   const webrtc::NetEqDecoder kDecoderType = webrtc::kDecoderPCM16Bswb32kHz;
     36   const int kPayloadType = 95;
     37 
     38   // Initialize NetEq instance.
     39   NetEq::Config config;
     40   config.sample_rate_hz = kSampRateHz;
     41   NetEq* neteq = NetEq::Create(config);
     42   // Register decoder in |neteq|.
     43   if (neteq->RegisterPayloadType(kDecoderType, kPayloadType) != 0)
     44     return -1;
     45 
     46   // Set up AudioLoop object.
     47   AudioLoop audio_loop;
     48   const size_t kMaxLoopLengthSamples = kSampRateHz * 10;  // 10 second loop.
     49   const size_t kInputBlockSizeSamples = 60 * kSampRateHz / 1000;  // 60 ms.
     50   if (!audio_loop.Init(kInputFileName, kMaxLoopLengthSamples,
     51                        kInputBlockSizeSamples))
     52     return -1;
     53 
     54   int32_t time_now_ms = 0;
     55 
     56   // Get first input packet.
     57   WebRtcRTPHeader rtp_header;
     58   RtpGenerator rtp_gen(kSampRateHz / 1000);
     59   // Start with positive drift first half of simulation.
     60   rtp_gen.set_drift_factor(drift_factor);
     61   bool drift_flipped = false;
     62   int32_t packet_input_time_ms =
     63       rtp_gen.GetRtpHeader(kPayloadType, kInputBlockSizeSamples, &rtp_header);
     64   const int16_t* input_samples = audio_loop.GetNextBlock();
     65   if (!input_samples) exit(1);
     66   uint8_t input_payload[kInputBlockSizeSamples * sizeof(int16_t)];
     67   int payload_len = WebRtcPcm16b_Encode(const_cast<int16_t*>(input_samples),
     68                                         kInputBlockSizeSamples,
     69                                         input_payload);
     70   assert(payload_len == kInputBlockSizeSamples * sizeof(int16_t));
     71 
     72   // Main loop.
     73   webrtc::Clock* clock = webrtc::Clock::GetRealTimeClock();
     74   int64_t start_time_ms = clock->TimeInMilliseconds();
     75   while (time_now_ms < runtime_ms) {
     76     while (packet_input_time_ms <= time_now_ms) {
     77       // Drop every N packets, where N = FLAGS_lossrate.
     78       bool lost = false;
     79       if (lossrate > 0) {
     80         lost = ((rtp_header.header.sequenceNumber - 1) % lossrate) == 0;
     81       }
     82       if (!lost) {
     83         // Insert packet.
     84         int error = neteq->InsertPacket(
     85             rtp_header, input_payload, payload_len,
     86             packet_input_time_ms * kSampRateHz / 1000);
     87         if (error != NetEq::kOK)
     88           return -1;
     89       }
     90 
     91       // Get next packet.
     92       packet_input_time_ms = rtp_gen.GetRtpHeader(kPayloadType,
     93                                                   kInputBlockSizeSamples,
     94                                                   &rtp_header);
     95       input_samples = audio_loop.GetNextBlock();
     96       if (!input_samples) return -1;
     97       payload_len = WebRtcPcm16b_Encode(const_cast<int16_t*>(input_samples),
     98                                         kInputBlockSizeSamples,
     99                                         input_payload);
    100       assert(payload_len == kInputBlockSizeSamples * sizeof(int16_t));
    101     }
    102 
    103     // Get output audio, but don't do anything with it.
    104     static const int kMaxChannels = 1;
    105     static const int kMaxSamplesPerMs = 48000 / 1000;
    106     static const int kOutputBlockSizeMs = 10;
    107     static const int kOutDataLen = kOutputBlockSizeMs * kMaxSamplesPerMs *
    108         kMaxChannels;
    109     int16_t out_data[kOutDataLen];
    110     int num_channels;
    111     int samples_per_channel;
    112     int error = neteq->GetAudio(kOutDataLen, out_data, &samples_per_channel,
    113                                 &num_channels, NULL);
    114     if (error != NetEq::kOK)
    115       return -1;
    116 
    117     assert(samples_per_channel == kSampRateHz * 10 / 1000);
    118 
    119     time_now_ms += kOutputBlockSizeMs;
    120     if (time_now_ms >= runtime_ms / 2 && !drift_flipped) {
    121       // Apply negative drift second half of simulation.
    122       rtp_gen.set_drift_factor(-drift_factor);
    123       drift_flipped = true;
    124     }
    125   }
    126   int64_t end_time_ms = clock->TimeInMilliseconds();
    127   delete neteq;
    128   return end_time_ms - start_time_ms;
    129 }
    130 
    131 }  // namespace test
    132 }  // namespace webrtc
    133