/* DESCRIPTION cavlc.go provides utilities for context-adaptive variable-length coding for the parsing of H.264 syntax structure fields. AUTHORS Saxon A. Nelson-Milton LICENSE Copyright (C) 2019 the Australian Ocean Lab (AusOcean). It is free software: you can redistribute it and/or modify them under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License in gpl.txt. If not, see http://www.gnu.org/licenses. */ package h264dec import ( "errors" "fmt" "bitbucket.org/ausocean/av/codec/h264/h264dec/bits" ) // parseLevelPrefix parses the level_prefix variable as specified by the process // outlined in section 9.2.2.1 in the specifications. func parseLevelPrefix(br *bits.BitReader) (int, error) { zeros := -1 for b := 0; b != 1; zeros++ { _b, err := br.ReadBits(1) if err != nil { return -1, fmt.Errorf("could not read bit, failed with error: %v", err) } b = int(_b) } 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) } 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") } 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<