Documentation
¶
Overview ¶
Package bitstream holds what the video codecs of the ITU-T H.26x family read their headers with, in pure Go.
It exists because two codecs needed the same code and neither should depend on the other. H.264 and H.265 frame their units identically -- the same start codes, the same escaping inside a unit, the same variable-length integers -- and differ only in how they read the header bytes of a unit once it is found. That difference is the seam: this package finds the units and reads the bits, and knows nothing about what a unit means.
Measured before it was written: the framing of a real HEVC stream, split by the H.264 code this was lifted from, gave 65 units whose types read the H.265 way are exactly what such a stream holds -- one video parameter set, one sequence set, one picture set, one IDR picture, thirty trailing pictures and their SEI messages. The framing transfers; the header does not.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNoStartCode means a byte stream holds no unit at all. ErrNoStartCode = errors.New("bitstream: no start code in the byte stream") // ErrLengthOverrun means a length-prefixed unit claims more bytes than the // stream holds. ErrLengthOverrun = errors.New("bitstream: unit length runs past the end") // ErrEmptySize means a length size is not one these formats use. ErrEmptySize = errors.New("bitstream: unit length size is not 1 to 4") )
Errors framing can refuse with.
var ( // ErrShort means the bitstream ended in the middle of a field. ErrShort = errors.New("bitstream: ends inside a field") // ErrTooLong means an Exp-Golomb code claims more leading zeros than any // value these formats state could need. ErrTooLong = errors.New("bitstream: Exp-Golomb code is longer than any value needs") // ErrWidth means a read was asked for a number of bits the value it returns // cannot hold, or a negative one. Both used to be answered silently. ErrWidth = errors.New("bitstream: a width the value cannot hold") )
Errors a reader can refuse with.
Functions ¶
func SplitAnnexB ¶
SplitAnnexB returns the units of a byte stream, the form a raw elementary stream and an MPEG-TS stream carry.
⛔ The units are returned as they lie, header bytes included, because how many of those bytes are header is the ONE thing that differs between the codecs sharing this: H.264 spends one and H.265 spends two. Reading them here would put a codec's rule in the one place that must not have one.
Units are separated by two or more zero bytes and a one. Three zeros and a one is the same separator with a leading zero, so the scan looks for the three-byte form and lets a fourth zero belong to the gap rather than to the unit -- a unit that began with a stray zero would have its header read out of a byte nobody wrote there. Trailing zeros are dropped for the same reason in reverse: an encoder may pad, and padding is not payload.
A stream cut after its last separator keeps the units that did arrive: a cut stream is the normal state of a download in progress, and refusing the whole of it would lose everything that was there.
func SplitLengthPrefixed ¶
SplitLengthPrefixed returns the units of the form an MP4 sample carries, where each is preceded by its length in sizeBytes bytes.
sizeBytes comes from the codec's configuration record and is 1, 2 or 4 in practice; anything outside 1 to 4 is refused rather than guessed, since a wrong size reads a length out of payload and would walk the stream into nonsense.
func Unescape ¶
Unescape undoes the escaping inside a unit.
These formats may not carry three consecutive bytes that look like a start code, so an encoder writes 00 00 03 where it means 00 00 and the reader drops the three.
⛔ Only a three that follows exactly two zeros is an escape: dropping every three after any zero would eat payload, and the byte after the escape is whatever it is -- including another zero, which starts the count again.
Types ¶
type Reader ¶
type Reader struct {
// contains filtered or unexported fields
}
Reader reads the fields of a payload: single bits, fixed-width values, and the Exp-Golomb integers these formats write their parameter sets with.
It is given an UNESCAPED payload. Escaping is undone by Unescape, and keeping the two apart means a caller that only walks past units never pays for a copy of one.
func (*Reader) Left ¶
Left is how many bits remain. It is what tells a reader whether an optional field follows or only the bits that end a payload.
func (*Reader) MoreData ¶
MoreData says whether any syntax element remains before the bits that end a payload.
Those bits are a single one followed by zeros to the byte boundary, so what is left is a field only if a one appears after the first one, or the first one is not where the padding would put it. Reading them as a field is how an optional tail comes to be read from a payload that does not have one.
func (*Reader) Peek ¶
Peek reads n bits without consuming them.
It exists for one question these formats ask and which cannot be answered any other way: whether what is left is a syntax element or the padding that ends a payload. Answering it by reading would consume the field it was asking about.
func (*Reader) Pos ¶
Pos is how many bits have been read, which is what lets a caller say where a refusal happened rather than only that one did.