def test_allow_subset(self): assert (is_allowed_combination( [{ "foo": ValueSet(123), "bar": ValueSet() }], {"foo": 123}, ) is True)
def test_add_range_overlap_single_values(self): vs = ValueSet() vs.add_value(5) vs.add_value(10) vs.add_value(15) vs.add_value(20) vs.add_value(25) vs.add_range(10, 20) assert vs._values == set([5, 25]) assert vs._ranges == set([(10, 20)])
def test_unfiltered(self): assert (allowed_values_for( [{ "foo": ValueSet(1) }, { "foo": ValueSet(2) }, { "foo": ValueSet(3) }], "foo", ) == ValueSet(1, 2, 3))
def test_allow_matching(self): assert (is_allowed_combination( [{ "foo": ValueSet(123), "bar": ValueSet(321) }], { "foo": 123, "bar": 321 }, ) is True)
def test_disallow_no_completely_matching_set(self): assert (is_allowed_combination( [{ "foo": ValueSet(123) }, { "bar": ValueSet(321) }], { "foo": 123, "bar": 321 }, ) is False)
def test_generates_custom_quant_matrices( self, lossless, asymmetric, constrain_level_zero, initial_quant_matrix, exp_matrices, ): codec_features = CodecFeatures( MINIMAL_CODEC_FEATURES_WITH_CUSTOM_QUANT_MATRIX, wavelet_index_ho=(WaveletFilters.le_gall_5_3 if not asymmetric else WaveletFilters.fidelity), quantization_matrix=initial_quant_matrix, lossless=lossless, picture_bytes=(None if lossless else MINIMAL_CODEC_FEATURES_WITH_CUSTOM_QUANT_MATRIX[ "picture_bytes"]), ) with temporary_level_override(): if constrain_level_zero: # Sanity check assert LEVEL_CONSTRAINTS[0]["level"] == ValueSet(0) LEVEL_CONSTRAINTS[0]["quant_matrix_values"] = ValueSet(3, 4, 8) test_cases = list(custom_quantization_matrix(codec_features)) matrices = {} for test_case in test_cases: stream = test_case.value to_visit = list(stream["sequences"][0]["data_units"]) while to_visit: d = to_visit.pop(0) if isinstance(d, dict): for key, value in d.items(): if key == "quant_matrix": assert value["custom_quant_matrix"] matrix = value["quant_matrix"] if test_case.subcase_name in matrices: # All pictures should have same custom # quantization matrix assert matrix == matrices[ test_case.subcase_name] else: matrices[test_case.subcase_name] = matrix else: to_visit.append(value) assert matrices == exp_matrices
def test_add_value(self): vs = ValueSet() # Duplicate values not allowed vs.add_value(123) vs.add_value(123) assert list(vs) == [123] # Values already in a range not allowed vs.add_range(10, 20) vs.add_value(10) vs.add_value(15) vs.add_value(20) assert list(vs) == [123, (10, 20)]
def test_value_ranges_restricted(self, dwt_depth, dwt_depth_ho, matrix, exp_fail_value): state = { "wavelet_index": tables.WaveletFilters.haar_no_shift, "wavelet_index_ho": tables.WaveletFilters.haar_no_shift, "dwt_depth": dwt_depth, "dwt_depth_ho": dwt_depth_ho, "_level_constrained_values": { "level": tables.Levels.sub_sd }, } state.update( bytes_to_state( serialise_to_bytes( bitstream.QuantMatrix( custom_quant_matrix=True, quant_matrix=matrix, ), state.copy(), ))) if exp_fail_value is not None: with pytest.raises(decoder.QuantisationMatrixValueNotAllowedInLevel ) as exc_info: decoder.quant_matrix(state) assert exc_info.value.value == exp_fail_value assert exc_info.value.allowed_values == ValueSet((0, 127)) assert exc_info.value.level_constrained_values == { "level": tables.Levels.sub_sd, "custom_quant_matrix": True, } else: decoder.quant_matrix(state)
def test_disallow_mismatching(self): assert (is_allowed_combination( [{ "foo": ValueSet(321) }], {"foo": 123}, ) is False)
def test_any_value_substitution(self): allowed_values = [ { "foo": AnyValue(), "bar": ValueSet(123) }, { "foo": ValueSet(2), "bar": ValueSet(321) }, { "foo": ValueSet(3), "bar": ValueSet(123) }, ] # No substitution assert allowed_values_for(allowed_values, "foo", {"bar": 123}) == AnyValue() # With substitution assert (allowed_values_for( allowed_values, "foo", {"bar": 123}, ValueSet(1, 2, 3, 4), ) == ValueSet(1, 2, 3, 4))
def test_combine(self): a1 = AnyValue() a2 = AnyValue() vs = ValueSet() for a in [a1, a2, vs]: for b in [a1, a2, vs]: if not (a == b == vs): assert isinstance(a + b, AnyValue)
def test_disallow_superset(self): assert (is_allowed_combination( [{ "foo": ValueSet(123) }], { "foo": 123, "bar": 321 }, ) is False)
def test_remove_non_matching_combinations(self): allowed_values = [ {}, { "foo": ValueSet(123) }, { "foo": ValueSet(123), "bar": ValueSet(321) }, { "foo": ValueSet(321) }, { "bar": ValueSet(321) }, ] assert (filter_constraint_table(allowed_values, {"foo": 123}) == allowed_values[:3])
def decide_extended_transform_flag(codec_features, flag_name, required): """ Decide what asym_transform*_flag setting to use, accounting for level restrictions. Parameters ========== codec_features : :py:class:`~vc2_conformance.codec_features.CodecFeatures` flag_name : str The name of the flag to be decided (e.g. "asym_transform_index_flag"). required : str If True, require this flag to be True, if False, the flag may be set to True or False, as allowed by the level, preferring False. Returns ======= flag : bool Raises ====== vc2_conformance.encoder.exceptions.IncompatibleLevelAndExtendedTransformParametersError If ``required`` is True but the level prohibits the flag. """ # The flag states which we could use to encode the required value usable_flags = [True] if required else [False, True] # The allowed flag values according to the current level constrained_values = codec_features_to_trivial_level_constraints( codec_features) permitted_flags = allowed_values_for(LEVEL_CONSTRAINTS, flag_name, constrained_values) # Warning: Slight bodge/special case handled here... # # The make_extended_transform_parameters function (and by extension, this # function) is required to return an ExtendedTransformParameters object # even for streams with major_version < 3 which don't contain that field. # # To handle this case, we treat an empty constraint table entry as allowing # 'False' as a valid flag option when in reality for < v3 streams no value # is permitted. # # Note that we will still raise # IncompatibleLevelAndExtendedTransformParametersError if required is True # in this case. We also don't allow False if the level specifically # requires the flag to be True (i.e. we only allow it when the level gives # no values). if permitted_flags == ValueSet(): permitted_flags.add_value(False) try: return next(flag for flag in usable_flags if flag in permitted_flags) except StopIteration: raise IncompatibleLevelAndExtendedTransformParametersError( codec_features)
def test_iter(self): vs = ValueSet() assert set(vs) == set() vs.add_value(1) vs.add_value(2) vs.add_value(3) assert set(vs) == set([1, 2, 3]) vs.add_range(10, 20) vs.add_range(30, 40) assert set(vs) == set([1, 2, 3, (10, 20), (30, 40)])
def test_level_assumptions(self): # The test case generator assumes that levels either require the slice # prefix bytes to be zero or allow it to be anything -- any condition # other than this would require the test case generator to be more # flexible than it is. # # The above assumption is verified below for values in LEVEL_CONSTRAINTS: if Profiles.high_quality in values["profile"]: assert values["slice_prefix_bytes"] == AnyValue() or values[ "slice_prefix_bytes" ] == ValueSet(0)
def test_repr(self): vs = ValueSet() assert repr(vs) == "ValueSet()" vs.add_value(123) vs.add_range(10, 20) assert repr(vs) == "ValueSet(123, (10, 20))"
def test_ranges(self): vs = ValueSet() vs.add_range(10, 20) assert 9 not in vs assert 9.9999 not in vs assert 10 in vs assert 15 in vs assert 20 in vs assert 20.0001 not in vs assert 21 not in vs vs.add_range(30, 40) assert 9 not in vs assert 9.9999 not in vs assert 10 in vs assert 15 in vs assert 20 in vs assert 20.0001 not in vs assert 21 not in vs assert 29 not in vs assert 29.9999 not in vs assert 30 in vs assert 35 in vs assert 40 in vs assert 40.0001 not in vs assert 41 not in vs
def test_level_constraints(): state = State() # Should be allowed assert_level_constraint(state, "level", 1) assert state["_level_constrained_values"] == {"level": 1} # Should not be allowed with pytest.raises(ValueNotAllowedInLevel) as exc_info: assert_level_constraint(state, "base_video_format", 0) assert exc_info.value.level_constrained_values == {"level": 1} assert exc_info.value.key == "base_video_format" assert exc_info.value.value == 0 assert exc_info.value.allowed_values == ValueSet(1, 2, 3, 4, 5, 6)
def test_unsatisfiable_level_constraints(self): base_video_parameters = set_source_defaults(BaseVideoFormats.hd720p_50) video_parameters = set_source_defaults(BaseVideoFormats.hd1080p_50) level_constraints_dict = defaultdict( AnyValue, custom_dimensions_flag=ValueSet(False), ) assert ( list( iter_source_parameter_options( base_video_parameters, video_parameters, level_constraints_dict ) ) == [] )
def test_individual_values(self): vs = ValueSet() vs.add_value(123) assert 123 in vs assert 321 not in vs vs.add_value("foo") assert 123 in vs assert "foo" in vs assert 321 not in vs assert "bar" not in vs
def test_level_overrides_obeyed( level_constraints, level_overrides, exp_asym_transform_index_flag_case, exp_asym_transform_flag_case, ): assert level_constraints[0]["level"] == ValueSet(0) level_constraints[0].update(level_overrides) codec_features = CodecFeatures( MINIMAL_CODEC_FEATURES, fragment_slice_count=1, # Force v3 wavelet_index=WaveletFilters.haar_no_shift, wavelet_index_ho=WaveletFilters.haar_no_shift, dwt_depth=1, dwt_depth_ho=0, ) test_cases = list(extended_transform_parameters(codec_features)) exp_cases = 0 if exp_asym_transform_index_flag_case: exp_cases += 1 if exp_asym_transform_flag_case: exp_cases += 1 assert len(test_cases) == exp_cases # Check that the extra flags are set (when expected) but not when the level # prohibits it for test_case in test_cases: etps = find_extended_transform_parameters(test_case.value) if test_case.subcase_name == "asym_transform_index_flag": assert exp_asym_transform_index_flag_case assert etps for etp in etps: assert etp["asym_transform_index_flag"] assert etp["wavelet_index_ho"] == WaveletFilters.haar_no_shift elif test_case.subcase_name == "asym_transform_flag": assert exp_asym_transform_flag_case assert etps for etp in etps: assert etp["asym_transform_flag"] assert etp["dwt_depth_ho"] == 0 else: assert False
def test_combination(self): vs = ValueSet() vs.add_value(1) vs.add_range(10, 20) assert 0 not in vs assert 1 in vs assert 2 not in vs assert 9 not in vs assert 10 in vs assert 15 in vs assert 20 in vs assert 21 not in vs
def test_filtered(self): assert (allowed_values_for( [ { "foo": ValueSet(1), "bar": ValueSet(123) }, { "foo": ValueSet(2), "bar": ValueSet(321) }, { "foo": ValueSet(3), "bar": ValueSet(123) }, ], "foo", {"bar": 123}, ) == ValueSet(1, 3))
def test_quantisation_matrix_value_not_allowed_in_level(): e = exceptions.QuantisationMatrixValueNotAllowedInLevel( value=999, allowed_values=ValueSet((0, 127)), level_constrained_values=OrderedDict( [("level", 1), ("custom_quant_matrix", True), ("foo", "bar")] ), ) assert wrap_paragraphs(e.explain()) == wrap_paragraphs( """ Custom quantisation matrix contains a value, 999, outside the range {0-127} allowed by the current level, 1 (SMPTE ST 2042-2:2017). The restriction above may be more constrained than expected due to one of the following previously encountered options: * level = 1 * custom_quant_matrix = True * foo = 'bar' """ )
def test_value_not_allowed_in_level(): e = exceptions.ValueNotAllowedInLevel( level_constrained_values=OrderedDict( [("level", 1), ("foo", "bar"), ("qux", "quo")] ), key="base_video_format", value=999, allowed_values=ValueSet((1, 6)), ) assert wrap_paragraphs(e.explain()) == wrap_paragraphs( """ The base_video_format value 999 is not allowed by level 1, expected {1-6} (SMPTE ST 2042-2:2017). The restriction above may be more constrained than expected due to one of the following previously encountered options: * level = 1 * foo = 'bar' * qux = 'quo' """ )
@pytest.fixture def level_constraints(): # Revert modifications made to LEVEL_CONSTRAINTS in this test old = deepcopy(LEVEL_CONSTRAINTS) try: yield LEVEL_CONSTRAINTS finally: del LEVEL_CONSTRAINTS[:] LEVEL_CONSTRAINTS.extend(old) @pytest.mark.parametrize( "level_overrides,exp_asym_transform_index_flag_case,exp_asym_transform_flag_case", [ ({ "asym_transform_index_flag": ValueSet(False) }, False, True), ({ "asym_transform_flag": ValueSet(False) }, True, False), ], ) def test_level_overrides_obeyed( level_constraints, level_overrides, exp_asym_transform_index_flag_case, exp_asym_transform_flag_case, ): assert level_constraints[0]["level"] == ValueSet(0) level_constraints[0].update(level_overrides)
def test_empty(self): empty = ValueSet() assert None not in empty assert 123 not in empty assert "foo" not in empty
def test_constructor_works(self): vs = ValueSet(5, 10, 15, 20, 25, (10, 15), (15, 21)) assert vs._values == set([5, 25]) assert vs._ranges == set([(10, 21)])
def test_add_range_overlap_existing_ranges(self, ranges): vs = ValueSet() for r in ranges: vs.add_range(*r) assert vs._ranges == set([(10, 30)])