mirror of
https://github.com/status-im/status-go.git
synced 2025-02-15 08:17:28 +00:00
* chore_: bump go-waku with filter loop fix * fix_: correct fleet node for staging fleet * fix_: use shards for lightclient init --------- Co-authored-by: Richard Ramos <info@richardramos.me>
222 lines
4.4 KiB
Go
222 lines
4.4 KiB
Go
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
// Package vp9 contains a VP9 header parser.
|
|
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")
|
|
)
|
|
|
|
// HeaderColorConfig is the color_config member of an header.
|
|
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
|
|
}
|
|
|
|
// HeaderFrameSize is the frame_size member of an header.
|
|
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
|
|
}
|
|
|
|
// Header is a VP9 Frame header.
|
|
// Specification:
|
|
// https://storage.googleapis.com/downloads.webmproject.org/docs/vp9/vp9-bitstream-specification-v0.6-20160331-draft.pdf
|
|
type Header struct {
|
|
Profile uint8
|
|
ShowExistingFrame bool
|
|
FrameToShowMapIdx uint8
|
|
NonKeyFrame bool
|
|
ShowFrame bool
|
|
ErrorResilientMode bool
|
|
ColorConfig *HeaderColorConfig
|
|
FrameSize *HeaderFrameSize
|
|
}
|
|
|
|
// Unmarshal decodes a Header.
|
|
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
|
|
}
|
|
|
|
// Width returns the video width.
|
|
func (h Header) Width() uint16 {
|
|
if h.FrameSize == nil {
|
|
return 0
|
|
}
|
|
return h.FrameSize.FrameWidthMinus1 + 1
|
|
}
|
|
|
|
// Height returns the video height.
|
|
func (h Header) Height() uint16 {
|
|
if h.FrameSize == nil {
|
|
return 0
|
|
}
|
|
return h.FrameSize.FrameHeightMinus1 + 1
|
|
}
|