github.com/bluenviron/mediacommon@v1.9.3/pkg/codecs/h264/avcc.go (about)

     1  package h264
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  )
     7  
     8  // ErrAVCCNoNALUs is returned by AVCCUnmarshal when no NALUs have been decoded.
     9  var ErrAVCCNoNALUs = errors.New("AVCC unit doesn't contain any NALU")
    10  
    11  // AVCCUnmarshal decodes an access unit from the AVCC stream format.
    12  // Specification: ISO 14496-15, section 5.3.4.2.1
    13  func AVCCUnmarshal(buf []byte) ([][]byte, error) {
    14  	bl := len(buf)
    15  	pos := 0
    16  	var ret [][]byte
    17  	naluCount := 0
    18  	auSize := 0
    19  
    20  	for {
    21  		if (bl - pos) < 4 {
    22  			return nil, fmt.Errorf("invalid length")
    23  		}
    24  
    25  		l := int(uint32(buf[pos])<<24 | uint32(buf[pos+1])<<16 | uint32(buf[pos+2])<<8 | uint32(buf[pos+3]))
    26  		pos += 4
    27  
    28  		if l != 0 {
    29  			if (auSize + l) > MaxAccessUnitSize {
    30  				return nil, fmt.Errorf("access unit size (%d) is too big, maximum is %d", auSize+l, MaxAccessUnitSize)
    31  			}
    32  
    33  			if (naluCount + 1) > MaxNALUsPerAccessUnit {
    34  				return nil, fmt.Errorf("NALU count (%d) exceeds maximum allowed (%d)",
    35  					len(ret)+1, MaxNALUsPerAccessUnit)
    36  			}
    37  
    38  			if (bl - pos) < l {
    39  				return nil, fmt.Errorf("invalid length")
    40  			}
    41  
    42  			ret = append(ret, buf[pos:pos+l])
    43  			auSize += l
    44  			naluCount++
    45  			pos += l
    46  		}
    47  
    48  		if (bl - pos) == 0 {
    49  			break
    50  		}
    51  	}
    52  
    53  	if ret == nil {
    54  		return nil, ErrAVCCNoNALUs
    55  	}
    56  
    57  	return ret, nil
    58  }
    59  
    60  func avccMarshalSize(au [][]byte) int {
    61  	n := 0
    62  	for _, nalu := range au {
    63  		n += 4 + len(nalu)
    64  	}
    65  	return n
    66  }
    67  
    68  // AVCCMarshal encodes an access unit into the AVCC stream format.
    69  // Specification: ISO 14496-15, section 5.3.4.2.1
    70  func AVCCMarshal(au [][]byte) ([]byte, error) {
    71  	buf := make([]byte, avccMarshalSize(au))
    72  	pos := 0
    73  
    74  	for _, nalu := range au {
    75  		naluLen := len(nalu)
    76  		buf[pos] = byte(naluLen >> 24)
    77  		buf[pos+1] = byte(naluLen >> 16)
    78  		buf[pos+2] = byte(naluLen >> 8)
    79  		buf[pos+3] = byte(naluLen)
    80  		pos += 4
    81  
    82  		pos += copy(buf[pos:], nalu)
    83  	}
    84  
    85  	return buf, nil
    86  }