1b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org/*
2b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
3b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org *
4b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org *  Use of this source code is governed by a BSD-style license
5b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org *  that can be found in the LICENSE file in the root of the source
6b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org *  tree. An additional intellectual property rights grant can be found
7b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org *  in the file PATENTS.  All contributing project authors may
8b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org */
10b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org
11b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/main/acm2/acm_send_test.h"
12b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org
13b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org#include <assert.h>
14b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org#include <stdio.h>
15b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org#include <string.h>
16b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org
17b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org#include "testing/gtest/include/gtest/gtest.h"
18b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org#include "webrtc/base/checks.h"
19b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
20b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h"
21b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/neteq/tools/packet.h"
22b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org
23b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.orgnamespace webrtc {
24b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.orgnamespace test {
25b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org
26b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.orgAcmSendTest::AcmSendTest(InputAudioFile* audio_source,
27b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org                         int source_rate_hz,
28b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org                         int test_duration_ms)
29b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org    : clock_(0),
30b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org      audio_source_(audio_source),
31b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org      source_rate_hz_(source_rate_hz),
32b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org      input_block_size_samples_(source_rate_hz_ * kBlockSizeMs / 1000),
33b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org      codec_registered_(false),
34b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org      test_duration_ms_(test_duration_ms),
35b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org      frame_type_(kAudioFrameSpeech),
36b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org      payload_type_(0),
37b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org      timestamp_(0),
38b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org      sequence_number_(0) {
39e0eadc5159180ccc0b3e8f461e0c45d5c03507adhenrik.lundin@webrtc.org  webrtc::AudioCoding::Config config;
40e0eadc5159180ccc0b3e8f461e0c45d5c03507adhenrik.lundin@webrtc.org  config.clock = &clock_;
41e0eadc5159180ccc0b3e8f461e0c45d5c03507adhenrik.lundin@webrtc.org  config.transport = this;
42e0eadc5159180ccc0b3e8f461e0c45d5c03507adhenrik.lundin@webrtc.org  acm_.reset(webrtc::AudioCoding::Create(config));
43b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  input_frame_.sample_rate_hz_ = source_rate_hz_;
44b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  input_frame_.num_channels_ = 1;
45b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  input_frame_.samples_per_channel_ = input_block_size_samples_;
46b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  assert(input_block_size_samples_ * input_frame_.num_channels_ <=
47b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org         AudioFrame::kMaxDataSizeSamples);
48b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org}
49b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org
50e0eadc5159180ccc0b3e8f461e0c45d5c03507adhenrik.lundin@webrtc.orgbool AcmSendTest::RegisterCodec(int codec_type,
51b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org                                int channels,
52b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org                                int payload_type,
53b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org                                int frame_size_samples) {
54e0eadc5159180ccc0b3e8f461e0c45d5c03507adhenrik.lundin@webrtc.org  codec_registered_ =
55e0eadc5159180ccc0b3e8f461e0c45d5c03507adhenrik.lundin@webrtc.org      acm_->RegisterSendCodec(codec_type, payload_type, frame_size_samples);
56b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  input_frame_.num_channels_ = channels;
57b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  assert(input_block_size_samples_ * input_frame_.num_channels_ <=
58b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org         AudioFrame::kMaxDataSizeSamples);
59b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  return codec_registered_;
60b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org}
61b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org
62b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.orgPacket* AcmSendTest::NextPacket() {
63b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  assert(codec_registered_);
64b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  if (filter_.test(payload_type_)) {
65b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org    // This payload type should be filtered out. Since the payload type is the
66b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org    // same throughout the whole test run, no packet at all will be delivered.
67b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org    // We can just as well signal that the test is over by returning NULL.
68b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org    return NULL;
69b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  }
70b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  // Insert audio and process until one packet is produced.
71b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  while (clock_.TimeInMilliseconds() < test_duration_ms_) {
72b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org    clock_.AdvanceTimeMilliseconds(kBlockSizeMs);
7354ade8bbee7cea004418c02de3658ffc870fc968andrew@webrtc.org    CHECK(audio_source_->Read(input_block_size_samples_, input_frame_.data_));
7419e318606e36fcecd718e3bdb5082d5b781b0332henrik.lundin@webrtc.org    if (input_frame_.num_channels_ > 1) {
7519e318606e36fcecd718e3bdb5082d5b781b0332henrik.lundin@webrtc.org      InputAudioFile::DuplicateInterleaved(input_frame_.data_,
7619e318606e36fcecd718e3bdb5082d5b781b0332henrik.lundin@webrtc.org                                           input_block_size_samples_,
7719e318606e36fcecd718e3bdb5082d5b781b0332henrik.lundin@webrtc.org                                           input_frame_.num_channels_,
7819e318606e36fcecd718e3bdb5082d5b781b0332henrik.lundin@webrtc.org                                           input_frame_.data_);
7919e318606e36fcecd718e3bdb5082d5b781b0332henrik.lundin@webrtc.org    }
80e0eadc5159180ccc0b3e8f461e0c45d5c03507adhenrik.lundin@webrtc.org    int32_t encoded_bytes = acm_->Add10MsAudio(input_frame_);
81e0eadc5159180ccc0b3e8f461e0c45d5c03507adhenrik.lundin@webrtc.org    EXPECT_GE(encoded_bytes, 0);
82b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org    input_frame_.timestamp_ += input_block_size_samples_;
83b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org    if (encoded_bytes > 0) {
84b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org      // Encoded packet received.
85b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org      return CreatePacket();
86b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org    }
87b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  }
88b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  // Test ended.
89b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  return NULL;
90b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org}
91b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org
92b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org// This method receives the callback from ACM when a new packet is produced.
93b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.orgint32_t AcmSendTest::SendData(FrameType frame_type,
94b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org                              uint8_t payload_type,
95b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org                              uint32_t timestamp,
96b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org                              const uint8_t* payload_data,
97b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org                              uint16_t payload_len_bytes,
98b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org                              const RTPFragmentationHeader* fragmentation) {
99b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  // Store the packet locally.
100b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  frame_type_ = frame_type;
101b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  payload_type_ = payload_type;
102b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  timestamp_ = timestamp;
103b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  last_payload_vec_.assign(payload_data, payload_data + payload_len_bytes);
104b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  assert(last_payload_vec_.size() == payload_len_bytes);
105b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  return 0;
106b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org}
107b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org
108b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.orgPacket* AcmSendTest::CreatePacket() {
109b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  const size_t kRtpHeaderSize = 12;
110b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  size_t allocated_bytes = last_payload_vec_.size() + kRtpHeaderSize;
111b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  uint8_t* packet_memory = new uint8_t[allocated_bytes];
112b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  // Populate the header bytes.
113b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  packet_memory[0] = 0x80;
114b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  packet_memory[1] = payload_type_;
115b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  packet_memory[2] = (sequence_number_ >> 8) & 0xFF;
116b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  packet_memory[3] = (sequence_number_) & 0xFF;
117b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  packet_memory[4] = (timestamp_ >> 24) & 0xFF;
118b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  packet_memory[5] = (timestamp_ >> 16) & 0xFF;
119b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  packet_memory[6] = (timestamp_ >> 8) & 0xFF;
120b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  packet_memory[7] = timestamp_ & 0xFF;
121b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  // Set SSRC to 0x12345678.
122b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  packet_memory[8] = 0x12;
123b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  packet_memory[9] = 0x34;
124b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  packet_memory[10] = 0x56;
125b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  packet_memory[11] = 0x78;
126b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org
127b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  ++sequence_number_;
128b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org
129b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  // Copy the payload data.
130b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  memcpy(packet_memory + kRtpHeaderSize,
131b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org         &last_payload_vec_[0],
132b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org         last_payload_vec_.size());
133b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  Packet* packet =
134b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org      new Packet(packet_memory, allocated_bytes, clock_.TimeInMilliseconds());
135b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  assert(packet);
136b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  assert(packet->valid_header());
137b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org  return packet;
138b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org}
139b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org
140b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org}  // namespace test
141b9a0168ddca289b1d669383a0607d69385a83554henrik.lundin@webrtc.org}  // namespace webrtc
142