diff --git a/codec/h264/h264dec/cabac.go b/codec/h264/h264dec/cabac.go index 21ae8316..9e353b5f 100644 --- a/codec/h264/h264dec/cabac.go +++ b/codec/h264/h264dec/cabac.go @@ -733,3 +733,21 @@ func CtxIdx(binIdx, maxBinIdxCtx, ctxIdxOffset int) int { return ctxIdx } + +// Error used by unaryBinarization. +var errNegativeSyntaxVal = errors.New("cannot get unary binarization of negative value") + +// unaryBinarization returns the unary binarization of a syntax element having +// value v, as specified by setion 9.3.2.1 in the specifications. +func unaryBinarization(v int) ([]int, error) { + if v < 0 { + return nil, errNegativeSyntaxVal + } + r := make([]int, v+1) + for i := 0; i <= v; i++ { + if i < v { + r[i] = 1 + } + } + return r, nil +} diff --git a/codec/h264/h264dec/cabac_test.go b/codec/h264/h264dec/cabac_test.go index 0d8adaa4..9bc3a35a 100644 --- a/codec/h264/h264dec/cabac_test.go +++ b/codec/h264/h264dec/cabac_test.go @@ -186,3 +186,31 @@ func TestCtxIdx(t *testing.T) { } } } + +func TestUnaryBinarization(t *testing.T) { + // Test data has been extracted from table 9-35 of the specifications. + tests := []struct { + in int + want []int + err error + }{ + {in: 0, want: []int{0}, err: nil}, + {in: 1, want: []int{1, 0}, err: nil}, + {in: 2, want: []int{1, 1, 0}, err: nil}, + {in: 3, want: []int{1, 1, 1, 0}, err: nil}, + {in: 4, want: []int{1, 1, 1, 1, 0}, err: nil}, + {in: 5, want: []int{1, 1, 1, 1, 1, 0}, err: nil}, + {in: -3, want: nil, err: errNegativeSyntaxVal}, + } + + for i, test := range tests { + got, err := unaryBinarization(test.in) + if err != test.err { + t.Errorf("did not get expected error for test %d\nGot: %v\nWant: %v", i, err, test.err) + } + + if !reflect.DeepEqual(test.want, got) { + t.Errorf("did not get expected result for test %d\nGot: %v\nWant: %v\n", i, got, test.want) + } + } +}