From ce803ba4883c7f7b668c363ec9aacc072f010579 Mon Sep 17 00:00:00 2001 From: Saxon Date: Fri, 6 Sep 2019 17:45:23 +0930 Subject: [PATCH] codec/h264/h264dec: add function for parsing level information using process in section 9.2.2 of specifications --- codec/h264/h264dec/cavlc.go | 91 +++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/codec/h264/h264dec/cavlc.go b/codec/h264/h264dec/cavlc.go index c477a490..0dcbc64b 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,93 @@ 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 + if trailingOnes != 0 { + 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) + } + if b == 0 { + levelVal = append(levelVal, 1) + continue + } + levelVal = append(levelVal, -1) + } + } + + 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") + } + + if totalCoeff-trailingOnes != 0 { + 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<