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
113e6db2321ccdc8738c9cecbe9bdab13d4f0f658dkjellander#include "webrtc/modules/audio_coding/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"
203e6db2321ccdc8738c9cecbe9bdab13d4f0f658dkjellander#include "webrtc/modules/audio_coding/include/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),
34dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting      input_block_size_samples_(
35dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting          static_cast<size_t>(source_rate_hz_ * kBlockSizeMs / 1000)),
360e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org      codec_registered_(false),
370e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org      test_duration_ms_(test_duration_ms),
380e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org      frame_type_(kAudioFrameSpeech),
390e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org      payload_type_(0),
400e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org      timestamp_(0),
410e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org      sequence_number_(0) {
420e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  input_frame_.sample_rate_hz_ = source_rate_hz_;
430e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  input_frame_.num_channels_ = 1;
440e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  input_frame_.samples_per_channel_ = input_block_size_samples_;
450e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  assert(input_block_size_samples_ * input_frame_.num_channels_ <=
460e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org         AudioFrame::kMaxDataSizeSamples);
470e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  acm_->RegisterTransportCallback(this);
480e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org}
490e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org
500e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.orgbool AcmSendTestOldApi::RegisterCodec(const char* payload_name,
510e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org                                      int sampling_freq_hz,
520e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org                                      int channels,
530e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org                                      int payload_type,
540e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org                                      int frame_size_samples) {
557e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wiberg  CodecInst codec;
5691d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_CHECK_EQ(0, AudioCodingModule::Codec(payload_name, &codec,
5791d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg                                           sampling_freq_hz, channels));
587e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wiberg  codec.pltype = payload_type;
597e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wiberg  codec.pacsize = frame_size_samples;
607e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wiberg  codec_registered_ = (acm_->RegisterSendCodec(codec) == 0);
610e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  input_frame_.num_channels_ = channels;
620e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  assert(input_block_size_samples_ * input_frame_.num_channels_ <=
630e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org         AudioFrame::kMaxDataSizeSamples);
640e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  return codec_registered_;
650e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org}
660e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org
677e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wibergbool AcmSendTestOldApi::RegisterExternalCodec(
6812cfc9b4dacd6942377df1f29a64bdbec591920ekwiberg    AudioEncoder* external_speech_encoder) {
697e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wiberg  acm_->RegisterExternalSendCodec(external_speech_encoder);
707e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wiberg  input_frame_.num_channels_ = external_speech_encoder->NumChannels();
717e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wiberg  assert(input_block_size_samples_ * input_frame_.num_channels_ <=
727e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wiberg         AudioFrame::kMaxDataSizeSamples);
737e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wiberg  return codec_registered_ = true;
747e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wiberg}
757e0c7d49ea45e3e6743ca9cfafba337c04eae657Karl Wiberg
760e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.orgPacket* AcmSendTestOldApi::NextPacket() {
770e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  assert(codec_registered_);
780e81fdf5d2c2665bc3d23e07cfd9ea7f7d36aed9pkasting@chromium.org  if (filter_.test(static_cast<size_t>(payload_type_))) {
790e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    // This payload type should be filtered out. Since the payload type is the
800e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    // same throughout the whole test run, no packet at all will be delivered.
810e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    // We can just as well signal that the test is over by returning NULL.
820e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    return NULL;
830e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  }
840e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  // Insert audio and process until one packet is produced.
850e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  while (clock_.TimeInMilliseconds() < test_duration_ms_) {
860e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    clock_.AdvanceTimeMilliseconds(kBlockSizeMs);
8791d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_CHECK(
8891d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg        audio_source_->Read(input_block_size_samples_, input_frame_.data_));
890e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    if (input_frame_.num_channels_ > 1) {
900e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org      InputAudioFile::DuplicateInterleaved(input_frame_.data_,
910e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org                                           input_block_size_samples_,
920e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org                                           input_frame_.num_channels_,
930e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org                                           input_frame_.data_);
940e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    }
95f56c1623103e3f72198d6b0f50de9f0585b6f52fhenrik.lundin@webrtc.org    data_to_send_ = false;
9691d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_CHECK_GE(acm_->Add10MsData(input_frame_), 0);
97b7e5054414ff524f9db81dab7917729b8c4c8bcbPeter Kasting    input_frame_.timestamp_ += static_cast<uint32_t>(input_block_size_samples_);
98f56c1623103e3f72198d6b0f50de9f0585b6f52fhenrik.lundin@webrtc.org    if (data_to_send_) {
990e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org      // Encoded packet received.
1000e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org      return CreatePacket();
1010e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    }
1020e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  }
1030e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  // Test ended.
1040e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  return NULL;
1050e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org}
1060e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org
1070e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org// This method receives the callback from ACM when a new packet is produced.
1080e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.orgint32_t AcmSendTestOldApi::SendData(
1090e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    FrameType frame_type,
1100e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    uint8_t payload_type,
1110e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    uint32_t timestamp,
1120e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    const uint8_t* payload_data,
1134591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org    size_t payload_len_bytes,
1140e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org    const RTPFragmentationHeader* fragmentation) {
1150e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  // Store the packet locally.
1160e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  frame_type_ = frame_type;
1170e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  payload_type_ = payload_type;
1180e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  timestamp_ = timestamp;
1190e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  last_payload_vec_.assign(payload_data, payload_data + payload_len_bytes);
1200e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  assert(last_payload_vec_.size() == payload_len_bytes);
121f56c1623103e3f72198d6b0f50de9f0585b6f52fhenrik.lundin@webrtc.org  data_to_send_ = true;
1220e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  return 0;
1230e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org}
1240e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org
1250e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.orgPacket* AcmSendTestOldApi::CreatePacket() {
1260e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  const size_t kRtpHeaderSize = 12;
1270e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  size_t allocated_bytes = last_payload_vec_.size() + kRtpHeaderSize;
1280e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  uint8_t* packet_memory = new uint8_t[allocated_bytes];
1290e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  // Populate the header bytes.
1300e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  packet_memory[0] = 0x80;
1310e81fdf5d2c2665bc3d23e07cfd9ea7f7d36aed9pkasting@chromium.org  packet_memory[1] = static_cast<uint8_t>(payload_type_);
1320e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  packet_memory[2] = (sequence_number_ >> 8) & 0xFF;
1330e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  packet_memory[3] = (sequence_number_) & 0xFF;
1340e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  packet_memory[4] = (timestamp_ >> 24) & 0xFF;
1350e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  packet_memory[5] = (timestamp_ >> 16) & 0xFF;
1360e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  packet_memory[6] = (timestamp_ >> 8) & 0xFF;
1370e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  packet_memory[7] = timestamp_ & 0xFF;
1380e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  // Set SSRC to 0x12345678.
1390e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  packet_memory[8] = 0x12;
1400e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  packet_memory[9] = 0x34;
1410e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  packet_memory[10] = 0x56;
1420e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  packet_memory[11] = 0x78;
1430e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org
1440e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  ++sequence_number_;
1450e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org
1460e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  // Copy the payload data.
1470e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  memcpy(packet_memory + kRtpHeaderSize,
1480e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org         &last_payload_vec_[0],
1490e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org         last_payload_vec_.size());
1500e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  Packet* packet =
1510e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org      new Packet(packet_memory, allocated_bytes, clock_.TimeInMilliseconds());
1520e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  assert(packet);
1530e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  assert(packet->valid_header());
1540e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org  return packet;
1550e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org}
1560e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org
1570e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org}  // namespace test
1580e6e4d2ff2dc3458ad74aa994a106481df198cd2henrik.lundin@webrtc.org}  // namespace webrtc
159