github.com/bluenviron/mediacommon@v1.9.3/pkg/codecs/av1/bitstream.go (about) 1 package av1 2 3 import ( 4 "fmt" 5 ) 6 7 func obuRemoveSize(h *OBUHeader, sizeN int, ob []byte) []byte { 8 newOBU := make([]byte, len(ob)-sizeN) 9 newOBU[0] = (byte(h.Type) << 3) 10 copy(newOBU[1:], ob[1+sizeN:]) 11 return newOBU 12 } 13 14 // BitstreamUnmarshal extracts a temporal unit from a bitstream. 15 // Optionally, it also removes the size field from OBUs. 16 // Specification: https://aomediacodec.github.io/av1-spec/#low-overhead-bitstream-format 17 func BitstreamUnmarshal(bs []byte, removeSizeField bool) ([][]byte, error) { 18 var ret [][]byte 19 20 for { 21 var h OBUHeader 22 err := h.Unmarshal(bs) 23 if err != nil { 24 return nil, err 25 } 26 27 if !h.HasSize { 28 return nil, fmt.Errorf("OBU size not present") 29 } 30 31 size, sizeN, err := LEB128Unmarshal(bs[1:]) 32 if err != nil { 33 return nil, err 34 } 35 36 obuLen := 1 + sizeN + int(size) 37 if len(bs) < obuLen { 38 return nil, fmt.Errorf("not enough bytes") 39 } 40 41 obu := bs[:obuLen] 42 43 if removeSizeField { 44 obu = obuRemoveSize(&h, sizeN, obu) 45 } 46 47 ret = append(ret, obu) 48 bs = bs[obuLen:] 49 50 if len(bs) == 0 { 51 break 52 } 53 } 54 55 return ret, nil 56 } 57 58 // BitstreamMarshal encodes a temporal unit into a bitstream. 59 // Specification: https://aomediacodec.github.io/av1-spec/#low-overhead-bitstream-format 60 func BitstreamMarshal(tu [][]byte) ([]byte, error) { 61 n := 0 62 63 for _, obu := range tu { 64 n += len(obu) 65 66 var h OBUHeader 67 err := h.Unmarshal(obu) 68 if err != nil { 69 return nil, err 70 } 71 72 if !h.HasSize { 73 size := len(obu) - 1 74 n += LEB128MarshalSize(uint(size)) 75 } 76 } 77 78 buf := make([]byte, n) 79 n = 0 80 81 for _, obu := range tu { 82 var h OBUHeader 83 h.Unmarshal(obu) //nolint:errcheck 84 85 if !h.HasSize { 86 buf[n] = obu[0] | 0b00000010 87 n++ 88 size := len(obu) - 1 89 n += LEB128MarshalTo(uint(size), buf[n:]) 90 n += copy(buf[n:], obu[1:]) 91 } 92 } 93 94 return buf, nil 95 }