codec/h264/h264dec: using const string instead of CSV file to hold table 9-5. Also made some other minor improvements

This commit is contained in:
Saxon 2019-09-07 22:13:38 +09:30
parent 92eb3e85a5
commit 42a1918c0d
3 changed files with 156 additions and 160 deletions

View File

@ -29,32 +29,13 @@ import (
"encoding/csv"
"errors"
"fmt"
"os"
"strconv"
"strings"
"bitbucket.org/ausocean/av/codec/h264/h264dec/bits"
)
// Initialize the CAVLC coeff_token mapping table.
func init() {
const file = "coefftokenmap.csv"
f, err := os.Open(file)
if err != nil {
panic(fmt.Sprintf("could not open coefftokenmap.csv file, failed with error: %v", err))
}
defer f.Close()
lines, err := csv.NewReader(f).ReadAll()
if err != nil {
panic(fmt.Sprintf("could not read lines from coeftokenmap.csv file, failed with error: %v", err))
}
coeffTokenMaps, err = formCoeffTokenMap(lines)
if err != nil {
panic(fmt.Sprintf("could not form coeff_token map, failed with err: %v", err))
}
}
// TODO: find where these are defined in the specifications.
const (
chromaDCLevel = iota
intra16x16DCLevel
@ -68,6 +49,93 @@ const (
crLevel4x4
)
// Initialize the CAVLC coeff_token mapping table.
func init() {
lines, err := csv.NewReader(strings.NewReader(coeffTokenTable)).ReadAll()
if err != nil {
panic(fmt.Sprintf("could not read lines from coeftokenmap.csv file, failed with error: %v", err))
}
coeffTokenMaps, err = formCoeffTokenMap(lines)
if err != nil {
panic(fmt.Sprintf("could not form coeff_token map, failed with err: %v", err))
}
}
// tokenMap maps coeff_token to values of TrailingOnes(coeff_token) and
// TotalCoeff(coeff_token) given as tokenMap[ number of leading zeros in
// coeff_token][ coeff_token val ][ 0 for trailing ones and 1 for totalCoef ]
type tokenMap map[int]map[int][2]int
// The number of columns in the coeffTokenMap defined below. This is
// representative of the number of defined nC ranges in table 9-5.
const nColumns = 6
// coeffTokenMaps holds a representation of table 9-5 from the specifications, and
// is indexed as follows, coeffToken[ nC group ][ number of coeff_token leading
// zeros ][ value of coeff_token ][ 0 for TrailingOnes(coeff_token) and 1 for
// TotalCoef(coeff_token) ].
var coeffTokenMaps [nColumns]tokenMap
// formCoeffTokenMap populates the global [nColumns]tokenMap coeffTokenMaps
// representation of table 9-5 in the specifications using the coeffTokenTable
// const string defined in cavlctab.go.
func formCoeffTokenMap(lines [][]string) ([nColumns]tokenMap, error) {
var maps [nColumns]tokenMap
for i := range maps {
maps[i] = make(tokenMap)
}
for _, line := range lines {
trailingOnes, err := strconv.Atoi(line[0])
if err != nil {
return maps, fmt.Errorf("could not convert trailingOnes string to int, failed with error: %v", err)
}
totalCoeff, err := strconv.Atoi(line[1])
if err != nil {
return maps, fmt.Errorf("could not convert totalCoeff string to int, failed with error: %v", err)
}
// For each column in this row, therefore each nC category, load the
// coeff_token leading zeros and value into the map.
for j, v := range line[2:] {
if v[0] == '-' {
continue
}
// Count the leading zeros.
var nZeros int
for _, c := range v {
if c == ' ' {
continue
}
if c == '0' {
nZeros++
continue
}
break
}
// This will be the value of the coeff_token (without leading zeros).
val, err := binToInt(v[nZeros:])
if err != nil {
return maps, fmt.Errorf("could not get value of remaining binary, failed with error: %v", err)
}
// Add the TrailingOnes(coeff_token) and TotalCoeff(coeff_token) values
// into the map for the coeff_token leading zeros and value.
if maps[j][nZeros] == nil {
maps[j][nZeros] = make(map[int][2]int)
}
maps[j][nZeros][val] = [2]int{trailingOnes, totalCoeff}
}
}
return maps, nil
}
// TODO: put this somewhere more appropriate once context is understood.
type block struct {
usingInterMbPredMode bool
@ -243,80 +311,6 @@ func available(b block) bool {
return true
}
// The number of columns in the coeffTokenMap defined below. This is
// representative of the number of defined nC ranges defined in table 9-5.
const nColumns = 6
// coeffMapping maps values of coeff_token to values of TrailingOnes(coeff_token)
// and TotalCoeff(coeff_token) given as map[ coeff_token val ][ 0 for trailing ones
// and 1 for totalCoef ]
type tokenMap map[int]map[int][2]int
// coeffTokenMap will a representation of table 9-5 from the specifications, and
// is indexed as follows, coeffToken[ nC group ][ number of coeff_token leading
// zeros ][ value of coeff_token ][ 0 for TrailingOnes(coeff_token) and 1 for
// TotalCoef(coeff_token) ].
var coeffTokenMaps [nColumns]tokenMap
// formCoeffTokenMap populates the global [nColumns]map[int]map[int][2]int,
// coeffTokenMap representation of table 9-5 from the specifications using lines
// read from a corresponding CSV file coefftokenmap.csv.
func formCoeffTokenMap(lines [][]string) ([nColumns]tokenMap, error) {
var maps [nColumns]tokenMap
for i := range maps {
maps[i] = make(tokenMap)
}
for _, line := range lines {
trailingOnes, err := strconv.Atoi(line[0])
if err != nil {
return maps, fmt.Errorf("could not convert trailingOnes string to int, failed with error: %v", err)
}
totalCoeff, err := strconv.Atoi(line[1])
if err != nil {
return maps, fmt.Errorf("could not convert totalCoeff string to int, failed with error: %v", err)
}
// For each column in this row, therefore each nC category, load the
// coeff_token leading zeros and value into the map.
for j, v := range line[2:] {
if v[0] == '-' {
continue
}
// Count the leading zeros.
var nZeros int
for _, c := range v {
if c == ' ' {
continue
}
if c == '0' {
nZeros++
continue
}
break
}
// This will be the value of the coeff_token (without leading zeros).
val, err := binToInt(v[nZeros:])
if err != nil {
return maps, fmt.Errorf("could not get value of remaining binary, failed with error: %v", err)
}
// Add the TrailingOnes(coeff_token) and TotalCoeff(coeff_token) values
// into the map for the coeff_token leading zeros and value.
if maps[j][nZeros] == nil {
maps[j][nZeros] = make(map[int][2]int)
}
maps[j][nZeros][val] = [2]int{trailingOnes, totalCoeff}
}
}
return maps, nil
}
// 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) {

View File

@ -35,14 +35,14 @@ import (
func TestFormCoeffTokenMap(t *testing.T) {
tests := []struct {
in [][]string
want [nColumns]map[int]map[int][2]int
want [nColumns]tokenMap
}{
{
in: [][]string{
{"0", "0", "1", "11", "1111", "0000 11", "01", "1"},
{"0", "1", "0001 01", "0010 11", "0011 11", "0000 00", "0001 11", "0001 111"},
},
want: [nColumns]map[int]map[int][2]int{
want: [nColumns]tokenMap{
0: {
0: {1: {0, 0}},
3: {5: {0, 1}},
@ -74,7 +74,7 @@ func TestFormCoeffTokenMap(t *testing.T) {
{"0", "0", "1", "11", "1111", "0000 11", "01", "1"},
{"0", "1", "0001 01", "0010 11", "0011 11", "-", "0001 11", "0001 111"},
},
want: [nColumns]map[int]map[int][2]int{
want: [nColumns]tokenMap{
0: {
0: {1: {0, 0}},
3: {5: {0, 1}},

View File

@ -1,4 +1,6 @@
0,0,1,11,1111,0000 11,01,1
package h264dec
const coeffTokenTable = `0,0,1,11,1111,0000 11,01,1
0,1,0001 01,0010 11,0011 11,0000 00,0001 11,0001 111
1,1,01,10,1110,0000 01,1,01
0,2,0000 0111,0001 11,0010 11,0001 00,0001 00,0001 110
@ -59,4 +61,4 @@
0,16,0000 0000 0000 0100,0000 0000 0001 11,0000 0000 01,1111 00,-,-
1,16,0000 0000 0000 0110,0000 0000 0001 10,0000 0001 00,1111 01,-,-
2,16,0000 0000 0000 0101,0000 0000 0001 01,0000 0000 11,1111 10,-,-
3,16,0000 0000 0000 1000,0000 0000 0001 00,0000 0000 10,1111 11,-,-
3,16,0000 0000 0000 1000,0000 0000 0001 00,0000 0000 10,1111 11,-,-`