File: neteq_replacement_input.cc

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (137 lines) | stat: -rw-r--r-- 4,384 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
 *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "modules/audio_coding/neteq/tools/neteq_replacement_input.h"

#include <algorithm>
#include <cstdint>
#include <memory>
#include <optional>
#include <set>
#include <utility>

#include "api/rtp_headers.h"
#include "modules/audio_coding/neteq/tools/fake_decode_from_file.h"
#include "modules/audio_coding/neteq/tools/neteq_input.h"
#include "rtc_base/checks.h"

namespace webrtc {
namespace test {

NetEqReplacementInput::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)
    : source_(std::move(source)),
      replacement_payload_type_(replacement_payload_type),
      comfort_noise_types_(comfort_noise_types),
      forbidden_types_(forbidden_types) {
  RTC_CHECK(source_);
  packet_ = source_->PopPacket();
  ReplacePacket();
}

std::optional<int64_t> NetEqReplacementInput::NextPacketTime() const {
  return packet_
             ? std::optional<int64_t>(static_cast<int64_t>(packet_->time_ms))
             : std::nullopt;
}

std::optional<int64_t> NetEqReplacementInput::NextOutputEventTime() const {
  return source_->NextOutputEventTime();
}

std::optional<NetEqInput::SetMinimumDelayInfo>
NetEqReplacementInput::NextSetMinimumDelayInfo() const {
  return source_->NextSetMinimumDelayInfo();
}

std::unique_ptr<NetEqInput::PacketData> NetEqReplacementInput::PopPacket() {
  std::unique_ptr<PacketData> to_return = std::move(packet_);
  while (true) {
    packet_ = source_->PopPacket();
    if (!packet_)
      break;
    if (packet_->payload.size() > packet_->header.paddingLength) {
      // Not padding only. Good to go. Skip this packet otherwise.
      break;
    }
  }
  ReplacePacket();
  return to_return;
}

void NetEqReplacementInput::AdvanceOutputEvent() {
  source_->AdvanceOutputEvent();
}

void NetEqReplacementInput::AdvanceSetMinimumDelay() {
  source_->AdvanceSetMinimumDelay();
}

bool NetEqReplacementInput::ended() const {
  return source_->ended();
}

std::optional<RTPHeader> NetEqReplacementInput::NextHeader() const {
  return source_->NextHeader();
}

void NetEqReplacementInput::ReplacePacket() {
  if (!source_->NextPacketTime()) {
    // End of input. Cannot do proper replacement on the very last packet, so we
    // delete it instead.
    packet_.reset();
    return;
  }

  RTC_DCHECK(packet_);

  RTC_CHECK_EQ(forbidden_types_.count(packet_->header.payloadType), 0)
      << "Payload type " << static_cast<int>(packet_->header.payloadType)
      << " is forbidden.";

  // Check if this packet is comfort noise.
  if (comfort_noise_types_.count(packet_->header.payloadType) != 0) {
    // If CNG, simply insert a zero-energy one-byte payload.
    uint8_t cng_payload[1] = {127};  // Max attenuation of CNG.
    packet_->payload.SetData(cng_payload);
    return;
  }

  std::optional<RTPHeader> next_hdr = source_->NextHeader();
  RTC_DCHECK(next_hdr);
  uint8_t payload[12];
  constexpr uint32_t kMaxFrameSize = 120 * 48;
  const uint32_t timestamp_diff =
      next_hdr->timestamp - packet_->header.timestamp;
  uint32_t frame_size = last_frame_size_timestamps_;
  if (timestamp_diff > 0) {
    frame_size = std::min(frame_size, timestamp_diff);
  }
  const bool opus_dtx = packet_->payload.size() <= 2;
  if (next_hdr->sequenceNumber == packet_->header.sequenceNumber + 1 &&
      timestamp_diff <= kMaxFrameSize && timestamp_diff > 0 && !opus_dtx) {
    // Packets are in order and the timestamp diff is valid.
    frame_size = timestamp_diff;
    last_frame_size_timestamps_ = frame_size;
  }
  RTC_DCHECK_LE(frame_size, kMaxFrameSize);
  RTC_DCHECK_GT(frame_size, 0);
  FakeDecodeFromFile::PrepareEncoded(packet_->header.timestamp, frame_size,
                                     packet_->payload.size(), payload);
  packet_->payload.SetData(payload);
  packet_->header.payloadType = replacement_payload_type_;
  return;
}

}  // namespace test
}  // namespace webrtc