Beispiel #1
0
 def test_allow_subset(self):
     assert (is_allowed_combination(
         [{
             "foo": ValueSet(123),
             "bar": ValueSet()
         }],
         {"foo": 123},
     ) is True)
Beispiel #2
0
 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)])
Beispiel #3
0
 def test_unfiltered(self):
     assert (allowed_values_for(
         [{
             "foo": ValueSet(1)
         }, {
             "foo": ValueSet(2)
         }, {
             "foo": ValueSet(3)
         }],
         "foo",
     ) == ValueSet(1, 2, 3))
Beispiel #4
0
 def test_allow_matching(self):
     assert (is_allowed_combination(
         [{
             "foo": ValueSet(123),
             "bar": ValueSet(321)
         }],
         {
             "foo": 123,
             "bar": 321
         },
     ) is True)
Beispiel #5
0
 def test_disallow_no_completely_matching_set(self):
     assert (is_allowed_combination(
         [{
             "foo": ValueSet(123)
         }, {
             "bar": ValueSet(321)
         }],
         {
             "foo": 123,
             "bar": 321
         },
     ) is False)
Beispiel #6
0
    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
Beispiel #7
0
    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)
Beispiel #9
0
 def test_disallow_mismatching(self):
     assert (is_allowed_combination(
         [{
             "foo": ValueSet(321)
         }],
         {"foo": 123},
     ) is False)
Beispiel #10
0
    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))
Beispiel #11
0
    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)
Beispiel #12
0
 def test_disallow_superset(self):
     assert (is_allowed_combination(
         [{
             "foo": ValueSet(123)
         }],
         {
             "foo": 123,
             "bar": 321
         },
     ) is False)
Beispiel #13
0
 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])
Beispiel #14
0
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)
Beispiel #15
0
    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)])
Beispiel #16
0
 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)
Beispiel #17
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))"
Beispiel #18
0
    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
Beispiel #19
0
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
                )
            )
            == []
        )
Beispiel #21
0
    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
Beispiel #22
0
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
Beispiel #23
0
    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
Beispiel #24
0
 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))
Beispiel #25
0
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'
    """
    )
Beispiel #26
0
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'
    """
    )
Beispiel #27
0
@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)
Beispiel #28
0
 def test_empty(self):
     empty = ValueSet()
     assert None not in empty
     assert 123 not in empty
     assert "foo" not in empty
Beispiel #29
0
 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)])
Beispiel #30
0
 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)])