1 /*
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 
11 #include "webrtc/modules/audio_coding/acm2/acm_send_test_oldapi.h"
12 
13 #include <assert.h>
14 #include <stdio.h>
15 #include <string.h>
16 
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "webrtc/base/checks.h"
19 #include "webrtc/modules/audio_coding/codecs/audio_encoder.h"
20 #include "webrtc/modules/audio_coding/include/audio_coding_module.h"
21 #include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h"
22 #include "webrtc/modules/audio_coding/neteq/tools/packet.h"
23 
24 namespace webrtc {
25 namespace test {
26 
AcmSendTestOldApi(InputAudioFile * audio_source,int source_rate_hz,int test_duration_ms)27 AcmSendTestOldApi::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),
34       input_block_size_samples_(
35           static_cast<size_t>(source_rate_hz_ * kBlockSizeMs / 1000)),
36       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 
RegisterCodec(const char * payload_name,int sampling_freq_hz,int channels,int payload_type,int frame_size_samples)50 bool AcmSendTestOldApi::RegisterCodec(const char* payload_name,
51                                       int sampling_freq_hz,
52                                       int channels,
53                                       int payload_type,
54                                       int frame_size_samples) {
55   CodecInst codec;
56   RTC_CHECK_EQ(0, AudioCodingModule::Codec(payload_name, &codec,
57                                            sampling_freq_hz, channels));
58   codec.pltype = payload_type;
59   codec.pacsize = frame_size_samples;
60   codec_registered_ = (acm_->RegisterSendCodec(codec) == 0);
61   input_frame_.num_channels_ = channels;
62   assert(input_block_size_samples_ * input_frame_.num_channels_ <=
63          AudioFrame::kMaxDataSizeSamples);
64   return codec_registered_;
65 }
66 
RegisterExternalCodec(AudioEncoder * external_speech_encoder)67 bool AcmSendTestOldApi::RegisterExternalCodec(
68     AudioEncoder* external_speech_encoder) {
69   acm_->RegisterExternalSendCodec(external_speech_encoder);
70   input_frame_.num_channels_ = external_speech_encoder->NumChannels();
71   assert(input_block_size_samples_ * input_frame_.num_channels_ <=
72          AudioFrame::kMaxDataSizeSamples);
73   return codec_registered_ = true;
74 }
75 
NextPacket()76 Packet* AcmSendTestOldApi::NextPacket() {
77   assert(codec_registered_);
78   if (filter_.test(static_cast<size_t>(payload_type_))) {
79     // This payload type should be filtered out. Since the payload type is the
80     // same throughout the whole test run, no packet at all will be delivered.
81     // We can just as well signal that the test is over by returning NULL.
82     return NULL;
83   }
84   // Insert audio and process until one packet is produced.
85   while (clock_.TimeInMilliseconds() < test_duration_ms_) {
86     clock_.AdvanceTimeMilliseconds(kBlockSizeMs);
87     RTC_CHECK(
88         audio_source_->Read(input_block_size_samples_, input_frame_.data_));
89     if (input_frame_.num_channels_ > 1) {
90       InputAudioFile::DuplicateInterleaved(input_frame_.data_,
91                                            input_block_size_samples_,
92                                            input_frame_.num_channels_,
93                                            input_frame_.data_);
94     }
95     data_to_send_ = false;
96     RTC_CHECK_GE(acm_->Add10MsData(input_frame_), 0);
97     input_frame_.timestamp_ += static_cast<uint32_t>(input_block_size_samples_);
98     if (data_to_send_) {
99       // Encoded packet received.
100       return CreatePacket();
101     }
102   }
103   // Test ended.
104   return NULL;
105 }
106 
107 // This method receives the callback from ACM when a new packet is produced.
SendData(FrameType frame_type,uint8_t payload_type,uint32_t timestamp,const uint8_t * payload_data,size_t payload_len_bytes,const RTPFragmentationHeader * fragmentation)108 int32_t AcmSendTestOldApi::SendData(
109     FrameType frame_type,
110     uint8_t payload_type,
111     uint32_t timestamp,
112     const uint8_t* payload_data,
113     size_t payload_len_bytes,
114     const RTPFragmentationHeader* fragmentation) {
115   // Store the packet locally.
116   frame_type_ = frame_type;
117   payload_type_ = payload_type;
118   timestamp_ = timestamp;
119   last_payload_vec_.assign(payload_data, payload_data + payload_len_bytes);
120   assert(last_payload_vec_.size() == payload_len_bytes);
121   data_to_send_ = true;
122   return 0;
123 }
124 
CreatePacket()125 Packet* AcmSendTestOldApi::CreatePacket() {
126   const size_t kRtpHeaderSize = 12;
127   size_t allocated_bytes = last_payload_vec_.size() + kRtpHeaderSize;
128   uint8_t* packet_memory = new uint8_t[allocated_bytes];
129   // Populate the header bytes.
130   packet_memory[0] = 0x80;
131   packet_memory[1] = static_cast<uint8_t>(payload_type_);
132   packet_memory[2] = (sequence_number_ >> 8) & 0xFF;
133   packet_memory[3] = (sequence_number_) & 0xFF;
134   packet_memory[4] = (timestamp_ >> 24) & 0xFF;
135   packet_memory[5] = (timestamp_ >> 16) & 0xFF;
136   packet_memory[6] = (timestamp_ >> 8) & 0xFF;
137   packet_memory[7] = timestamp_ & 0xFF;
138   // Set SSRC to 0x12345678.
139   packet_memory[8] = 0x12;
140   packet_memory[9] = 0x34;
141   packet_memory[10] = 0x56;
142   packet_memory[11] = 0x78;
143 
144   ++sequence_number_;
145 
146   // Copy the payload data.
147   memcpy(packet_memory + kRtpHeaderSize,
148          &last_payload_vec_[0],
149          last_payload_vec_.size());
150   Packet* packet =
151       new Packet(packet_memory, allocated_bytes, clock_.TimeInMilliseconds());
152   assert(packet);
153   assert(packet->valid_header());
154   return packet;
155 }
156 
157 }  // namespace test
158 }  // namespace webrtc
159