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  }