package vp9
import (
"errors"
)
var (
errInvalidFrameMarker = errors .New ("invalid frame marker" )
errWrongFrameSyncByte0 = errors .New ("wrong frame_sync_byte_0" )
errWrongFrameSyncByte1 = errors .New ("wrong frame_sync_byte_1" )
errWrongFrameSyncByte2 = errors .New ("wrong frame_sync_byte_2" )
)
type HeaderColorConfig struct {
TenOrTwelveBit bool
BitDepth uint8
ColorSpace uint8
ColorRange bool
SubsamplingX bool
SubsamplingY bool
}
func (c *HeaderColorConfig ) unmarshal (profile uint8 , buf []byte , pos *int ) error {
if profile >= 2 {
var err error
c .TenOrTwelveBit , err = readFlag (buf , pos )
if err != nil {
return err
}
if c .TenOrTwelveBit {
c .BitDepth = 12
} else {
c .BitDepth = 10
}
} else {
c .BitDepth = 8
}
tmp , err := readBits (buf , pos , 3 )
if err != nil {
return err
}
c .ColorSpace = uint8 (tmp )
if c .ColorSpace != 7 {
var err error
c .ColorRange , err = readFlag (buf , pos )
if err != nil {
return err
}
if profile == 1 || profile == 3 {
err := hasSpace (buf , *pos , 3 )
if err != nil {
return err
}
c .SubsamplingX = readFlagUnsafe (buf , pos )
c .SubsamplingY = readFlagUnsafe (buf , pos )
*pos ++
} else {
c .SubsamplingX = true
c .SubsamplingY = true
}
} else {
c .ColorRange = true
if profile == 1 || profile == 3 {
c .SubsamplingX = false
c .SubsamplingY = false
err := hasSpace (buf , *pos , 1 )
if err != nil {
return err
}
*pos ++
}
}
return nil
}
type HeaderFrameSize struct {
FrameWidthMinus1 uint16
FrameHeightMinus1 uint16
}
func (s *HeaderFrameSize ) unmarshal (buf []byte , pos *int ) error {
err := hasSpace (buf , *pos , 32 )
if err != nil {
return err
}
s .FrameWidthMinus1 = uint16 (readBitsUnsafe (buf , pos , 16 ))
s .FrameHeightMinus1 = uint16 (readBitsUnsafe (buf , pos , 16 ))
return nil
}
type Header struct {
Profile uint8
ShowExistingFrame bool
FrameToShowMapIdx uint8
NonKeyFrame bool
ShowFrame bool
ErrorResilientMode bool
ColorConfig *HeaderColorConfig
FrameSize *HeaderFrameSize
}
func (h *Header ) Unmarshal (buf []byte ) error {
pos := 0
err := hasSpace (buf , pos , 4 )
if err != nil {
return err
}
frameMarker := readBitsUnsafe (buf , &pos , 2 )
if frameMarker != 2 {
return errInvalidFrameMarker
}
profileLowBit := uint8 (readBitsUnsafe (buf , &pos , 1 ))
profileHighBit := uint8 (readBitsUnsafe (buf , &pos , 1 ))
h .Profile = profileHighBit <<1 + profileLowBit
if h .Profile == 3 {
err = hasSpace (buf , pos , 1 )
if err != nil {
return err
}
pos ++
}
h .ShowExistingFrame , err = readFlag (buf , &pos )
if err != nil {
return err
}
if h .ShowExistingFrame {
var tmp uint64
tmp , err = readBits (buf , &pos , 3 )
if err != nil {
return err
}
h .FrameToShowMapIdx = uint8 (tmp )
return nil
}
err = hasSpace (buf , pos , 3 )
if err != nil {
return err
}
h .NonKeyFrame = readFlagUnsafe (buf , &pos )
h .ShowFrame = readFlagUnsafe (buf , &pos )
h .ErrorResilientMode = readFlagUnsafe (buf , &pos )
if !h .NonKeyFrame {
err := hasSpace (buf , pos , 24 )
if err != nil {
return err
}
frameSyncByte0 := uint8 (readBitsUnsafe (buf , &pos , 8 ))
if frameSyncByte0 != 0x49 {
return errWrongFrameSyncByte0
}
frameSyncByte1 := uint8 (readBitsUnsafe (buf , &pos , 8 ))
if frameSyncByte1 != 0x83 {
return errWrongFrameSyncByte1
}
frameSyncByte2 := uint8 (readBitsUnsafe (buf , &pos , 8 ))
if frameSyncByte2 != 0x42 {
return errWrongFrameSyncByte2
}
h .ColorConfig = &HeaderColorConfig {}
err = h .ColorConfig .unmarshal (h .Profile , buf , &pos )
if err != nil {
return err
}
h .FrameSize = &HeaderFrameSize {}
err = h .FrameSize .unmarshal (buf , &pos )
if err != nil {
return err
}
}
return nil
}
func (h Header ) Width () uint16 {
if h .FrameSize == nil {
return 0
}
return h .FrameSize .FrameWidthMinus1 + 1
}
func (h Header ) Height () uint16 {
if h .FrameSize == nil {
return 0
}
return h .FrameSize .FrameHeightMinus1 + 1
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .