예제 #1
0
def color_spec(state, video_parameters):
    """(11.4.10.1)"""
    custom_color_spec_flag = read_bool(state)
    # (C.3) Check level allows custom color specs
    ## Begin not in spec
    assert_level_constraint(state, "custom_color_spec_flag", custom_color_spec_flag)
    ## End not in spec

    if custom_color_spec_flag:
        index = read_uint(state)

        # (11.4.10.1) Index should be a supported value
        assert_in_enum(index, PresetColorSpecs, BadPresetColorSpec)  ## Not in spec

        # (C.3) Check level allows the specified preset
        assert_level_constraint(state, "color_spec_index", index)  ## Not in spec

        preset_color_spec(video_parameters, index)

        if index == 0:
            color_primaries(state, video_parameters)
            color_matrix(state, video_parameters)
            transfer_function(state, video_parameters)
        ## Begin not in spec
        else:
            # (11.2.2) Color spec must be supported by current version
            minimum_required_version = preset_color_spec_version_implication(index)
            if state["major_version"] < minimum_required_version:
                raise PresetColorSpecNotSupportedByVersion(
                    index, state["major_version"]
                )
            log_version_lower_bound(state, minimum_required_version)
예제 #2
0
def transfer_function(state, video_parameters):
    """(11.4.10.4)"""
    custom_transfer_function_flag = read_bool(state)
    # (C.3) Check level allows custom transfer functions
    ## Begin not in spec
    assert_level_constraint(
        state, "custom_transfer_function_flag", custom_transfer_function_flag
    )
    ## End not in spec

    if custom_transfer_function_flag:
        index = read_uint(state)

        # (11.4.10.3) Index should be a supported value
        ## Begin not in spec
        assert_in_enum(index, PresetTransferFunctions, BadPresetTransferFunction)
        ## End not in spec

        # (C.3) Check level allows the specified preset
        ## Begin not in spec
        assert_level_constraint(state, "transfer_function_index", index)
        ## End not in spec

        # (11.2.2) Preset must be supported by current version
        ## Begin not in spec
        minimum_required_version = preset_transfer_function_version_implication(index)
        if state["major_version"] < minimum_required_version:
            raise PresetTransferFunctionNotSupportedByVersion(
                index, state["major_version"]
            )
        log_version_lower_bound(state, minimum_required_version)
        ## End not in spec

        preset_transfer_function(video_parameters, index)
예제 #3
0
def parse_parameters(state):
    """(11.2.1)"""
    state["major_version"] = read_uint(state)

    # (11.2.2) Check the major_version  is at least 1. (It may need to be
    # higher depending on the features used on the sequence, but this will be
    # checked as the stream is processed. Later, at the end of the stream we'll
    # also check the major_version was not too high for the set of features
    # actually used.)
    ## Begin not in spec
    if state["major_version"] < MINIMUM_MAJOR_VERSION:
        raise MajorVersionTooLow(state["major_version"])
    ## End not in spec

    state["minor_version"] = read_uint(state)

    # (11.2.2) Check the minor_version is 0.
    ## Begin not in spec
    if state["minor_version"] != 0:
        raise MinorVersionNotZero(state["minor_version"])
    ## End not in spec

    state["profile"] = read_uint(state)

    # (C.2) Profile must be a supported value
    assert_in_enum(state["profile"], Profiles, BadProfile)  ## Not in spec

    # (11.2.2) Profile must be supported by current version
    ## Begin not in spec
    minimum_required_version = profile_version_implication(state["profile"])
    if state["major_version"] < minimum_required_version:
        raise ProfileNotSupportedByVersion(state["profile"], state["major_version"])
    log_version_lower_bound(state, minimum_required_version)
    ## End not in spec

    state["level"] = read_uint(state)

    # (C.3) Level must be a supported value
    assert_in_enum(state["level"], Levels, BadLevel)  ## Not in spec

    # (C.3) Levels may constrain the order and choice of data units in a
    # sequence. See the various level standards documents (e.g. ST 2042-2) for
    # details.
    ## Begin not in spec
    if "_level_sequence_matcher" not in state:
        state["_level_sequence_matcher"] = Matcher(
            LEVEL_SEQUENCE_RESTRICTIONS[state["level"]].sequence_restriction_regex
        )
        # If we're at this point we're currently reading the first sequence
        # header (in the first data unit) of a sequence. Advance the state
        # machine accordingly.
        assert state["_level_sequence_matcher"].match_symbol("sequence_header")
    ## End not in spec

    # (C.3) Levels may constrain the allowed profiles and versions
    ## Begin not in spec
    assert_level_constraint(state, "level", state["level"])
    assert_level_constraint(state, "profile", state["profile"])
    assert_level_constraint(state, "major_version", state["major_version"])
    assert_level_constraint(state, "minor_version", state["minor_version"])
예제 #4
0
def extended_transform_parameters(state):
    """(12.4.4.1)"""
    asym_transform_index_flag = read_bool(state)
    # (C.3) Check level allows an asymmetric transform types
    ## Begin not in spec
    assert_level_constraint(state, "asym_transform_index_flag",
                            asym_transform_index_flag)
    ## End not in spec

    if asym_transform_index_flag:
        state["wavelet_index_ho"] = read_uint(state)

        # (12.4.4.2) Check wavelet type is supported
        ## Begin not in spec
        assert_in_enum(state["wavelet_index_ho"], WaveletFilters,
                       BadHOWaveletIndex)
        ## End not in spec

        # (C.3) Check level allows this wavelet type
        ## Begin not in spec
        assert_level_constraint(state, "wavelet_index_ho",
                                state["wavelet_index_ho"])
        ## End not in spec

    asym_transform_flag = read_bool(state)
    # (C.3) Check level allows an asymmetric transform depths
    ## Begin not in spec
    assert_level_constraint(state, "asym_transform_flag", asym_transform_flag)
    ## End not in spec

    if asym_transform_flag:
        state["dwt_depth_ho"] = read_uint(state)

        # (C.3) Check level allows this wavelet depth
        ## Begin not in spec
        assert_level_constraint(state, "dwt_depth_ho", state["dwt_depth_ho"])
        ## End not in spec

    # (11.2.2) Log increased minimum version requirements if an asymmetric
    # transform was used.
    ## Begin not in spec
    minimum_required_version = wavelet_transform_version_implication(
        state["wavelet_index"],
        state["wavelet_index_ho"],
        state["dwt_depth_ho"],
    )
    log_version_lower_bound(state, minimum_required_version)
예제 #5
0
def signal_range(state, video_parameters):
    """(11.4.9)"""
    custom_signal_range_flag = read_bool(state)
    # (C.3) Check level allows custom signal range
    ## Begin not in spec
    assert_level_constraint(state, "custom_signal_range_flag", custom_signal_range_flag)
    ## End not in spec

    if custom_signal_range_flag:
        index = read_uint(state)
        # (C.3) Check level allows the specified preset
        ## Begin not in spec
        assert_level_constraint(state, "custom_signal_range_index", index)
        ## End not in spec

        if index == 0:
            video_parameters["luma_offset"] = read_uint(state)
            # (C.3) Check level allows this offset
            ## Begin not in spec
            assert_level_constraint(
                state, "luma_offset", video_parameters["luma_offset"]
            )
            ## End not in spec

            video_parameters["luma_excursion"] = read_uint(state)
            # (C.3) Check level allows this excursion
            ## Begin not in spec
            assert_level_constraint(
                state, "luma_excursion", video_parameters["luma_excursion"]
            )
            ## End not in spec

            # (11.4.9) Check luma_excursion is valid
            #
            # Errata: Spec fails to constrain excursions.  Excursions *must* be
            # >= 1 or the pseudocode behaviour will be undefined.
            ## Begin not in spec
            if video_parameters["luma_excursion"] < 1:
                raise BadCustomSignalExcursion(
                    "luma", video_parameters["luma_excursion"]
                )
            ## End not in spec

            video_parameters["color_diff_offset"] = read_uint(state)
            # (C.3) Check level allows this offset
            ## Begin not in spec
            assert_level_constraint(
                state, "color_diff_offset", video_parameters["color_diff_offset"]
            )
            ## End not in spec

            video_parameters["color_diff_excursion"] = read_uint(state)
            # (C.3) Check level allows this excursion
            ## Begin not in spec
            assert_level_constraint(
                state, "color_diff_excursion", video_parameters["color_diff_excursion"]
            )
            ## End not in spec

            # (11.4.9) Check color_diff_excursion is valid
            #
            # Errata: Spec fails to constrain excursions.  Excursions *must* be
            # >= 1 or the pseudocode behaviour will be undefined.
            ## Begin not in spec
            if video_parameters["color_diff_excursion"] < 1:
                raise BadCustomSignalExcursion(
                    "color_diff", video_parameters["color_diff_excursion"]
                )
            ## End not in spec
        else:
            # (11.4.9) Signal range preset must be a known value
            ## Begin not in spec
            assert_in_enum(index, PresetSignalRanges, BadPresetSignalRange)
            ## End not in spec

            # (11.2.2) Signal range preset must be supported by current version
            ## Begin not in spec
            minimum_required_version = preset_signal_range_version_implication(index)
            if state["major_version"] < minimum_required_version:
                raise PresetSignalRangeNotSupportedByVersion(
                    index, state["major_version"]
                )
            log_version_lower_bound(state, minimum_required_version)
            ## End not in spec

            preset_signal_range(video_parameters, index)
예제 #6
0
def frame_rate(state, video_parameters):
    """(11.4.6)"""
    custom_frame_rate_flag = read_bool(state)
    # (C.3) Check level allows custom frame rates
    ## Begin not in spec
    assert_level_constraint(state, "custom_frame_rate_flag", custom_frame_rate_flag)
    ## End not in spec

    if custom_frame_rate_flag:
        index = read_uint(state)

        # (C.3) Check level allows the specified preset
        assert_level_constraint(state, "frame_rate_index", index)  ## Not in spec

        if index == 0:
            video_parameters["frame_rate_numer"] = read_uint(state)
            # (C.3) Check level allows the specified numerator
            ## Begin not in spec
            assert_level_constraint(
                state,
                "frame_rate_numer",
                video_parameters["frame_rate_numer"],
            )
            ## End not in spec

            video_parameters["frame_rate_denom"] = read_uint(state)
            # (C.3) Check level allows the specified denominator
            ## Begin not in spec
            assert_level_constraint(
                state,
                "frame_rate_denom",
                video_parameters["frame_rate_denom"],
            )
            ## End not in spec

            # Errata: spec doesn't prevent divide-by-zero in custom frame rate
            # fractions.
            #
            # (11.4.6) frame_rate_denom must not be zero (i.e. a divide by zero)
            ## Begin not in spec
            if video_parameters["frame_rate_denom"] == 0:
                raise FrameRateHasZeroDenominator(video_parameters["frame_rate_numer"])
            ## End not in spec

            # Errata: spec doesn't prevent 0 fps
            #
            # (11.4.6) frame_rate_numer must not be zero (i.e. 0 fps)
            ## Begin not in spec
            if video_parameters["frame_rate_numer"] == 0:
                raise FrameRateHasZeroNumerator(video_parameters["frame_rate_denom"])
            ## End not in spec

        else:
            # (11.4.6) Frame rate preset must be a known value
            ## Begin not in spec
            assert_in_enum(index, PresetFrameRates, BadPresetFrameRateIndex)
            ## End not in spec

            # (11.2.2) Frame rate preset must be supported by current version
            ## Begin not in spec
            minimum_required_version = preset_frame_rate_version_implication(index)
            if state["major_version"] < minimum_required_version:
                raise PresetFrameRateNotSupportedByVersion(
                    index, state["major_version"]
                )
            log_version_lower_bound(state, minimum_required_version)
            ## End not in spec

            preset_frame_rate(video_parameters, index)
예제 #7
0
def parse_info(state):
    """(10.5.1)"""
    byte_align(state)

    # (10.5.1) Check that the previous parse_info's next_parse_offset was
    # calculated correctly
    ## Begin not in spec
    this_parse_info_offset = tell(state)[0]
    last_parse_info_offset = state.get("_last_parse_info_offset", None)

    if state.get("next_parse_offset"):
        true_parse_offset = this_parse_info_offset - last_parse_info_offset
        last_next_parse_offset = state["next_parse_offset"]
        if last_next_parse_offset != 0 and last_next_parse_offset != true_parse_offset:
            raise InconsistentNextParseOffset(
                last_parse_info_offset,
                last_next_parse_offset,
                true_parse_offset,
            )
    ## End not in spec

    # (10.5.1) Capture and check the parse_info prefix
    ### read_uint_lit(state, 4)
    ## Begin not in spec
    prefix = read_uint_lit(state, 4)
    if prefix != PARSE_INFO_PREFIX:
        raise BadParseInfoPrefix(prefix)
    ## End not in spec

    # (10.5.1) Check the parse_code is a supported value
    state["parse_code"] = read_uint_lit(state, 1)
    assert_in_enum(state["parse_code"], ParseCodes, BadParseCode)  ## Not in spec

    # (10.4.1) Check that the sequence starts with a sequence_header and ends
    # with and end_of_sequence.
    ## Begin not in spec
    assert_parse_code_in_sequence(
        state["parse_code"],
        state["_generic_sequence_matcher"],
        GenericInvalidSequence,
    )
    ## End not in spec

    # (C.3) Check that the sequence follows the pattern dictated by the current
    # level (NB: this matcher is populated later by parse_parameters (11.2.1)
    # when the level is read for the first time.
    ## Begin not in spec
    if "_level_sequence_matcher" in state:
        assert_parse_code_in_sequence(
            state["parse_code"],
            state["_level_sequence_matcher"],
            LevelInvalidSequence,
            state["level"],
        )
    ## End not in spec

    # (C.2.2) Ensure that only the profile-permitted parse codes are used
    ## Begin not in spec
    if "profile" in state:
        profile_params = PROFILES[state["profile"]]
        if state["parse_code"] not in profile_params.allowed_parse_codes:
            raise ParseCodeNotAllowedInProfile(state["parse_code"], state["profile"])
    ## End not in spec

    # (11.2.2) Check that the parse code used is supported by the current
    # major_version.
    ## Begin not in spec
    minimum_required_version = parse_code_version_implication(state["parse_code"])
    # NB: If this is the sequence header at the start of a sequence we may not
    # know the major_version yet. In that case, we can safely skip this test as
    # the sequence header is supported by all versions.
    major_version = state.get("major_version", MINIMUM_MAJOR_VERSION)
    if major_version < minimum_required_version:
        raise ParseCodeNotSupportedByVersion(state["parse_code"], major_version)
    log_version_lower_bound(state, minimum_required_version)
    ## End not in spec

    # (10.5.1) Check that the next_parse_offset holds a plausible value
    state["next_parse_offset"] = read_uint_lit(state, 4)
    ## Begin not in spec
    if state["parse_code"] == ParseCodes.end_of_sequence:
        # (10.5.1) End of stream must have '0' as next offset
        if state["next_parse_offset"] != 0:
            raise NonZeroNextParseOffsetAtEndOfSequence(state["next_parse_offset"])
    elif not (is_picture(state) or is_fragment(state)):
        # (10.5.1) Non-picture containing blocks *must* have a non-zero offset
        if state["next_parse_offset"] == 0:
            raise MissingNextParseOffset(state["parse_code"])

    # (10.5.1) Offsets pointing inside this parse_info bock are always invalid
    if 1 <= state["next_parse_offset"] < PARSE_INFO_HEADER_BYTES:
        raise InvalidNextParseOffset(state["next_parse_offset"])
    ## End not in spec

    # (10.5.1) Check that the previous parse offset was calculated correctly
    state["previous_parse_offset"] = read_uint_lit(state, 4)
    ## Begin not in spec
    if last_parse_info_offset is None:
        # (10.5.1) This is the first parse_info encountered, must be zero
        if state["previous_parse_offset"] != 0:
            raise NonZeroPreviousParseOffsetAtStartOfSequence(
                state["previous_parse_offset"]
            )
    else:
        # (10.5.1) Previous offset must be present and calculated correctly otherwise
        true_previous_parse_offset = this_parse_info_offset - last_parse_info_offset
        if state["previous_parse_offset"] != true_previous_parse_offset:
            raise InconsistentPreviousParseOffset(
                last_parse_info_offset,
                state["previous_parse_offset"],
                true_parse_offset,
            )
    ## End not in spec

    state["_last_parse_info_offset"] = this_parse_info_offset  ## Not in spec