Documentation
¶
Overview ¶
Package h265 reads an H.265/HEVC bitstream in pure Go, with no libavcodec linkage and no external binaries.
The framing and the bit reading are go-avkit/bitstream's, shared with H.264: the two formats separate their units identically and differ in how the header bytes of a unit are read -- H.264 spends one and this spends two -- and in what the parameter sets hold. This package is that difference.
Index ¶
- Constants
- Variables
- type LongTermRef
- type LongTermRefPic
- type LtPicture
- type POC
- type POCCounter
- type PPS
- type Picture
- type PictureRefs
- type PredWeights
- type RefListEntry
- type RefPic
- type RefPicSet
- type RefWeight
- type SPS
- type ShortHeaderError
- type ShortTermRPS
- type SliceSegmentHeader
- type SliceType
- type Unit
- type UnitType
Examples ¶
Constants ¶
const MaxRefIdxActive = 15
MaxRefIdxActive is the most entries a reference picture list may have, 7.4.3.3. It bounds what a parameter set may state and what Lists will build.
Variables ¶
var ( // ErrNotPPS means the unit handed over is not a picture parameter set. ErrNotPPS = errors.New("h265: unit is not a picture parameter set") // ErrUnsupportedPPS means the set does not end where a set must end, so // something in it was read wrongly. ErrUnsupportedPPS = errors.New("h265: picture parameter set was not consumed exactly") // ErrRefIdxRange means the set states more reference indices than a list // can hold. 7.4.3.3 puts num_ref_idx_lX_default_active_minus1 in 0..14; a // larger value is not a big stream, it is a few bytes asking a reader to // size a list from an attacker's number. ErrRefIdxRange = errors.New("h265: num_ref_idx_lX_default_active_minus1 out of range") )
Errors a picture parameter set can be refused with.
var ( // ErrNotSlice means the unit handed over does not carry a slice segment. ErrNotSlice = errors.New("h265: unit does not carry a slice segment") // ErrSliceHeader means a segment states something this reader does not follow. ErrSliceHeader = errors.New("h265: unsupported slice segment header") )
Errors a slice segment header can be refused with.
var ( // ErrNotSPS means the unit handed over is not a sequence parameter set. ErrNotSPS = errors.New("h265: unit is not a sequence parameter set") // ErrUnsupportedSPS means the set states something this reader does not // follow. ErrUnsupportedSPS = errors.New("h265: unsupported sequence parameter set") )
Errors a sequence parameter set can be refused with.
var ErrNoOrder = errors.New("h265: the unit carries no picture order count")
ErrNoOrder means the unit states no order of its own.
var ErrRefLists = errors.New("h265: reference list cannot be built")
ErrRefLists means a slice asked for a reference list that cannot be built.
Functions ¶
This section is empty.
Types ¶
type LongTermRef ¶ added in v0.5.0
type LongTermRef struct {
POCLSB uint32
Used bool
// MSBPresent says DeltaMSBCycle was stated. Without it the picture is the
// one whose low bits match; with it, the one that many wraps further back.
MSBPresent bool
DeltaMSBCycle uint32
// FromSPS says the entry was named out of the sequence's own list rather
// than stated by the slice.
FromSPS bool
}
LongTermRef is one long-term picture a slice names.
A long-term picture is named by the LOW bits of its order count, which is enough while no two candidates share them. When two would, the slice states the high bits as well, which is what MSBPresent says.
type LongTermRefPic ¶ added in v0.4.0
LongTermRefPic is one long-term picture a sequence offers to its slices.
type LtPicture ¶ added in v0.7.0
LtPicture is one long-term picture a set names.
⛔ POC is a full order count only when Exact is set. Otherwise it is the LOW bits of one, and the picture meant is whichever held in the decoded picture buffer matches them -- which is enough while no two candidates share them, and is why the format lets a slice state the high bits when two would.
type POC ¶ added in v0.3.0
type POC struct {
// Value is the count itself.
Value int32
// LSB is what the slice header stated, before the high bits were carried in.
LSB uint32
// Carried says this picture is the one later pictures count from. Only a
// picture of sub-layer zero that is neither leading nor sub-layer
// non-reference does that, and a counter that carried from every picture
// would place everything after the first dropped one wrongly.
Carried bool
}
POC is a picture's order count: where it belongs in the order a viewer sees, which is not the order it was coded in.
type POCCounter ¶ added in v0.3.0
type POCCounter struct {
// contains filtered or unexported fields
}
POCCounter derives picture order counts across a coded video sequence.
⛔ It has to be a counter rather than a function because the format sends only the LOW bits of the count. The high bits are carried forward from an earlier picture, and the one they come from is not simply the previous picture: it is the previous one of sub-layer zero that is neither a leading picture nor a sub-layer non-reference. Those are exactly the pictures a thinned stream may have dropped, so counting from them would make the order depend on what was thrown away.
Feed it every coded picture of the sequence, in decode order, one slice per picture: the first slice segment of each. A picture carried by several segments is one picture here.
func (*POCCounter) Next ¶ added in v0.3.0
Next gives the order count of one coded picture and remembers what the pictures after it will need.
The unit is wanted whole, not just its payload: the count depends on the unit TYPE, which says whether the high bits restart, and on the temporal identifier, which says whether this picture is one later ones count from.
func (*POCCounter) Reset ¶ added in v0.3.0
func (c *POCCounter) Reset()
Reset forgets every picture counted so far. It is what a seek is: the pictures before the new position are not the ones the counts should follow from.
type PPS ¶
type PPS struct {
ID uint32
SPSID uint32
DependentSlicesEnabled bool
OutputFlagPresent bool
ExtraSliceHeaderBits uint8
SignDataHiding bool
CABACInitPresent bool
NumRefIdxL0 uint32
NumRefIdxL1 uint32
InitQP int32 // already un-biased
ConstrainedIntraPred bool
TransformSkip bool
CUQPDeltaEnabled bool
CbQPOffset int32
CrQPOffset int32
SliceChromaQPOffsets bool
WeightedPred bool
WeightedBipred bool
TransquantBypass bool
TilesEnabled bool
EntropySyncEnabled bool
TileColumns uint32
TileRows uint32
UniformTileSpacing bool
DeblockingOverride bool
DeblockingDisabled bool
BetaOffsetDiv2 int32
TCOffsetDiv2 int32
ListsModification bool
SliceHeaderExtension bool
}
PPS is what a picture parameter set says about the slices that refer to it.
Two of these fields are what a slice segment header cannot be read without: whether a segment may depend on the one before it, and how many bits of the header the stream reserves before the slice type. A reader without them is misaligned from the first field that matters.
type Picture ¶
type Picture struct {
Units []Unit
Type SliceType
// TypeKnown is false when no segment of this picture stated a type, which
// happens when a stream is joined part way through a picture.
TypeKnown bool
Sync bool
Bytes int
}
Picture is one coded picture: the units that carry it, and what it is.
Units are in the order they arrived, parameter sets and all, so a caller writing a sample table has the bytes of a sample and nothing else to gather.
func SplitPictures ¶
SplitPictures groups a stream's units into the pictures they carry.
⛔ Where H.264 needs several fields compared between neighbouring slices to find a boundary, HEVC states it outright: one flag per segment says whether it begins a picture. That is the whole rule here, and it is worth saying that the simpler format is simpler rather than carrying the other one's machinery over.
Parameter sets and delimiters that arrive before a picture's first segment belong to that picture: a decoder must hold them before the segment that uses them.
type PictureRefs ¶ added in v0.5.0
type PictureRefs struct {
ShortTerm ShortTermRPS
LongTerm []LongTermRef
// NamedSet says the short-term set was NAMED out of the sequence's sets
// rather than stated by the slice, and SetIndex says which.
NamedSet bool
SetIndex int
// Type is how the slice is coded. An I slice predicts from nothing, so the
// fields below are not stated for one.
Type SliceType
// NumRefIdxL0Active and NumRefIdxL1Active are how many entries each
// reference list has. They start at the picture parameter set's and a
// slice may override them.
NumRefIdxL0Active uint32
NumRefIdxL1Active uint32
// ListEntryL0 and ListEntryL1 are ref_pic_lists_modification, 7.3.6.2: the
// position in the temporary list that each entry of the final list is
// taken from. nil means the slice stated no modification for that list and
// the default order stands -- which is NOT the same as an empty slice.
ListEntryL0 []uint32
ListEntryL1 []uint32
// TemporalMVP says the slice predicts motion from another picture, which
// is what the two fields below name.
TemporalMVP bool
// CollocatedFromL0 says which list the picture is taken from, and
// CollocatedRefIdx its position in that list. Both are only meaningful
// while TemporalMVP is set.
CollocatedFromL0 bool
CollocatedRefIdx uint32
// Weights is pred_weight_table, nil where the picture parameter set does
// not weight this kind of slice.
Weights *PredWeights
// MaxMergeCand is 5 - five_minus_max_num_merge_cand, in 1..5.
MaxMergeCand uint8
}
PictureRefs is what one coded picture states about the pictures it may still need: a short-term set, and the long-term pictures it names.
func ReferencesOf ¶ added in v0.5.0
func ReferencesOf(u Unit, sps SPS, pps PPS) (PictureRefs, error)
ReferencesOf reads what a coded picture says it still needs.
An IDR says nothing: it begins a coded video sequence, so nothing before it is available and nothing after it may reach back. That is not an error and comes back as an empty set.
Pass the FIRST slice segment of the picture. A later segment states no set of its own -- the set belongs to the picture -- and its address, which this package cannot yet work out, sits in the way.
type PredWeights ¶ added in v0.9.0
type PredWeights struct {
LumaLog2Denom uint8
ChromaLog2Denom uint8
// L0 and L1 are as long as the lists they weigh.
L0 []RefWeight
L1 []RefWeight
}
PredWeights is pred_weight_table, 7.3.6.3: how a slice weighs each picture it predicts from.
⛔ The weights here are VALUES, not the deltas the syntax carries. The format states each as a difference from the neutral weight, and the offsets of the chroma components as a difference that has to be folded with the weight before it means anything. A caller handed the raw deltas would scale by something close to zero.
type RefListEntry ¶ added in v0.7.0
type RefListEntry struct {
POC int32
// LongTerm says the entry came from the long-term pictures, which a decoder
// treats differently: a long-term reference is not scaled by distance the
// way a short-term one is.
LongTerm bool
// Exact says POC is a full order count. A long-term entry whose slice did
// not state its high bits carries only the low ones. See LtPicture.
Exact bool
}
RefListEntry is one entry of a reference picture list.
func Lists ¶ added in v0.7.0
func Lists(set RefPicSet, refs PictureRefs) (l0, l1 []RefListEntry, err error)
Lists builds the reference picture lists a slice predicts from, clause 8.3.4.
⛔ The two lists hold the SAME pictures in a different order, and the order is the point: list 0 starts with what came before this picture, list 1 with what comes after. A decoder handed them the same way round predicts a B slice from the wrong side.
refs carries how many entries each list has and, where the slice stated one, the order its entries are taken in. A list SHORTER than the pictures available simply stops; a list LONGER repeats them, which is legal and is why the candidates are cycled rather than laid down once.
An I slice predicts from nothing and gets no lists. A P slice gets list 0.
Example ¶
ExampleLists is the snippet the README shows, compiled. A documented call that does not build is a claim, not a capability.
package main
import (
"fmt"
"github.com/go-avkit/h265"
)
// ExampleLists is the snippet the README shows, compiled. A documented call
// that does not build is a claim, not a capability.
func main() {
var sps h265.SPS
// What ReferencesOf reads out of the slice segment header. A B slice that
// names, for each of its three list 0 entries, the picture it wants there.
refs := h265.PictureRefs{
Type: h265.SliceB,
NumRefIdxL0Active: 3,
NumRefIdxL1Active: 2,
ShortTerm: h265.ShortTermRPS{
Before: []h265.RefPic{{DeltaPOC: -8, Used: true}, {DeltaPOC: -4, Used: true}},
After: []h265.RefPic{{DeltaPOC: 4, Used: true}},
},
ListEntryL0: []uint32{2, 0, 1},
}
set := h265.Derive(refs, 16, sps)
l0, l1, err := h265.Lists(set, refs)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("list 0:", order(l0))
fmt.Println("list 1:", order(l1))
}
func order(l []h265.RefListEntry) []int32 {
out := make([]int32, len(l))
for i, e := range l {
out[i] = e.POC
}
return out
}
Output: list 0: [20 8 12] list 1: [20 8]
type RefPic ¶ added in v0.4.0
type RefPic struct {
// DeltaPOC is the entry's order count minus the current picture's, so it is
// negative for a picture already seen and positive for one still to come.
DeltaPOC int32
Used bool
}
RefPic is one entry of a short-term reference picture set: where the picture sits relative to the current one, and whether the current one may use it.
A set lists pictures the DECODER must keep, which is not the same as the pictures this one predicts from. An entry that is not Used is kept because a LATER picture will want it, and dropping it would break that one instead.
type RefPicSet ¶ added in v0.7.0
type RefPicSet struct {
// StCurrBefore are pictures already decoded that this one may use, nearest
// first; StCurrAfter are those that follow it in output order and precede
// it in the stream.
StCurrBefore []int32
StCurrAfter []int32
// StFoll are short-term pictures to keep and not use.
StFoll []int32
// LtCurr and LtFoll are the long-term pictures, likewise split.
LtCurr []LtPicture
LtFoll []LtPicture
}
RefPicSet is what one coded picture needs kept, derived from what its slice stated: five lists, and the difference between them is the whole point.
⛔ Curr and Foll are NOT the same thing. A picture in Curr may be predicted from by this picture. A picture in Foll may not -- it is listed because a LATER picture will want it, and a decoder that dropped it would break that one instead. Both must be kept; only one may be used.
func Derive ¶ added in v0.7.0
func Derive(refs PictureRefs, poc int32, sps SPS) RefPicSet
Derive turns what a slice stated into the pictures a decoder must keep, given the order count of the picture that stated it.
The short-term entries are relative and become absolute here; the long-term ones are already counts, or the low bits of counts.
type RefWeight ¶ added in v0.9.0
type RefWeight struct {
LumaStated bool
LumaWeight int32
LumaOffset int32
ChromaStated bool
// ChromaWeight and ChromaOffset are Cb then Cr.
ChromaWeight [2]int32
ChromaOffset [2]int32
}
RefWeight is how one reference picture is weighted, 7.4.7.3.
Stated says the slice gave a weight for that component. Where it did not, the weight is the neutral one -- 1 << the denominator -- and the offset is zero, which this fills in so that a caller never has to ask whether a field was present before using it.
type SPS ¶
type SPS struct {
VPSID uint8
MaxSubLayers uint8
ProfileSpace uint8
Tier uint8
ProfileIDC uint8
LevelIDC uint8
ID uint32
ChromaFormat uint8
SeparatePlanes bool
CodedWidth uint32
CodedHeight uint32
WinLeft uint32
WinRight uint32
WinTop uint32
WinBottom uint32
Width uint32
Height uint32
BitDepthLuma uint8
BitDepthChroma uint8
Log2MaxPOCLSB uint8
// ShortTermRefPicSets are the sets a slice may name instead of stating one
// of its own, in the order the sequence lists them. A set may be written as
// a difference from an earlier one, so the order is load-bearing.
// SAOEnabled and TemporalMVPEnabled are not used here, but a slice header
// cannot be read without them: both decide whether a field is present,
// and a reader without them is misaligned from that point on.
SAOEnabled bool
TemporalMVPEnabled bool
ShortTermRefPicSets []ShortTermRPS
// LongTermRefPics are the long-term pictures the sequence offers, named by
// the low bits of their order count.
LongTermRefPics []LongTermRefPic
// LongTermRefPicsPresent says the sequence allows long-term pictures at
// all. It is not the same as offering any: a sequence may allow them and
// list none, and then a slice states its own.
LongTermRefPicsPresent bool
}
SPS is what a sequence parameter set says about the pictures that follow.
Width and Height are what a player shows and what a container states: the coded size less the conformance window. Unlike H.264 the coded size is stated in luma samples directly rather than in macroblocks, so there is no multiply -- but the window still has to be taken off, and its offsets are in CHROMA units.
type ShortHeaderError ¶
ShortHeaderError means a unit is too short to hold the two bytes of header this format spends.
func (*ShortHeaderError) Error ¶
func (e *ShortHeaderError) Error() string
type ShortTermRPS ¶ added in v0.4.0
type ShortTermRPS struct {
Before []RefPic // negative deltas, nearest first: -1, -2, ...
After []RefPic // positive deltas, nearest first: 1, 2, ...
}
ShortTermRPS is a short-term reference picture set: the pictures a coded picture may still need, stated relative to its own order count.
The two halves are kept apart because the format states them apart and because they mean different things: Before holds pictures already decoded, After holds pictures that follow in order but precede this one in the stream. Both are ordered by distance, nearest first.
func (ShortTermRPS) Count ¶ added in v0.4.0
func (s ShortTermRPS) Count() int
Count is how many pictures the set names, which is the NumDeltaPocs the next set may predict from.
type SliceSegmentHeader ¶
type SliceSegmentHeader struct {
First bool // first_slice_segment_in_pic_flag
Dependent bool // only meaningful when First is false
PPSID uint32
Type SliceType
TypeRead bool
RandomAccess bool // the unit type says this picture can stand alone
// NoOutputOfPriorPics is stated only by a random access picture.
NoOutputOfPriorPics bool
}
SliceSegmentHeader is the beginning of a slice segment: which picture it belongs to, whether it starts one, and -- when it starts one -- how that picture is coded.
⛔ Type is read only for a segment that BEGINS a picture, and TypeRead says so. Reaching the type of a later segment means first reading its address, whose width comes from the coding tree block size in the sequence set -- a field this package does not read yet. Reporting a type it had not read would be worse than saying it did not: a picture's type would then come from whichever segment was looked at.
func ParseSliceSegmentHeader ¶
func ParseSliceSegmentHeader(u Unit, pps PPS) (SliceSegmentHeader, error)
ParseSliceSegmentHeader reads the beginning of a slice segment.
It needs the picture parameter set, which states whether a segment may depend on the one before it and how many bits the stream reserves before the slice type. Both change where the type sits, so a reader without them is misaligned from the first field that matters.
type SliceType ¶
type SliceType uint8
SliceType is how a slice is coded. HEVC numbers them the other way round from H.264, and naming them here rather than reusing a number is the point.
type Unit ¶
type Unit struct {
Type UnitType
// LayerID is which layer of a scalable stream this belongs to. A plain
// stream states zero throughout, and a decoder that ignored it would mix the
// layers of one that does not.
LayerID uint8
// TemporalID is the sub-layer, one more than the field on the wire. A stream
// can be thinned by dropping the higher ones, which is what it is for.
TemporalID uint8
Payload []byte
}
Unit is one NAL unit: its two header bytes read, and its payload still escaped.
Payload is a window into the caller's bytes and is not copied.
func SplitAnnexB ¶
SplitAnnexB finds the NAL units of a byte stream and reads each one's header.
func SplitLengthPrefixed ¶
SplitLengthPrefixed finds the units of the form an MP4 sample carries, where each is preceded by its length in lengthSize bytes, and reads each one's header.
lengthSize comes from the hvcC record.
type UnitType ¶
type UnitType uint8
UnitType is what a NAL unit holds. Only the ones this package acts on are named; the rest travel as their number.
const ( UnitTrailN UnitType = 0 UnitTrailR UnitType = 1 UnitTSAN UnitType = 2 UnitTSAR UnitType = 3 UnitSTSAN UnitType = 4 UnitSTSAR UnitType = 5 UnitRADLN UnitType = 6 UnitRADLR UnitType = 7 UnitRASLN UnitType = 8 UnitRASLR UnitType = 9 UnitBLAWLP UnitType = 16 UnitBLAWRADL UnitType = 17 UnitBLANLP UnitType = 18 UnitIDRWRADL UnitType = 19 UnitIDRNLP UnitType = 20 UnitCRA UnitType = 21 UnitVPS UnitType = 32 UnitSPS UnitType = 33 UnitPPS UnitType = 34 UnitAUD UnitType = 35 UnitEOS UnitType = 36 UnitEOB UnitType = 37 UnitFD UnitType = 38 UnitPrefixSEI UnitType = 39 UnitSuffixSEI UnitType = 40 )
The unit types a reader has to tell apart.
⛔ A picture's type is not one flag here as it is in H.264. HEVC names sixteen kinds of slice segment, and which of them can be decoded without anything before it is what a sample table needs: the ones from BLA_W_LP to CRA are exactly that set, and IsRandomAccess is where the boundary is written down rather than scattered.
func (UnitType) IsBLA ¶ added in v0.3.0
IsBLA says the stream was spliced here. A broken link picture is decoded as a random access point whose leading pictures may refer to material that is not there, and its order count restarts: the high bits are taken as zero however far the count had got.
func (UnitType) IsIDR ¶ added in v0.3.0
IsIDR says the picture starts a new coded video sequence and states no order of its own: an IDR carries no slice_pic_order_cnt_lsb at all, and its count is zero by definition.
func (UnitType) IsLeading ¶ added in v0.3.0
IsLeading says the picture precedes its random access point in output order while following it in decode order -- RADL if it can be decoded, RASL if it refers to material before the access point and so may not be.
func (UnitType) IsRandomAccess ¶
IsRandomAccess says whether a picture of this type can be decoded with nothing before it, which is what a sample table calls a sync sample.
func (UnitType) IsSliceSegment ¶
IsSliceSegment says whether a unit carries coded picture data.
func (UnitType) IsSubLayerNonReference ¶ added in v0.3.0
IsSubLayerNonReference says no picture of the same sub-layer uses this one for prediction, which is what makes a stream thinnable: these can be dropped without disturbing anything left. The even types below 15 are the ones.