diff --git a/codec/h264/h264dec/cavlc.go b/codec/h264/h264dec/cavlc.go index c477a490..e1932548 100644 --- a/codec/h264/h264dec/cavlc.go +++ b/codec/h264/h264dec/cavlc.go @@ -26,6 +26,7 @@ LICENSE package h264dec import ( + "errors" "fmt" "bitbucket.org/ausocean/av/codec/h264/h264dec/bits" @@ -44,3 +45,85 @@ func parseLevelPrefix(br *bits.BitReader) (int, error) { } return zeros, nil } + +// parseLevelInformation parses level information and returns the resultant +// levelVal list using the process defined by section 9.2.2 in the specifications. +func parseLevelInformation(br *bits.BitReader, totalCoeff, trailingOnes int) ([]int, error) { + var levelVal []int + var i int + for ; i < trailingOnes; i++ { + b, err := br.ReadBits(1) + if err != nil { + return nil, fmt.Errorf("could not read trailing_ones_sign_flag, failed with error: %v", err) + } + levelVal = append(levelVal, 1-int(b)*2) + } + + var suffixLen int + switch { + case totalCoeff > 10 && trailingOnes < 3: + suffixLen = 1 + case totalCoeff <= 10 || trailingOnes == 3: + suffixLen = 0 + default: + return nil, errors.New("invalid TotalCoeff and TrailingOnes combination") + } + + for j := 0; j < totalCoeff-trailingOnes; j++ { + levelPrefix, err := parseLevelPrefix(br) + if err != nil { + return nil, fmt.Errorf("could not parse level prefix, failed with error: %v", err) + } + + var levelSuffixSize int + switch { + case levelPrefix == 14 && suffixLen == 0: + levelSuffixSize = 4 + case levelPrefix >= 15: + levelSuffixSize = levelPrefix - 3 + default: + levelSuffixSize = suffixLen + } + + var levelSuffix int + if levelSuffixSize > 0 { + b, err := br.ReadBits(levelSuffixSize) + if err != nil { + return nil, fmt.Errorf("could not parse levelSuffix, failed with error: %v", err) + } + levelSuffix = int(b) + } else { + levelSuffix = 0 + } + + levelCode := (mini(15, levelPrefix) << uint(suffixLen)) + levelSuffix + + if levelPrefix >= 15 && suffixLen == 0 { + levelCode += 15 + } + + if levelPrefix >= 16 { + levelCode += (1 << uint(levelPrefix-3)) - 4096 + } + + if i == trailingOnes && trailingOnes < 3 { + levelCode += 2 + } + + if levelCode%2 == 0 { + levelVal = append(levelVal, (levelCode+2)>>1) + } else { + levelVal = append(levelVal, (-levelCode-1)>>1) + } + + if suffixLen == 0 { + suffixLen = 1 + } + + if absi(levelVal[i]) > (3<