Documentation
¶
Overview ¶
Package vp9 reads a VP9 bitstream in pure Go, with no libvpx or ffmpeg linkage and no external binaries.
It begins with the uncompressed header, which is where VP9 states what a container does not: Matroska and MP4 carry no VP9 profile or level, so the frames are the only place either can be read from. That is why this exists before any decoding does -- a muxer needs the profile, the bit depth, the chroma subsampling and the frame size to write a usable vpcC record, and every one of them is in the first few dozen bits of a key frame.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNotVP9 means the frame does not begin with VP9's frame marker. ErrNotVP9 = errors.New("vp9: not a VP9 frame") // ErrSyncCode means a key frame's sync code is not the one VP9 states. ErrSyncCode = errors.New("vp9: wrong sync code") // ErrReserved means a bit the format reserves was set. ErrReserved = errors.New("vp9: reserved bit set") // ErrProfile means a profile and a colour description contradict each // other: 4:2:0 cannot be stated in profile 1 or 3, and 4:4:4 cannot be // stated in profile 0 or 2. ErrProfile = errors.New("vp9: colour description contradicts the profile") )
Errors a header can be refused with.
var ErrShort = errors.New("vp9: bitstream ends inside a field")
ErrShort means the bitstream ended in the middle of a field.
var ErrSuperframe = errors.New("vp9: superframe index is inconsistent")
ErrSuperframe means a packet carries an index that describes itself wrongly.
Functions ¶
func SplitSuperframe ¶
SplitSuperframe returns the frames a VP9 packet holds.
A packet usually holds one frame and is handed back unchanged. It may instead be a superframe: several frames followed by an index that states how long each one is, which is how an encoder ships a frame nobody shows -- an alternate reference -- together with the frame that does show.
⛔ A packet whose last byte merely LOOKS like an index byte is handed back whole rather than refused. Three bits of pattern in one byte happen by chance, and an ordinary frame ending in such a byte is a frame, not a broken superframe: the index describes itself completely enough to say which it is, so the answer is taken from the arithmetic and not from the pattern. What the arithmetic requires is that the first and last bytes of the index agree and that the sizes account for exactly the bytes before it -- checked here, and the reason a coincidence cannot be mistaken for an index.
Types ¶
type Header ¶
type Header struct {
Profile uint8 // 0 to 3
Key bool // A key frame states its own description.
Show bool // The frame is shown rather than only decoded.
ErrorResilient bool
ShowExisting bool // The frame only repeats one already decoded.
ExistingFrame uint8 // Which one, when ShowExisting.
BitDepth uint8 // 8, 10 or 12
ColorSpace uint8 // 0 to 7, as ISO/IEC 23001-8 numbers them
FullRange bool
SubsamplingX uint8 // 1 means the chroma planes are half as wide
SubsamplingY uint8
Width uint16
Height uint16
RenderWidth uint16 // The size to display at, which may differ.
RenderHeight uint16
}
Header is what a VP9 frame's uncompressed header states.
Only a key frame states the whole of it: a later frame either refers to a frame already decoded or repeats one, and takes its description from there. So a caller that needs a track's description reads the FIRST key frame, and Key says whether it got one.
func ParseHeader ¶
ParseHeader reads the uncompressed header at the start of one VP9 frame.
It reads no further than it needs: everything after the frame size is either arithmetic-coded or of no use to a caller describing a track, and stopping here keeps this readable against the one part of the format that is plain bit fields.