2020-06-08 03:29:51 +03:00
|
|
|
package av1
|
|
|
|
|
|
|
|
import (
|
2021-08-17 13:06:32 +03:00
|
|
|
"github.com/wader/fq/format"
|
|
|
|
"github.com/wader/fq/format/registry"
|
|
|
|
"github.com/wader/fq/pkg/decode"
|
2021-12-02 00:48:25 +03:00
|
|
|
"github.com/wader/fq/pkg/scalar"
|
2020-06-08 03:29:51 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
2021-11-17 18:46:10 +03:00
|
|
|
registry.MustRegister(decode.Format{
|
2020-06-08 03:29:51 +03:00
|
|
|
Name: format.AV1_OBU,
|
|
|
|
Description: "AV1 Open Bitstream Unit",
|
|
|
|
DecodeFn: obuDecode,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-09-27 12:01:14 +03:00
|
|
|
//nolint:revive
|
2020-06-08 03:29:51 +03:00
|
|
|
const (
|
|
|
|
OBU_SEQUENCE_HEADER = 1
|
|
|
|
OBU_TEMPORAL_DELIMITER = 2
|
|
|
|
OBU_FRAME_HEADER = 3
|
|
|
|
OBU_TILE_GROUP = 4
|
|
|
|
OBU_METADATA = 5
|
|
|
|
OBU_FRAME = 6
|
|
|
|
OBU_REDUNDANT_FRAME_HEADER = 7
|
|
|
|
OBU_TILE_LIST = 8
|
|
|
|
OBU_PADDING = 15
|
|
|
|
)
|
|
|
|
|
2021-12-02 00:48:25 +03:00
|
|
|
var obuTypeNames = scalar.UToSymStr{
|
2020-06-08 03:29:51 +03:00
|
|
|
OBU_SEQUENCE_HEADER: "OBU_SEQUENCE_HEADER",
|
|
|
|
OBU_TEMPORAL_DELIMITER: "OBU_TEMPORAL_DELIMITER",
|
|
|
|
OBU_FRAME_HEADER: "OBU_FRAME_HEADER",
|
|
|
|
OBU_TILE_GROUP: "OBU_TILE_GROUP",
|
|
|
|
OBU_METADATA: "OBU_METADATA",
|
|
|
|
OBU_FRAME: "OBU_FRAME",
|
|
|
|
OBU_REDUNDANT_FRAME_HEADER: "OBU_REDUNDANT_FRAME_HEADER",
|
|
|
|
OBU_TILE_LIST: "OBU_TILE_LIST",
|
|
|
|
OBU_PADDING: "OBU_PADDING",
|
|
|
|
}
|
|
|
|
|
2021-11-05 17:04:26 +03:00
|
|
|
func decodeLeb128(d *decode.D) uint64 {
|
2020-06-08 03:29:51 +03:00
|
|
|
var v uint64
|
|
|
|
for i := 0; i < 8; i++ {
|
|
|
|
b := d.U8()
|
|
|
|
v = v | (b&0x7f)<<(i*7)
|
|
|
|
if b&0x80 == 0 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
|
|
|
func obuDecode(d *decode.D, in interface{}) interface{} {
|
|
|
|
var obuType uint64
|
|
|
|
var obuSize int64
|
|
|
|
hasExtension := false
|
|
|
|
hasSizeField := false
|
|
|
|
|
2021-11-05 17:04:26 +03:00
|
|
|
d.FieldStruct("header", func(d *decode.D) {
|
2020-06-08 03:29:51 +03:00
|
|
|
d.FieldU1("forbidden_bit")
|
2021-12-02 00:48:25 +03:00
|
|
|
obuType = d.FieldU4("type", obuTypeNames)
|
2020-06-08 03:29:51 +03:00
|
|
|
hasExtension = d.FieldBool("extension_flag")
|
|
|
|
hasSizeField = d.FieldBool("has_size_field")
|
|
|
|
d.FieldU1("reserved_1bit")
|
|
|
|
if hasExtension {
|
|
|
|
d.FieldU3("temporal_id")
|
|
|
|
d.FieldU2("spatial_id")
|
|
|
|
d.FieldU3("extension_header_reserved_3bits")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
if hasSizeField {
|
2021-11-05 17:04:26 +03:00
|
|
|
obuSize = int64(d.FieldUFn("size", decodeLeb128))
|
2020-06-08 03:29:51 +03:00
|
|
|
} else {
|
|
|
|
obuSize = d.BitsLeft() / 8
|
|
|
|
if hasExtension {
|
|
|
|
obuSize--
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_ = obuType
|
|
|
|
|
|
|
|
if d.BitsLeft() > 0 {
|
2021-11-05 17:04:26 +03:00
|
|
|
d.FieldRawLen("data", obuSize*8)
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|