blob: a84fa7c3e986469e6431410e90e7be7348f71b8d [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
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000013#include <stdio.h>
14#include <string.h>
15
Fredrik Solenbergf693bfa2018-12-11 12:22:10 +010016#include "absl/strings/match.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "api/audio_codecs/audio_encoder.h"
Karl Wiberg5817d3d2018-04-06 10:06:42 +020018#include "api/audio_codecs/builtin_audio_decoder_factory.h"
Karl Wiberg801500c2018-08-16 15:01:12 +020019#include "api/audio_codecs/builtin_audio_encoder_factory.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "modules/audio_coding/include/audio_coding_module.h"
21#include "modules/audio_coding/neteq/tools/input_audio_file.h"
22#include "modules/audio_coding/neteq/tools/packet.h"
23#include "rtc_base/checks.h"
Steve Anton10542f22019-01-11 09:11:00 -080024#include "rtc_base/string_encode.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#include "test/gtest.h"
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000026
27namespace webrtc {
28namespace test {
29
30AcmSendTestOldApi::AcmSendTestOldApi(InputAudioFile* audio_source,
31 int source_rate_hz,
32 int test_duration_ms)
33 : clock_(0),
Karl Wiberg5817d3d2018-04-06 10:06:42 +020034 acm_(webrtc::AudioCodingModule::Create([this] {
35 AudioCodingModule::Config config;
36 config.clock = &clock_;
37 config.decoder_factory = CreateBuiltinAudioDecoderFactory();
38 return config;
39 }())),
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000040 audio_source_(audio_source),
41 source_rate_hz_(source_rate_hz),
Peter Kastingdce40cf2015-08-24 14:52:23 -070042 input_block_size_samples_(
43 static_cast<size_t>(source_rate_hz_ * kBlockSizeMs / 1000)),
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000044 codec_registered_(false),
45 test_duration_ms_(test_duration_ms),
Niels Möllerc936cb62019-03-19 14:10:16 +010046 frame_type_(AudioFrameType::kAudioFrameSpeech),
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000047 payload_type_(0),
48 timestamp_(0),
49 sequence_number_(0) {
50 input_frame_.sample_rate_hz_ = source_rate_hz_;
51 input_frame_.num_channels_ = 1;
52 input_frame_.samples_per_channel_ = input_block_size_samples_;
Mirko Bonadei25ab3222021-07-08 20:08:20 +020053 RTC_DCHECK_LE(input_block_size_samples_ * input_frame_.num_channels_,
54 AudioFrame::kMaxDataSizeSamples);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000055 acm_->RegisterTransportCallback(this);
56}
57
kwiberg65fc8b92016-08-29 10:05:24 -070058AcmSendTestOldApi::~AcmSendTestOldApi() = default;
59
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000060bool AcmSendTestOldApi::RegisterCodec(const char* payload_name,
Fredrik Solenbergf693bfa2018-12-11 12:22:10 +010061 int clockrate_hz,
62 int num_channels,
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000063 int payload_type,
64 int frame_size_samples) {
Fredrik Solenbergf693bfa2018-12-11 12:22:10 +010065 SdpAudioFormat format(payload_name, clockrate_hz, num_channels);
66 if (absl::EqualsIgnoreCase(payload_name, "g722")) {
67 RTC_CHECK_EQ(16000, clockrate_hz);
68 format.clockrate_hz = 8000;
69 } else if (absl::EqualsIgnoreCase(payload_name, "opus")) {
70 RTC_CHECK(num_channels == 1 || num_channels == 2);
71 if (num_channels == 2) {
72 format.parameters["stereo"] = "1";
73 }
74 format.num_channels = 2;
75 }
Karl Wiberg801500c2018-08-16 15:01:12 +020076 format.parameters["ptime"] = rtc::ToString(rtc::CheckedDivExact(
Fredrik Solenbergf693bfa2018-12-11 12:22:10 +010077 frame_size_samples, rtc::CheckedDivExact(clockrate_hz, 1000)));
78 auto factory = CreateBuiltinAudioEncoderFactory();
Karl Wiberg801500c2018-08-16 15:01:12 +020079 acm_->SetEncoder(
80 factory->MakeAudioEncoder(payload_type, format, absl::nullopt));
81 codec_registered_ = true;
Fredrik Solenbergf693bfa2018-12-11 12:22:10 +010082 input_frame_.num_channels_ = num_channels;
Mirko Bonadei25ab3222021-07-08 20:08:20 +020083 RTC_DCHECK_LE(input_block_size_samples_ * input_frame_.num_channels_,
84 AudioFrame::kMaxDataSizeSamples);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +000085 return codec_registered_;
86}
87
Karl Wiberg801500c2018-08-16 15:01:12 +020088void AcmSendTestOldApi::RegisterExternalCodec(
89 std::unique_ptr<AudioEncoder> external_speech_encoder) {
Karl Wiberg7e0c7d42015-05-18 14:52:29 +020090 input_frame_.num_channels_ = external_speech_encoder->NumChannels();
Karl Wiberg801500c2018-08-16 15:01:12 +020091 acm_->SetEncoder(std::move(external_speech_encoder));
Mirko Bonadei25ab3222021-07-08 20:08:20 +020092 RTC_DCHECK_LE(input_block_size_samples_ * input_frame_.num_channels_,
93 AudioFrame::kMaxDataSizeSamples);
Karl Wiberg801500c2018-08-16 15:01:12 +020094 codec_registered_ = true;
Karl Wiberg7e0c7d42015-05-18 14:52:29 +020095}
96
henrik.lundin46ba49c2016-05-24 22:50:47 -070097std::unique_ptr<Packet> AcmSendTestOldApi::NextPacket() {
Mirko Bonadei25ab3222021-07-08 20:08:20 +020098 RTC_DCHECK(codec_registered_);
pkasting@chromium.org0e81fdf2015-02-02 23:54:03 +000099 if (filter_.test(static_cast<size_t>(payload_type_))) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000100 // This payload type should be filtered out. Since the payload type is the
101 // same throughout the whole test run, no packet at all will be delivered.
102 // We can just as well signal that the test is over by returning NULL.
henrik.lundin46ba49c2016-05-24 22:50:47 -0700103 return nullptr;
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000104 }
105 // Insert audio and process until one packet is produced.
106 while (clock_.TimeInMilliseconds() < test_duration_ms_) {
107 clock_.AdvanceTimeMilliseconds(kBlockSizeMs);
Alex Loiko65438812019-02-22 10:13:44 +0100108 RTC_CHECK(audio_source_->Read(
109 input_block_size_samples_ * input_frame_.num_channels_,
110 input_frame_.mutable_data()));
henrik.lundin@webrtc.orgf56c1622015-03-02 12:29:30 +0000111 data_to_send_ = false;
henrikg91d6ede2015-09-17 00:24:34 -0700112 RTC_CHECK_GE(acm_->Add10MsData(input_frame_), 0);
Peter Kastingb7e50542015-06-11 12:55:50 -0700113 input_frame_.timestamp_ += static_cast<uint32_t>(input_block_size_samples_);
henrik.lundin@webrtc.orgf56c1622015-03-02 12:29:30 +0000114 if (data_to_send_) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000115 // Encoded packet received.
116 return CreatePacket();
117 }
118 }
119 // Test ended.
henrik.lundin46ba49c2016-05-24 22:50:47 -0700120 return nullptr;
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000121}
122
123// This method receives the callback from ACM when a new packet is produced.
Niels Möllerc35b6e62019-04-25 16:31:18 +0200124int32_t AcmSendTestOldApi::SendData(AudioFrameType frame_type,
125 uint8_t payload_type,
126 uint32_t timestamp,
127 const uint8_t* payload_data,
Minyue Liff0e4db2020-01-23 13:45:50 +0100128 size_t payload_len_bytes,
129 int64_t absolute_capture_timestamp_ms) {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000130 // Store the packet locally.
131 frame_type_ = frame_type;
132 payload_type_ = payload_type;
133 timestamp_ = timestamp;
134 last_payload_vec_.assign(payload_data, payload_data + payload_len_bytes);
Mirko Bonadei25ab3222021-07-08 20:08:20 +0200135 RTC_DCHECK_EQ(last_payload_vec_.size(), payload_len_bytes);
henrik.lundin@webrtc.orgf56c1622015-03-02 12:29:30 +0000136 data_to_send_ = true;
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000137 return 0;
138}
139
henrik.lundin46ba49c2016-05-24 22:50:47 -0700140std::unique_ptr<Packet> AcmSendTestOldApi::CreatePacket() {
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000141 const size_t kRtpHeaderSize = 12;
Danil Chapovalovb4100ad2021-06-16 14:23:22 +0200142 rtc::CopyOnWriteBuffer packet_buffer(last_payload_vec_.size() +
143 kRtpHeaderSize);
144 uint8_t* packet_memory = packet_buffer.MutableData();
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000145 // Populate the header bytes.
146 packet_memory[0] = 0x80;
pkasting@chromium.org0e81fdf2015-02-02 23:54:03 +0000147 packet_memory[1] = static_cast<uint8_t>(payload_type_);
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000148 packet_memory[2] = (sequence_number_ >> 8) & 0xFF;
Yves Gerey665174f2018-06-19 15:03:05 +0200149 packet_memory[3] = (sequence_number_)&0xFF;
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000150 packet_memory[4] = (timestamp_ >> 24) & 0xFF;
151 packet_memory[5] = (timestamp_ >> 16) & 0xFF;
152 packet_memory[6] = (timestamp_ >> 8) & 0xFF;
153 packet_memory[7] = timestamp_ & 0xFF;
154 // Set SSRC to 0x12345678.
155 packet_memory[8] = 0x12;
156 packet_memory[9] = 0x34;
157 packet_memory[10] = 0x56;
158 packet_memory[11] = 0x78;
159
160 ++sequence_number_;
161
162 // Copy the payload data.
Yves Gerey665174f2018-06-19 15:03:05 +0200163 memcpy(packet_memory + kRtpHeaderSize, &last_payload_vec_[0],
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000164 last_payload_vec_.size());
Danil Chapovalovb4100ad2021-06-16 14:23:22 +0200165 auto packet = std::make_unique<Packet>(std::move(packet_buffer),
166 clock_.TimeInMilliseconds());
henrik.lundin46ba49c2016-05-24 22:50:47 -0700167 RTC_DCHECK(packet);
168 RTC_DCHECK(packet->valid_header());
henrik.lundin@webrtc.org0e6e4d22014-09-23 12:05:34 +0000169 return packet;
170}
171
172} // namespace test
173} // namespace webrtc