acm_send_test_oldapi.cc revision b7e5054414ff524f9db81dab7917729b8c4c8bcb
10e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org/*
20e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
30e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org *
40e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org *  Use of this source code is governed by a BSD-style license
50e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org *  that can be found in the LICENSE file in the root of the source
60e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org *  tree. An additional intellectual property rights grant can be found
70e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org *  in the file PATENTS.  All contributing project authors may
80e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
90e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org */
100e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org
110e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/main/acm2/acm_send_test_oldapi.h"
120e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org
130e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org#include <assert.h>
140e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org#include <stdio.h>
150e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org#include <string.h>
160e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org
170e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org#include "testing/gtest/include/gtest/gtest.h"
180e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org#include "webrtc/base/checks.h"
197e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wiberg#include "webrtc/modules/audio_coding/codecs/audio_encoder.h"
200e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
210e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h"
220e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/neteq/tools/packet.h"
230e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org
240e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.orgnamespace webrtc {
250e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.orgnamespace test {
260e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org
270e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.orgAcmSendTestOldApi::AcmSendTestOldApi(InputAudioFile* audio_source,
280e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org                                     int source_rate_hz,
290e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org                                     int test_duration_ms)
300e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    : clock_(0),
310e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org      acm_(webrtc::AudioCodingModule::Create(0, &clock_)),
320e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org      audio_source_(audio_source),
330e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org      source_rate_hz_(source_rate_hz),
340e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org      input_block_size_samples_(source_rate_hz_ * kBlockSizeMs / 1000),
350e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org      codec_registered_(false),
360e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org      test_duration_ms_(test_duration_ms),
370e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org      frame_type_(kAudioFrameSpeech),
380e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org      payload_type_(0),
390e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org      timestamp_(0),
400e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org      sequence_number_(0) {
410e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  input_frame_.sample_rate_hz_ = source_rate_hz_;
420e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  input_frame_.num_channels_ = 1;
430e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  input_frame_.samples_per_channel_ = input_block_size_samples_;
440e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  assert(input_block_size_samples_ * input_frame_.num_channels_ <=
450e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org         AudioFrame::kMaxDataSizeSamples);
460e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  acm_->RegisterTransportCallback(this);
470e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org}
480e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org
490e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.orgbool AcmSendTestOldApi::RegisterCodec(const char* payload_name,
500e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org                                      int sampling_freq_hz,
510e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org                                      int channels,
520e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org                                      int payload_type,
530e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org                                      int frame_size_samples) {
547e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wiberg  CodecInst codec;
557e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wiberg  CHECK_EQ(0, AudioCodingModule::Codec(payload_name, &codec, sampling_freq_hz,
567e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wiberg                                       channels));
577e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wiberg  codec.pltype = payload_type;
587e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wiberg  codec.pacsize = frame_size_samples;
597e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wiberg  codec_registered_ = (acm_->RegisterSendCodec(codec) == 0);
600e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  input_frame_.num_channels_ = channels;
610e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  assert(input_block_size_samples_ * input_frame_.num_channels_ <=
620e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org         AudioFrame::kMaxDataSizeSamples);
630e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  return codec_registered_;
640e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org}
650e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org
667e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wibergbool AcmSendTestOldApi::RegisterExternalCodec(
677e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wiberg    AudioEncoderMutable* external_speech_encoder) {
687e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wiberg  acm_->RegisterExternalSendCodec(external_speech_encoder);
697e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wiberg  input_frame_.num_channels_ = external_speech_encoder->NumChannels();
707e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wiberg  assert(input_block_size_samples_ * input_frame_.num_channels_ <=
717e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wiberg         AudioFrame::kMaxDataSizeSamples);
727e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wiberg  return codec_registered_ = true;
737e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wiberg}
747e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wiberg
750e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.orgPacket* AcmSendTestOldApi::NextPacket() {
760e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  assert(codec_registered_);
770e81fdf5d2c2665bc3d23e07cfd9ea7f7d36aed9pkasting@chromium.org  if (filter_.test(static_cast<size_t>(payload_type_))) {
780e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    // This payload type should be filtered out. Since the payload type is the
790e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    // same throughout the whole test run, no packet at all will be delivered.
800e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    // We can just as well signal that the test is over by returning NULL.
810e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    return NULL;
820e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  }
830e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  // Insert audio and process until one packet is produced.
840e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  while (clock_.TimeInMilliseconds() < test_duration_ms_) {
850e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    clock_.AdvanceTimeMilliseconds(kBlockSizeMs);
860e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    CHECK(audio_source_->Read(input_block_size_samples_, input_frame_.data_));
870e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    if (input_frame_.num_channels_ > 1) {
880e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org      InputAudioFile::DuplicateInterleaved(input_frame_.data_,
890e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org                                           input_block_size_samples_,
900e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org                                           input_frame_.num_channels_,
910e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org                                           input_frame_.data_);
920e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    }
93f56c1623103e3f72198d6b0f50de9f0585b6f52fhenrik.lundin@webrtc.org    data_to_send_ = false;
94f56c1623103e3f72198d6b0f50de9f0585b6f52fhenrik.lundin@webrtc.org    CHECK_GE(acm_->Add10MsData(input_frame_), 0);
95b7e5054414ff524f9db81dab7917729b8c4c8bcbPeter Kasting    input_frame_.timestamp_ += static_cast<uint32_t>(input_block_size_samples_);
96f56c1623103e3f72198d6b0f50de9f0585b6f52fhenrik.lundin@webrtc.org    if (data_to_send_) {
970e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org      // Encoded packet received.
980e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org      return CreatePacket();
990e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    }
1000e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  }
1010e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  // Test ended.
1020e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  return NULL;
1030e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org}
1040e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org
1050e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org// This method receives the callback from ACM when a new packet is produced.
1060e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.orgint32_t AcmSendTestOldApi::SendData(
1070e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    FrameType frame_type,
1080e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    uint8_t payload_type,
1090e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    uint32_t timestamp,
1100e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    const uint8_t* payload_data,
1114591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org    size_t payload_len_bytes,
1120e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    const RTPFragmentationHeader* fragmentation) {
1130e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  // Store the packet locally.
1140e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  frame_type_ = frame_type;
1150e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  payload_type_ = payload_type;
1160e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  timestamp_ = timestamp;
1170e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  last_payload_vec_.assign(payload_data, payload_data + payload_len_bytes);
1180e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  assert(last_payload_vec_.size() == payload_len_bytes);
119f56c1623103e3f72198d6b0f50de9f0585b6f52fhenrik.lundin@webrtc.org  data_to_send_ = true;
1200e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  return 0;
1210e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org}
1220e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org
1230e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.orgPacket* AcmSendTestOldApi::CreatePacket() {
1240e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  const size_t kRtpHeaderSize = 12;
1250e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  size_t allocated_bytes = last_payload_vec_.size() + kRtpHeaderSize;
1260e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  uint8_t* packet_memory = new uint8_t[allocated_bytes];
1270e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  // Populate the header bytes.
1280e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  packet_memory[0] = 0x80;
1290e81fdf5d2c2665bc3d23e07cfd9ea7f7d36aed9pkasting@chromium.org  packet_memory[1] = static_cast<uint8_t>(payload_type_);
1300e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  packet_memory[2] = (sequence_number_ >> 8) & 0xFF;
1310e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  packet_memory[3] = (sequence_number_) & 0xFF;
1320e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  packet_memory[4] = (timestamp_ >> 24) & 0xFF;
1330e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  packet_memory[5] = (timestamp_ >> 16) & 0xFF;
1340e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  packet_memory[6] = (timestamp_ >> 8) & 0xFF;
1350e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  packet_memory[7] = timestamp_ & 0xFF;
1360e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  // Set SSRC to 0x12345678.
1370e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  packet_memory[8] = 0x12;
1380e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  packet_memory[9] = 0x34;
1390e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  packet_memory[10] = 0x56;
1400e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  packet_memory[11] = 0x78;
1410e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org
1420e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  ++sequence_number_;
1430e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org
1440e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  // Copy the payload data.
1450e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  memcpy(packet_memory + kRtpHeaderSize,
1460e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org         &last_payload_vec_[0],
1470e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org         last_payload_vec_.size());
1480e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  Packet* packet =
1490e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org      new Packet(packet_memory, allocated_bytes, clock_.TimeInMilliseconds());
1500e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  assert(packet);
1510e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  assert(packet->valid_header());
1520e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  return packet;
1530e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org}
1540e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org
1550e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org}  // namespace test
1560e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org}  // namespace webrtc
157