blob: d5f196b9a2d229b87362d3509e5ff4b015a250d0 [file] [log] [blame]
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +00001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_coding/acm2/acm_send_test.h"
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000012
13#include <assert.h>
14#include <stdio.h>
15#include <string.h>
16
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "api/audio_codecs/audio_encoder.h"
18#include "modules/audio_coding/include/audio_coding_module.h"
19#include "modules/audio_coding/neteq/tools/input_audio_file.h"
20#include "modules/audio_coding/neteq/tools/packet.h"
21#include "rtc_base/checks.h"
22#include "test/gtest.h"
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000023
24namespace webrtc {
25namespace test {
26
27AcmSendTestOldApi::AcmSendTestOldApi(InputAudioFile* audio_source,
28 int source_rate_hz,
29 int test_duration_ms)
30 : clock_(0),
31 acm_(webrtc::AudioCodingModule::Create(0, &clock_)),
32 audio_source_(audio_source),
33 source_rate_hz_(source_rate_hz),
Peter Kastingdce40cf2015-08-24 14:52:23 -070034 input_block_size_samples_(
35 static_cast<size_t>(source_rate_hz_ * kBlockSizeMs / 1000)),
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000036 codec_registered_(false),
37 test_duration_ms_(test_duration_ms),
38 frame_type_(kAudioFrameSpeech),
39 payload_type_(0),
40 timestamp_(0),
41 sequence_number_(0) {
42 input_frame_.sample_rate_hz_ = source_rate_hz_;
43 input_frame_.num_channels_ = 1;
44 input_frame_.samples_per_channel_ = input_block_size_samples_;
45 assert(input_block_size_samples_ * input_frame_.num_channels_ <=
46 AudioFrame::kMaxDataSizeSamples);
47 acm_->RegisterTransportCallback(this);
48}
49
kwiberg65fc8b92016-08-29 10:05:24 -070050AcmSendTestOldApi::~AcmSendTestOldApi() = default;
51
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000052bool AcmSendTestOldApi::RegisterCodec(const char* payload_name,
53 int sampling_freq_hz,
54 int channels,
55 int payload_type,
56 int frame_size_samples) {
Karl Wiberg7e0c7d42015-05-18 14:52:29 +020057 CodecInst codec;
henrikg91d6ede2015-09-17 00:24:34 -070058 RTC_CHECK_EQ(0, AudioCodingModule::Codec(payload_name, &codec,
59 sampling_freq_hz, channels));
Karl Wiberg7e0c7d42015-05-18 14:52:29 +020060 codec.pltype = payload_type;
61 codec.pacsize = frame_size_samples;
62 codec_registered_ = (acm_->RegisterSendCodec(codec) == 0);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000063 input_frame_.num_channels_ = channels;
64 assert(input_block_size_samples_ * input_frame_.num_channels_ <=
65 AudioFrame::kMaxDataSizeSamples);
66 return codec_registered_;
67}
68
Karl Wiberg7e0c7d42015-05-18 14:52:29 +020069bool AcmSendTestOldApi::RegisterExternalCodec(
kwiberg12cfc9b2015-09-08 05:57:53 -070070 AudioEncoder* external_speech_encoder) {
Karl Wiberg7e0c7d42015-05-18 14:52:29 +020071 acm_->RegisterExternalSendCodec(external_speech_encoder);
72 input_frame_.num_channels_ = external_speech_encoder->NumChannels();
73 assert(input_block_size_samples_ * input_frame_.num_channels_ <=
74 AudioFrame::kMaxDataSizeSamples);
75 return codec_registered_ = true;
76}
77
henrik.lundin46ba49c2016-05-24 22:50:47 -070078std::unique_ptr<Packet> AcmSendTestOldApi::NextPacket() {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000079 assert(codec_registered_);
pkasting@chromium.org0e81fdf2015-02-02 23:54:03 +000080 if (filter_.test(static_cast<size_t>(payload_type_))) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000081 // This payload type should be filtered out. Since the payload type is the
82 // same throughout the whole test run, no packet at all will be delivered.
83 // We can just as well signal that the test is over by returning NULL.
henrik.lundin46ba49c2016-05-24 22:50:47 -070084 return nullptr;
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000085 }
86 // Insert audio and process until one packet is produced.
87 while (clock_.TimeInMilliseconds() < test_duration_ms_) {
88 clock_.AdvanceTimeMilliseconds(kBlockSizeMs);
yujo36b1a5f2017-06-12 12:45:32 -070089 RTC_CHECK(audio_source_->Read(input_block_size_samples_,
90 input_frame_.mutable_data()));
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000091 if (input_frame_.num_channels_ > 1) {
yujo36b1a5f2017-06-12 12:45:32 -070092 InputAudioFile::DuplicateInterleaved(input_frame_.data(),
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000093 input_block_size_samples_,
94 input_frame_.num_channels_,
yujo36b1a5f2017-06-12 12:45:32 -070095 input_frame_.mutable_data());
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000096 }
henrik.lundin@webrtc.orgf56c1622015-03-02 12:29:30 +000097 data_to_send_ = false;
henrikg91d6ede2015-09-17 00:24:34 -070098 RTC_CHECK_GE(acm_->Add10MsData(input_frame_), 0);
Peter Kastingb7e50542015-06-11 12:55:50 -070099 input_frame_.timestamp_ += static_cast<uint32_t>(input_block_size_samples_);
henrik.lundin@webrtc.orgf56c1622015-03-02 12:29:30 +0000100 if (data_to_send_) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000101 // Encoded packet received.
102 return CreatePacket();
103 }
104 }
105 // Test ended.
henrik.lundin46ba49c2016-05-24 22:50:47 -0700106 return nullptr;
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000107}
108
109// This method receives the callback from ACM when a new packet is produced.
110int32_t AcmSendTestOldApi::SendData(
111 FrameType frame_type,
112 uint8_t payload_type,
113 uint32_t timestamp,
114 const uint8_t* payload_data,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000115 size_t payload_len_bytes,
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000116 const RTPFragmentationHeader* fragmentation) {
117 // Store the packet locally.
118 frame_type_ = frame_type;
119 payload_type_ = payload_type;
120 timestamp_ = timestamp;
121 last_payload_vec_.assign(payload_data, payload_data + payload_len_bytes);
122 assert(last_payload_vec_.size() == payload_len_bytes);
henrik.lundin@webrtc.orgf56c1622015-03-02 12:29:30 +0000123 data_to_send_ = true;
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000124 return 0;
125}
126
henrik.lundin46ba49c2016-05-24 22:50:47 -0700127std::unique_ptr<Packet> AcmSendTestOldApi::CreatePacket() {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000128 const size_t kRtpHeaderSize = 12;
129 size_t allocated_bytes = last_payload_vec_.size() + kRtpHeaderSize;
130 uint8_t* packet_memory = new uint8_t[allocated_bytes];
131 // Populate the header bytes.
132 packet_memory[0] = 0x80;
pkasting@chromium.org0e81fdf2015-02-02 23:54:03 +0000133 packet_memory[1] = static_cast<uint8_t>(payload_type_);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000134 packet_memory[2] = (sequence_number_ >> 8) & 0xFF;
135 packet_memory[3] = (sequence_number_) & 0xFF;
136 packet_memory[4] = (timestamp_ >> 24) & 0xFF;
137 packet_memory[5] = (timestamp_ >> 16) & 0xFF;
138 packet_memory[6] = (timestamp_ >> 8) & 0xFF;
139 packet_memory[7] = timestamp_ & 0xFF;
140 // Set SSRC to 0x12345678.
141 packet_memory[8] = 0x12;
142 packet_memory[9] = 0x34;
143 packet_memory[10] = 0x56;
144 packet_memory[11] = 0x78;
145
146 ++sequence_number_;
147
148 // Copy the payload data.
149 memcpy(packet_memory + kRtpHeaderSize,
150 &last_payload_vec_[0],
151 last_payload_vec_.size());
henrik.lundin46ba49c2016-05-24 22:50:47 -0700152 std::unique_ptr<Packet> packet(
153 new Packet(packet_memory, allocated_bytes, clock_.TimeInMilliseconds()));
154 RTC_DCHECK(packet);
155 RTC_DCHECK(packet->valid_header());
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000156 return packet;
157}
158
159} // namespace test
160} // namespace webrtc