<!-- go/cmark -->
<!--* freshness: {owner: 'jakobi' reviewed: '2021-04-13'} *-->

# NetEq

NetEq is the audio jitter buffer and packet loss concealer. The jitter buffer is
an adaptive jitter buffer, meaning that the buffering delay is continuously
optimized based on the network conditions. Its main goal is to ensure a smooth
playout of incoming audio packets from the network with a low amount of audio
artifacts (alterations to the original content of the packets) while at the same
time keep the delay as low as possible.

## API

At a high level, the NetEq API has two main functions:
[`InsertPacket`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/api/neteq/neteq.h;l=198;drc=4461f059d180fe8c2886d422ebd1cb55b5c83e72)
and
[`GetAudio`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/api/neteq/neteq.h;l=219;drc=4461f059d180fe8c2886d422ebd1cb55b5c83e72).

### InsertPacket

[`InsertPacket`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/api/neteq/neteq.h;l=198;drc=4461f059d180fe8c2886d422ebd1cb55b5c83e72)
delivers an RTP packet from the network to NetEq where the following happens:

1.  The packet is discarded if it is too late for playout (for example if it was
    reordered). Otherwize it is put into the packet buffer where it is stored
    until it is time for playout. If the buffer is full, discard all the
    existing packets (this should be rare).
2.  The interarrival time between packets is analyzed and statistics is updated
    which is used to derive a new target playout delay. The interarrival time is
    measured in the number of GetAudio ‘ticks’ and thus clock drift between the
    sender and receiver can be accounted for.

### GetAudio

[`GetAudio`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/api/neteq/neteq.h;l=219;drc=4461f059d180fe8c2886d422ebd1cb55b5c83e72)
pulls 10 ms of audio from NetEq for playout. A much simplified decision logic is
as follows:

1.  If there is 10 ms audio in the sync buffer then return that.
2.  If the next packet is available (based on RTP timestamp) in the packet
    buffer then decode it and append the result to the sync buffer.
    1.  Compare the current delay estimate (filtered buffer level) with the
        target delay and time stretch (accelerate or decelerate) the contents of
        the sync buffer if the buffer level is too high or too low.
    2.  Return 10 ms of audio from the sync buffer.
3.  If the last decoded packet was a discontinuous transmission (DTX) packet
    then generate comfort noise.
4.  If there is no available packet for decoding due to the next packet having
    not arrived or been lost then generate packet loss concealment by
    extrapolating the remaining audio in the sync buffer or by asking the
    decoder to produce it.

In summary, the output is the result one of the following operations:

*   Normal: audio decoded from a packet.
*   Acceleration: accelerated playout of a decoded packet.
*   Preemptive expand: decelerated playout of a decoded packet.
*   Expand: packet loss concealment generated by NetEq or the decoder.
*   Merge: audio stitched together from packet loss concealment to decoded data
    in case of a loss.
*   Comfort noise (CNG): comfort noise generated by NetEq or the decoder between
    talk spurts due to discontinuous transmission of packets (DTX).

## Statistics

There are a number of functions that can be used to query the internal state of
NetEq, statistics about the type of audio output and latency metrics such as how
long time packets have waited in the buffer.

*   [`NetworkStatistics`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/api/neteq/neteq.h;l=273;drc=4461f059d180fe8c2886d422ebd1cb55b5c83e72):
    instantaneous values or stats averaged over the duration since last call to
    this function.
*   [`GetLifetimeStatistics`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/api/neteq/neteq.h;l=280;drc=4461f059d180fe8c2886d422ebd1cb55b5c83e72):
    cumulative stats that persist over the lifetime of the class.
*   [`GetOperationsAndState`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/api/neteq/neteq.h;l=284;drc=4461f059d180fe8c2886d422ebd1cb55b5c83e72):
    information about the internal state of NetEq (is only inteded to be used
    for testing and debugging).

## Tests and tools

*   [`neteq_rtpplay`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_coding/neteq/tools/neteq_rtpplay.cc;drc=cee751abff598fc19506f77de08bea7c61b9dcca):
    Simulate NetEq behavior based on either an RTP dump, a PCAP file or an RTC
    event log. A replacement audio file can also be used instead of the original
    payload. Outputs aggregated statistics and optionally an audio file to
    listen to.
*   [`neteq_speed_test`](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/audio_coding/neteq/test/neteq_speed_test.cc;drc=2ab97f6f8e27b47c0d9beeb8b6ca5387bda9f55c):
    Measure performance of NetEq, used on perf bots.
*   Unit tests including bit exactness tests where RTP file is used as an input
    to NetEq, the output is concatenated and a checksum is calculated and
    compared against a reference.

## Other responsibilities

*   Dual-tone multi-frequency signaling (DTMF): receive telephone events and
    produce dual tone waveforms.
*   Forward error correction (RED or codec inband FEC): split inserted packets
    and prioritize the payloads.
*   NACK (negative acknowledgement): keep track of lost packets and generate a
    list of packets to NACK.
*   Audio/video sync: NetEq can be instructed to increase the latency in order
    to keep audio and video in sync.
