av/codec/h264/h264dec/pps_test.go

148 lines
4.6 KiB
Go

package h264dec
import (
"bytes"
"errors"
"reflect"
"testing"
"bitbucket.org/ausocean/av/codec/h264/h264dec/bits"
)
func TestNewPPS(t *testing.T) {
// TODO: add test with scaling list once we have a test for scalingList func.
tests := []struct {
in string
chromaFormat int
want PPS
}{
{
in: "1" + // ue(v) pic_parameter_set_id = 0
"1" + // ue(v) seq_parameter_set_id = 0
"1" + // u(1) entropy_coding_mode_flag = 1
"0" + // u(1) pic_order_present_flag = 0
"1" + // ue(v) num_slice_groups_minus1 = 0
"1" + // ue(v) num_ref_idx_L0_active_minus1 = 0
"1" + // ue(v) num_ref_idx_L1_active_minus1 = 0
"1" + // u(1) weighted_pred_flag = 1
"00" + // u(2) weighted_bipred_idc = 0
"1" + // se(v) pic_init_qp_minus26 = 0
"1" + // se(v) pic_init_qs_minus26 = 0
"1" + // se(v) chroma_qp_index_offset = 0
"1" + // u(1) deblocking_filter_control_present_flag = 1
"0" + // u(1) constrained_intra_pred_flag = 0
"0" + // u(1) redundant_pic_cnt_present_flag = 0
"10000000", // rbspTrailingBits
want: PPS{
ID: 0,
SPSID: 0,
EntropyCodingMode: 1,
BottomFieldPicOrderInFramePresent: false,
NumSliceGroupsMinus1: 0,
NumRefIdxL0DefaultActiveMinus1: 0,
NumRefIdxL1DefaultActiveMinus1: 0,
WeightedPred: true,
WeightedBipred: 0,
PicInitQpMinus26: 0,
PicInitQsMinus26: 0,
ChromaQpIndexOffset: 0,
DeblockingFilterControlPresent: true,
ConstrainedIntraPred: false,
RedundantPicCntPresent: false,
},
},
{
in: "1" + // ue(v) pic_parameter_set_id = 0
"1" + // ue(v) seq_parameter_set_id = 0
"1" + // u(1) entropy_coding_mode_flag = 1
"1" + // u(1) bottom_field_pic_order_in_frame_present_flag = 1
"010" + // ue(v) num_slice_groups_minus1 = 1
"1" + // ue(v) slice_group_map_type = 0
"1" + // ue(v) run_length_minus1[0] = 0
"1" + // ue(v) run_length_minus1[1] = 0
"1" + // ue(v) num_ref_idx_L0_active_minus1 = 0
"1" + // ue(v) num_ref_idx_L1_active_minus1 = 0
"1" + // u(1) weighted_pred_flag = 0
"00" + // u(2) weighted_bipred_idc = 0
"011" + // se(v) pic_init_qp_minus26 = -1
"010" + // se(v) pic_init_qs_minus26 = 1
"00100" + // se(v) chroma_qp_index_offset = 2
"0" + // u(1) deblocking_filter_control_present_flag =0
"0" + // u(1) constrained_intra_pred_flag=0
"0" + // u(1) redundant_pic_cnt_present_flag=0
"0" + // u(1) transform_8x8_mode_flag=0
"0" + // u(1) pic_scaling_matrix_present_flag=0
"00100" + // se(v) second_chroma_qp_index_offset=2
"10000", // stop bit and trailing bits
want: PPS{
ID: 0,
SPSID: 0,
EntropyCodingMode: 1,
BottomFieldPicOrderInFramePresent: true,
NumSliceGroupsMinus1: 1,
RunLengthMinus1: []int{0, 0},
NumRefIdxL0DefaultActiveMinus1: 0,
NumRefIdxL1DefaultActiveMinus1: 0,
WeightedPred: true,
WeightedBipred: 0,
PicInitQpMinus26: -1,
PicInitQsMinus26: 1,
ChromaQpIndexOffset: 2,
DeblockingFilterControlPresent: false,
ConstrainedIntraPred: false,
RedundantPicCntPresent: false,
Transform8x8Mode: 0,
PicScalingMatrixPresent: false,
SecondChromaQpIndexOffset: 2,
},
},
}
for i, test := range tests {
bin, err := binToSlice(test.in)
if err != nil {
t.Fatalf("error: %v converting binary string to slice for test: %d", err, i)
}
pps, err := NewPPS(bits.NewBitReader(bytes.NewReader(bin)), test.chromaFormat)
if err != nil {
t.Fatalf("did not expect error: %v for test: %d", err, i)
}
if !reflect.DeepEqual(test.want, *pps) {
t.Errorf("did not get expected result for test: %d.\nGot: %+v\nWant: %+v\n", i, *pps, test.want)
}
}
}
// binToSlice is a helper function to convert a string of binary into a
// corresponding byte slice, e.g. "0100 0001 1000 1100" => {0x41,0x8c}.
// Spaces in the string are ignored.
func binToSlice(s string) ([]byte, error) {
var (
a byte = 0x80
cur byte
bytes []byte
)
for _, c := range s {
switch c {
case ' ':
continue
case '1':
cur |= a
case '0':
default:
return nil, errors.New("invalid binary string")
}
a >>= 1
if a == 0 {
bytes = append(bytes, cur)
cur = 0
a = 0x80
}
}
return bytes, nil
}