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/main/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/main/interface/audio_coding_module.h"
20#include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h"
21#include "webrtc/modules/audio_coding/neteq/tools/packet.h"
22
23namespace webrtc {
24namespace test {
25
26AcmSendTestOldApi::AcmSendTestOldApi(InputAudioFile* audio_source,
27                                     int source_rate_hz,
28                                     int test_duration_ms)
29    : clock_(0),
30      acm_(webrtc::AudioCodingModule::Create(0, &clock_)),
31      audio_source_(audio_source),
32      source_rate_hz_(source_rate_hz),
33      input_block_size_samples_(source_rate_hz_ * kBlockSizeMs / 1000),
34      codec_registered_(false),
35      test_duration_ms_(test_duration_ms),
36      frame_type_(kAudioFrameSpeech),
37      payload_type_(0),
38      timestamp_(0),
39      sequence_number_(0) {
40  input_frame_.sample_rate_hz_ = source_rate_hz_;
41  input_frame_.num_channels_ = 1;
42  input_frame_.samples_per_channel_ = input_block_size_samples_;
43  assert(input_block_size_samples_ * input_frame_.num_channels_ <=
44         AudioFrame::kMaxDataSizeSamples);
45  acm_->RegisterTransportCallback(this);
46}
47
48bool AcmSendTestOldApi::RegisterCodec(const char* payload_name,
49                                      int sampling_freq_hz,
50                                      int channels,
51                                      int payload_type,
52                                      int frame_size_samples) {
53  CHECK_EQ(0,
54           AudioCodingModule::Codec(
55               payload_name, &codec_, sampling_freq_hz, channels));
56  codec_.pltype = payload_type;
57  codec_.pacsize = frame_size_samples;
58  codec_registered_ = (acm_->RegisterSendCodec(codec_) == 0);
59  input_frame_.num_channels_ = channels;
60  assert(input_block_size_samples_ * input_frame_.num_channels_ <=
61         AudioFrame::kMaxDataSizeSamples);
62  return codec_registered_;
63}
64
65Packet* AcmSendTestOldApi::NextPacket() {
66  assert(codec_registered_);
67  if (filter_.test(payload_type_)) {
68    // This payload type should be filtered out. Since the payload type is the
69    // same throughout the whole test run, no packet at all will be delivered.
70    // We can just as well signal that the test is over by returning NULL.
71    return NULL;
72  }
73  // Insert audio and process until one packet is produced.
74  while (clock_.TimeInMilliseconds() < test_duration_ms_) {
75    clock_.AdvanceTimeMilliseconds(kBlockSizeMs);
76    CHECK(audio_source_->Read(input_block_size_samples_, input_frame_.data_));
77    if (input_frame_.num_channels_ > 1) {
78      InputAudioFile::DuplicateInterleaved(input_frame_.data_,
79                                           input_block_size_samples_,
80                                           input_frame_.num_channels_,
81                                           input_frame_.data_);
82    }
83    CHECK_EQ(0, acm_->Add10MsData(input_frame_));
84    input_frame_.timestamp_ += input_block_size_samples_;
85    int32_t encoded_bytes = acm_->Process();
86    if (encoded_bytes > 0) {
87      // Encoded packet received.
88      return CreatePacket();
89    }
90  }
91  // Test ended.
92  return NULL;
93}
94
95// This method receives the callback from ACM when a new packet is produced.
96int32_t AcmSendTestOldApi::SendData(
97    FrameType frame_type,
98    uint8_t payload_type,
99    uint32_t timestamp,
100    const uint8_t* payload_data,
101    uint16_t payload_len_bytes,
102    const RTPFragmentationHeader* fragmentation) {
103  // Store the packet locally.
104  frame_type_ = frame_type;
105  payload_type_ = payload_type;
106  timestamp_ = timestamp;
107  last_payload_vec_.assign(payload_data, payload_data + payload_len_bytes);
108  assert(last_payload_vec_.size() == payload_len_bytes);
109  return 0;
110}
111
112Packet* AcmSendTestOldApi::CreatePacket() {
113  const size_t kRtpHeaderSize = 12;
114  size_t allocated_bytes = last_payload_vec_.size() + kRtpHeaderSize;
115  uint8_t* packet_memory = new uint8_t[allocated_bytes];
116  // Populate the header bytes.
117  packet_memory[0] = 0x80;
118  packet_memory[1] = payload_type_;
119  packet_memory[2] = (sequence_number_ >> 8) & 0xFF;
120  packet_memory[3] = (sequence_number_) & 0xFF;
121  packet_memory[4] = (timestamp_ >> 24) & 0xFF;
122  packet_memory[5] = (timestamp_ >> 16) & 0xFF;
123  packet_memory[6] = (timestamp_ >> 8) & 0xFF;
124  packet_memory[7] = timestamp_ & 0xFF;
125  // Set SSRC to 0x12345678.
126  packet_memory[8] = 0x12;
127  packet_memory[9] = 0x34;
128  packet_memory[10] = 0x56;
129  packet_memory[11] = 0x78;
130
131  ++sequence_number_;
132
133  // Copy the payload data.
134  memcpy(packet_memory + kRtpHeaderSize,
135         &last_payload_vec_[0],
136         last_payload_vec_.size());
137  Packet* packet =
138      new Packet(packet_memory, allocated_bytes, clock_.TimeInMilliseconds());
139  assert(packet);
140  assert(packet->valid_header());
141  return packet;
142}
143
144}  // namespace test
145}  // namespace webrtc
146