neteq_replacement_input.cc (4312B)
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 <algorithm> 14 #include <cstdint> 15 #include <memory> 16 #include <optional> 17 #include <set> 18 #include <utility> 19 20 #include "modules/audio_coding/neteq/tools/fake_decode_from_file.h" 21 #include "modules/audio_coding/neteq/tools/neteq_input.h" 22 #include "modules/rtp_rtcp/source/rtp_packet_received.h" 23 #include "rtc_base/checks.h" 24 25 namespace webrtc { 26 namespace test { 27 28 NetEqReplacementInput::NetEqReplacementInput( 29 std::unique_ptr<NetEqInput> source, 30 uint8_t replacement_payload_type, 31 const std::set<uint8_t>& comfort_noise_types, 32 const std::set<uint8_t>& forbidden_types) 33 : source_(std::move(source)), 34 replacement_payload_type_(replacement_payload_type), 35 comfort_noise_types_(comfort_noise_types), 36 forbidden_types_(forbidden_types) { 37 RTC_CHECK(source_); 38 packet_ = source_->PopPacket(); 39 ReplacePacket(); 40 } 41 42 std::optional<int64_t> NetEqReplacementInput::NextPacketTime() const { 43 return packet_ ? std::optional(packet_->arrival_time().ms()) : std::nullopt; 44 } 45 46 std::optional<int64_t> NetEqReplacementInput::NextOutputEventTime() const { 47 return source_->NextOutputEventTime(); 48 } 49 50 std::optional<NetEqInput::SetMinimumDelayInfo> 51 NetEqReplacementInput::NextSetMinimumDelayInfo() const { 52 return source_->NextSetMinimumDelayInfo(); 53 } 54 55 std::unique_ptr<RtpPacketReceived> NetEqReplacementInput::PopPacket() { 56 std::unique_ptr<RtpPacketReceived> to_return = std::move(packet_); 57 while (true) { 58 packet_ = source_->PopPacket(); 59 if (!packet_) 60 break; 61 if (!packet_->payload().empty()) { 62 // Not padding only. Good to go. Skip this packet otherwise. 63 break; 64 } 65 } 66 ReplacePacket(); 67 return to_return; 68 } 69 70 void NetEqReplacementInput::AdvanceOutputEvent() { 71 source_->AdvanceOutputEvent(); 72 } 73 74 void NetEqReplacementInput::AdvanceSetMinimumDelay() { 75 source_->AdvanceSetMinimumDelay(); 76 } 77 78 bool NetEqReplacementInput::ended() const { 79 return source_->ended(); 80 } 81 82 const RtpPacketReceived* NetEqReplacementInput::NextPacket() const { 83 return source_->NextPacket(); 84 } 85 86 void NetEqReplacementInput::ReplacePacket() { 87 if (!source_->NextPacketTime()) { 88 // End of input. Cannot do proper replacement on the very last packet, so we 89 // delete it instead. 90 packet_.reset(); 91 return; 92 } 93 94 RTC_DCHECK(packet_); 95 96 RTC_CHECK_EQ(forbidden_types_.count(packet_->PayloadType()), 0) 97 << "Payload type " << static_cast<int>(packet_->PayloadType()) 98 << " is forbidden."; 99 100 // Check if this packet is comfort noise. 101 if (comfort_noise_types_.count(packet_->PayloadType()) != 0) { 102 // If CNG, simply insert a zero-energy one-byte payload. 103 uint8_t cng_payload[1] = {127}; // Max attenuation of CNG. 104 packet_->SetPayload(cng_payload); 105 return; 106 } 107 108 const RtpPacketReceived* next_packet = source_->NextPacket(); 109 RTC_DCHECK(next_packet); 110 uint8_t payload[12]; 111 constexpr uint32_t kMaxFrameSize = 120 * 48; 112 const uint32_t timestamp_diff = 113 next_packet->Timestamp() - packet_->Timestamp(); 114 uint32_t frame_size = last_frame_size_timestamps_; 115 if (timestamp_diff > 0) { 116 frame_size = std::min(frame_size, timestamp_diff); 117 } 118 const bool opus_dtx = packet_->payload_size() <= 2; 119 if (next_packet->SequenceNumber() == packet_->SequenceNumber() + 1 && 120 timestamp_diff <= kMaxFrameSize && timestamp_diff > 0 && !opus_dtx) { 121 // Packets are in order and the timestamp diff is valid. 122 frame_size = timestamp_diff; 123 last_frame_size_timestamps_ = frame_size; 124 } 125 RTC_DCHECK_LE(frame_size, kMaxFrameSize); 126 RTC_DCHECK_GT(frame_size, 0); 127 FakeDecodeFromFile::PrepareEncoded(packet_->Timestamp(), frame_size, 128 packet_->payload_size(), payload); 129 packet_->SetPayload(payload); 130 packet_->SetPayloadType(replacement_payload_type_); 131 return; 132 } 133 134 } // namespace test 135 } // namespace webrtc