webrtc/modules/audio_coding/neteq/packet.h
Jakob Ivarsson 89f64b994f Make packet info optional and only set for primary packets in NetEq.
Header metadata such as audio level and capture time doesn't make sense
for redundant payloads (i.e. RED and inband-FEC).

It is assumed that one of the parsed payload timestamps will correspond
to the RTP header timestamp.

This fixes a bug where capture time and CSRCs were not set after
parsing RED packets.

CreateRedPayload test function is adapted from red_payload_splitter_unittest.cc

Bug: webrtc:15185
Change-Id: Iba58772499b6d760f516854999b60511896b053c
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/305700
Reviewed-by: Henrik Lundin <henrik.lundin@webrtc.org>
Commit-Queue: Jakob Ivarsson‎ <jakobi@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#40240}
2023-06-07 18:17:03 +00:00

128 lines
4.6 KiB
C++

/*
* Copyright (c) 2012 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.
*/
#ifndef MODULES_AUDIO_CODING_NETEQ_PACKET_H_
#define MODULES_AUDIO_CODING_NETEQ_PACKET_H_
#include <stdint.h>
#include <list>
#include <memory>
#include "api/audio_codecs/audio_decoder.h"
#include "api/neteq/tick_timer.h"
#include "api/rtp_packet_info.h"
#include "rtc_base/buffer.h"
#include "rtc_base/checks.h"
namespace webrtc {
// Struct for holding RTP packets.
struct Packet {
struct Priority {
Priority() : codec_level(0), red_level(0) {}
Priority(int codec_level, int red_level)
: codec_level(codec_level), red_level(red_level) {
CheckInvariant();
}
int codec_level;
int red_level;
// Priorities are sorted low-to-high, first on the level the codec
// prioritizes it, then on the level of RED packet it is; i.e. if it is a
// primary or secondary payload of a RED packet. For example: with Opus, an
// Fec packet (which the decoder prioritizes lower than a regular packet)
// will not be used if there is _any_ RED payload for the same
// timeframe. The highest priority packet will have levels {0, 0}. Negative
// priorities are not allowed.
bool operator<(const Priority& b) const {
CheckInvariant();
b.CheckInvariant();
if (codec_level == b.codec_level)
return red_level < b.red_level;
return codec_level < b.codec_level;
}
bool operator==(const Priority& b) const {
CheckInvariant();
b.CheckInvariant();
return codec_level == b.codec_level && red_level == b.red_level;
}
bool operator!=(const Priority& b) const { return !(*this == b); }
bool operator>(const Priority& b) const { return b < *this; }
bool operator<=(const Priority& b) const { return !(b > *this); }
bool operator>=(const Priority& b) const { return !(b < *this); }
private:
void CheckInvariant() const {
RTC_DCHECK_GE(codec_level, 0);
RTC_DCHECK_GE(red_level, 0);
}
};
uint32_t timestamp;
uint16_t sequence_number;
uint8_t payload_type;
// Datagram excluding RTP header and header extension.
rtc::Buffer payload;
Priority priority;
absl::optional<RtpPacketInfo> packet_info;
std::unique_ptr<TickTimer::Stopwatch> waiting_time;
std::unique_ptr<AudioDecoder::EncodedAudioFrame> frame;
Packet();
Packet(Packet&& b);
~Packet();
// Packets should generally be moved around but sometimes it's useful to make
// a copy, for example for testing purposes. NOTE: Will only work for
// un-parsed packets, i.e. `frame` must be unset. The payload will, however,
// be copied. `waiting_time` will also not be copied.
Packet Clone() const;
Packet& operator=(Packet&& b);
// Comparison operators. Establish a packet ordering based on (1) timestamp,
// (2) sequence number and (3) redundancy.
// Timestamp and sequence numbers are compared taking wrap-around into
// account. For two packets with the same sequence number and timestamp a
// primary payload is considered "smaller" than a secondary.
bool operator==(const Packet& rhs) const {
return (this->timestamp == rhs.timestamp &&
this->sequence_number == rhs.sequence_number &&
this->priority == rhs.priority);
}
bool operator!=(const Packet& rhs) const { return !operator==(rhs); }
bool operator<(const Packet& rhs) const {
if (this->timestamp == rhs.timestamp) {
if (this->sequence_number == rhs.sequence_number) {
// Timestamp and sequence numbers are identical - deem the left hand
// side to be "smaller" (i.e., "earlier") if it has higher priority.
return this->priority < rhs.priority;
}
return (static_cast<uint16_t>(rhs.sequence_number -
this->sequence_number) < 0xFFFF / 2);
}
return (static_cast<uint32_t>(rhs.timestamp - this->timestamp) <
0xFFFFFFFF / 2);
}
bool operator>(const Packet& rhs) const { return rhs.operator<(*this); }
bool operator<=(const Packet& rhs) const { return !operator>(rhs); }
bool operator>=(const Packet& rhs) const { return !operator<(rhs); }
bool empty() const { return !frame && payload.empty(); }
};
// A list of packets.
typedef std::list<Packet> PacketList;
} // namespace webrtc
#endif // MODULES_AUDIO_CODING_NETEQ_PACKET_H_