Opus encoder produces 40/60ms CBR packets with excess padding
The packets produced by opus_multistream_encode()
when encoding 40ms or 60ms CELT or Hybrid packets for a single stream contain 4 to 6 bytes of padding, which could have been used to add 1 or 2 bytes to each frame.
For example:
$ opusenc --hard-cbr --bitrate 31.5 --framesize 60 comp48s.wav out.opus
Encoding using libopus 1.1-42-ge1f8462 (audio)
-----------------------------------------------------
Input: 48kHz 2 channels
Output: 2 channels (2 coupled)
60ms packets, 31.5kbit/sec CBR
Preskip: 312
Encoding complete
-----------------------------------------------------
Encoded: 1 minute and 30.84 seconds
Runtime: 2 seconds
(45.42x realtime)
Wrote: 362224 bytes, 1514 packets, 97 pages
Bitrate: 31.4667kbit/s (without overhead)
Instant rates: 31.4667kbit/s to 31.4667kbit/s
(236 to 236 bytes per packet)
Overhead: 1.36% (container+metadata)
$
The above command produces 236-byte packets (31.467 kb/s), each containing the 2 bytes required for a code 3 packet, three 76-byte frames, and 6 bytes of padding (including the padding length byte). Instead of the 6 bytes of padding, each frame could have contained 78 bytes of data.
If the multistream API is not used, opus_encode()
does produce packets containing three 78-byte frames for this same bitrate and frame size. However, for some reason it also adds 1 byte of padding to each packet, which causes it to slightly exceed the target bitrate.
$ opus_demo audio 48000 2 31500 -cbr -framesize 60 comp48s.pcm out.pcm
libopus 1.1-42-ge1f8462
Encoding 48000 Hz input at 31.500 kb/s in auto mode with 2880-sample frames.
average bitrate: 31.613 kb/s
maximum bitrate: 31.600 kb/s
active bitrate: 31.600 kb/s
bitrate standard deviation: 0.000 kb/s
$