/* DESCRIPTION slice_test.go provides testing for parsing functionality found in slice.go. AUTHORS Saxon Nelson-Milton <saxon@ausocean.org> Shawn Smith <shawn@ausocean.org> 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 ( "bytes" "reflect" "testing" "bitbucket.org/ausocean/av/codec/h264/h264dec/bits" ) var subWidthCTests = []struct { in SPS want int }{ {SPS{}, 17}, {SPS{ChromaFormatIDC: 0}, 17}, {SPS{ChromaFormatIDC: 1}, 2}, {SPS{ChromaFormatIDC: 2}, 2}, {SPS{ChromaFormatIDC: 3}, 1}, {SPS{ChromaFormatIDC: 3, SeparateColorPlaneFlag: true}, 17}, {SPS{ChromaFormatIDC: 999}, 17}, } // TestSubWidthC tests that the correct SubWidthC is returned given // SPS inputs with various chroma formats. func TestSubWidthC(t *testing.T) { for _, tt := range subWidthCTests { if got := SubWidthC(&tt.in); got != tt.want { t.Errorf("SubWidthC(%#v) = %d, want %d", tt.in, got, tt.want) } } } var subHeightCTests = []struct { in SPS want int }{ {SPS{}, 17}, {SPS{ChromaFormatIDC: 0}, 17}, {SPS{ChromaFormatIDC: 1}, 2}, {SPS{ChromaFormatIDC: 2}, 1}, {SPS{ChromaFormatIDC: 3}, 1}, {SPS{ChromaFormatIDC: 3, SeparateColorPlaneFlag: true}, 17}, {SPS{ChromaFormatIDC: 999}, 17}, } // TestSubHeightC tests that the correct SubHeightC is returned given // SPS inputs with various chroma formats. func TestSubHeightC(t *testing.T) { for _, tt := range subHeightCTests { if got := SubHeightC(&tt.in); got != tt.want { t.Errorf("SubHeight(%#v) = %d, want %d", tt.in, got, tt.want) } } } func TestNewRefPicListModification(t *testing.T) { tests := []struct { in string s SliceHeader p PPS want RefPicListModification }{ { in: "1" + // u(1) ref_pic_list_modification_flag_l0=true // First modification for list0 "1" + // ue(v) modification_of_pic_nums_idc[0][0] = 0 "010" + // ue(v) abs_diff_pic_num_minus1[0][0] = 1 // Second modification for list0 "010" + // ue(v) modification_of_pic_nums_idc[0][1] = 1 "011" + // ue(v) abs_diff_pic_num_minus1[0][1] = 2 // Third modification for list0 "011" + // ue(v) modification_of_pic_nums_idc[0][2] = 2 "010" + // ue(v) long_term_pic_num = 1 // Fourth modification does not exist "00100", // ue(v) modification_of_pic_nums_idc[0][3] = 3 s: SliceHeader{ SliceType: 3, }, p: PPS{ NumRefIdxL0DefaultActiveMinus1: 2, }, want: RefPicListModification{ RefPicListModificationFlag: [2]bool{true, false}, ModificationOfPicNums: [2][]int{{0, 1, 2, 3}, {0, 0}}, AbsDiffPicNumMinus1: [2][]int{{1, 2, 0, 0}, {0, 0}}, LongTermPicNum: [2][]int{{0, 0, 1, 0}, {0, 0}}, }, }, } for i, test := range tests { inBytes, err := binToSlice(test.in) if err != nil { t.Fatalf("unexpected error %v for binToSlice in test %d", err, i) } got, err := NewRefPicListModification(bits.NewBitReader(bytes.NewReader(inBytes)), &test.p, &test.s) if err != nil { t.Fatalf("unexpected error %v for NewRefPicListModification in test %d", err, i) } if !reflect.DeepEqual(*got, test.want) { t.Errorf("did not get expected result for test %d\nGot: %v\nWant: %v\n", i, got, test.want) } } } func TestNewPredWeightTable(t *testing.T) { tests := []struct { in string sliceHeader SliceHeader chromaArrayType int want PredWeightTable }{ { in: "011" + // ue(v) luma_log2_weight_denom = 2 "00100" + // ue(v) chroma_log2_weigght_denom = 3 // list0 // i = 0 "1" + // u(1) luma_weight_l0_flag = true "011" + // se(v) luma_weight_l0[0] = -1 "010" + // se(v) luma_offset_l0[0] = 1 "1" + // u(1) chroma_weight_l0_flag = true // i = 0, j = 0 "010" + // se(v) chroma_weight_l0[0][0] = 1 "010" + // se(v) chroma_offset_l0[0][0] = 1 // i = 0, j = 1 "010" + // se(v) chroma_weight_l0[0][1] = 1 "010" + // se(v) chroma_offset_l0[0][1] = 1 // i = 1 "1" + // u(1) luma_weight_l0_flag = true "011" + // se(v) luma_weight_l0[1] = -1 "00100" + // se(v) luma_offset_l0[1] = 2 "1" + // u(1) chroma_weight_l0_flag = true // i = 1, j = 0 "011" + // se(v) chroma_weight_l0[1][0] = -1 "00101" + // se(v) chroma_offset_l0[1][0] = -2 // i = 1, j = 1 "011" + // se(v) chroma_weight_l0[1][1] = -1 "011" + // se(v) chroma_offset_l0[1][1] = -1 // list1 // i = 0 "1" + // u(1) luma_weight_l1_flag = true "011" + // se(v) luma_weight_l1[0] = -1 "010" + // se(v) luma_offset_l1[0] = 1 "1" + // u(1) chroma_weight_l1_flag = true // i = 0, j = 0 "010" + // se(v) chroma_weight_l1[0][0] = 1 "010" + // se(v) chroma_offset_l1[0][0] = 1 // i = 0, j = 1 "010" + // se(v) chroma_weight_l1[0][1] = 1 "010" + // se(v) chroma_offset_l1[0][1] = 1 // i = 1 "1" + // u(1) luma_weight_l1_flag = true "011" + // se(v) luma_weight_l1[1] = -1 "00100" + // se(v) luma_offset_l1[1] = 2 "1" + // u(1) chroma_weight_l1_flag = true // i = 1, j = 0 "011" + // se(v) chroma_weight_l0[1][0] = -1 "00101" + // se(v) chroma_offset_l0[1][0] = -2 // i = 1, j = 1 "011" + // se(v) chroma_weight_l0[1][1] = -1 "011", // se(v) chroma_offset_l0[1][1] = -1 sliceHeader: SliceHeader{ NumRefIdxL0ActiveMinus1: 1, NumRefIdxL1ActiveMinus1: 1, SliceType: 1, }, chromaArrayType: 1, want: PredWeightTable{ LumaLog2WeightDenom: 2, ChromaLog2WeightDenom: 3, LumaWeightL0Flag: true, LumaWeightL0: []int{-1, -1}, LumaOffsetL0: []int{1, 2}, ChromaWeightL0Flag: true, ChromaWeightL0: [][]int{{1, 1}, {-1, -1}}, ChromaOffsetL0: [][]int{{1, 1}, {-2, -1}}, LumaWeightL1Flag: true, LumaWeightL1: []int{-1, -1}, LumaOffsetL1: []int{1, 2}, ChromaWeightL1Flag: true, ChromaWeightL1: [][]int{{1, 1}, {-1, -1}}, ChromaOffsetL1: [][]int{{1, 1}, {-2, -1}}, }, }, } for i, test := range tests { inBytes, err := binToSlice(test.in) if err != nil { t.Fatalf("unexpected error %v for binToSlice in test %d", err, i) } got, err := NewPredWeightTable(bits.NewBitReader(bytes.NewReader(inBytes)), &test.sliceHeader, test.chromaArrayType) if err != nil { t.Fatalf("unexpected error %v for NewPredWeightTable in test %d", err, i) } if !reflect.DeepEqual(*got, test.want) { t.Errorf("did not get expected result for test %d\nGot: %v\nWant: %v\n", i, got, test.want) } } } func TestDecRefPicMarking(t *testing.T) { tests := []struct { in string idrPic bool want DecRefPicMarking }{ { in: "0" + // u(1) no_output_of_prior_pics_flag = false "1", // u(1) long_term_reference_flag = true idrPic: true, want: DecRefPicMarking{ NoOutputOfPriorPicsFlag: false, LongTermReferenceFlag: true, }, }, { in: "1" + // u(1) adaptive_ref_pic_marking_mode_flag = true "010" + // ue(v) memory_management_control_operation = 1 "011" + // ue(v) difference_of_pic_nums_minus1 = 2 "00100" + // ue(v) memory_management_control_operation = 3 "1" + // ue(v) difference_of_pic_nums_minus1 = 0 "011" + // ue(v) long_term_frame_idx = 2 "011" + // ue(v) memory_management_control_operation = 2 "00100" + // ue(v) long_term_pic_num = 3 "00101" + // ue(v) memory_management_control_operation = 4 "010" + // ue(v) max_long_term_frame_idx_plus1 = 1 "1", // ue(v) memory_management_control_operation = 0 idrPic: false, want: DecRefPicMarking{ AdaptiveRefPicMarkingModeFlag: true, elements: []drpmElement{ { MemoryManagementControlOperation: 1, DifferenceOfPicNumsMinus1: 2, }, { MemoryManagementControlOperation: 3, DifferenceOfPicNumsMinus1: 0, LongTermFrameIdx: 2, }, { MemoryManagementControlOperation: 2, LongTermPicNum: 3, }, { MemoryManagementControlOperation: 4, MaxLongTermFrameIdxPlus1: 1, }, { MemoryManagementControlOperation: 0, }, }, }, }, } for i, test := range tests { inBytes, err := binToSlice(test.in) if err != nil { t.Fatalf("unexpected error %v for binToSlice in test %d", err, i) } got, err := NewDecRefPicMarking(bits.NewBitReader(bytes.NewReader(inBytes)), test.idrPic) if err != nil { t.Fatalf("unexpected error %v for NewPredWeightTable in test %d", err, i) } if !reflect.DeepEqual(*got, test.want) { t.Errorf("did not get expected result for test %d\nGot: %v\nWant: %v\n", i, got, test.want) } } }