1 /*
2 * Copyright (c) 2016 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 "modules/audio_coding/neteq/tools/neteq_replacement_input.h"
12
13 #include "modules/audio_coding/neteq/tools/fake_decode_from_file.h"
14 #include "rtc_base/checks.h"
15
16 namespace webrtc {
17 namespace test {
18
NetEqReplacementInput(std::unique_ptr<NetEqInput> source,uint8_t replacement_payload_type,const std::set<uint8_t> & comfort_noise_types,const std::set<uint8_t> & forbidden_types)19 NetEqReplacementInput::NetEqReplacementInput(
20 std::unique_ptr<NetEqInput> source,
21 uint8_t replacement_payload_type,
22 const std::set<uint8_t>& comfort_noise_types,
23 const std::set<uint8_t>& forbidden_types)
24 : source_(std::move(source)),
25 replacement_payload_type_(replacement_payload_type),
26 comfort_noise_types_(comfort_noise_types),
27 forbidden_types_(forbidden_types) {
28 RTC_CHECK(source_);
29 packet_ = source_->PopPacket();
30 ReplacePacket();
31 }
32
NextPacketTime() const33 absl::optional<int64_t> NetEqReplacementInput::NextPacketTime() const {
34 return packet_
35 ? absl::optional<int64_t>(static_cast<int64_t>(packet_->time_ms))
36 : absl::nullopt;
37 }
38
NextOutputEventTime() const39 absl::optional<int64_t> NetEqReplacementInput::NextOutputEventTime() const {
40 return source_->NextOutputEventTime();
41 }
42
PopPacket()43 std::unique_ptr<NetEqInput::PacketData> NetEqReplacementInput::PopPacket() {
44 std::unique_ptr<PacketData> to_return = std::move(packet_);
45 while (true) {
46 packet_ = source_->PopPacket();
47 if (!packet_)
48 break;
49 if (packet_->payload.size() > packet_->header.paddingLength) {
50 // Not padding only. Good to go. Skip this packet otherwise.
51 break;
52 }
53 }
54 ReplacePacket();
55 return to_return;
56 }
57
AdvanceOutputEvent()58 void NetEqReplacementInput::AdvanceOutputEvent() {
59 source_->AdvanceOutputEvent();
60 }
61
ended() const62 bool NetEqReplacementInput::ended() const {
63 return source_->ended();
64 }
65
NextHeader() const66 absl::optional<RTPHeader> NetEqReplacementInput::NextHeader() const {
67 return source_->NextHeader();
68 }
69
ReplacePacket()70 void NetEqReplacementInput::ReplacePacket() {
71 if (!source_->NextPacketTime()) {
72 // End of input. Cannot do proper replacement on the very last packet, so we
73 // delete it instead.
74 packet_.reset();
75 return;
76 }
77
78 RTC_DCHECK(packet_);
79
80 RTC_CHECK_EQ(forbidden_types_.count(packet_->header.payloadType), 0)
81 << "Payload type " << static_cast<int>(packet_->header.payloadType)
82 << " is forbidden.";
83
84 // Check if this packet is comfort noise.
85 if (comfort_noise_types_.count(packet_->header.payloadType) != 0) {
86 // If CNG, simply insert a zero-energy one-byte payload.
87 uint8_t cng_payload[1] = {127}; // Max attenuation of CNG.
88 packet_->payload.SetData(cng_payload);
89 return;
90 }
91
92 absl::optional<RTPHeader> next_hdr = source_->NextHeader();
93 RTC_DCHECK(next_hdr);
94 uint8_t payload[12];
95 RTC_DCHECK_LE(last_frame_size_timestamps_, 120 * 48);
96 uint32_t input_frame_size_timestamps = last_frame_size_timestamps_;
97 const uint32_t timestamp_diff =
98 next_hdr->timestamp - packet_->header.timestamp;
99 if (next_hdr->sequenceNumber == packet_->header.sequenceNumber + 1 &&
100 timestamp_diff <= 120 * 48) {
101 // Packets are in order and the timestamp diff is less than 5760 samples.
102 // Accept the timestamp diff as a valid frame size.
103 input_frame_size_timestamps = timestamp_diff;
104 last_frame_size_timestamps_ = input_frame_size_timestamps;
105 }
106 RTC_DCHECK_LE(input_frame_size_timestamps, 120 * 48);
107 FakeDecodeFromFile::PrepareEncoded(packet_->header.timestamp,
108 input_frame_size_timestamps,
109 packet_->payload.size(), payload);
110 packet_->payload.SetData(payload);
111 packet_->header.payloadType = replacement_payload_type_;
112 return;
113 }
114
115 } // namespace test
116 } // namespace webrtc
117