Ejemplo n.º 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)
Ejemplo n.º 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)
Ejemplo n.º 3
0
def scan_format(state, video_parameters):
    """(11.4.5)"""
    custom_scan_format_flag = read_bool(state)
    # (C.3) Check level allows custom scan formats
    ## Begin not in spec
    assert_level_constraint(state, "custom_scan_format_flag", custom_scan_format_flag)
    ## End not in spec

    if custom_scan_format_flag:
        video_parameters["source_sampling"] = read_uint(state)

        # (11.4.5) Mode be a known value
        ## Begin not in spec
        assert_in_enum(
            video_parameters["source_sampling"],
            SourceSamplingModes,
            BadSourceSamplingMode,
        )
        ## End not in spec

        # (C.3) Check level allows this value
        ## Begin not in spec
        assert_level_constraint(
            state,
            "source_sampling",
            video_parameters["source_sampling"],
        )
Ejemplo n.º 4
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"])
Ejemplo n.º 5
0
def color_diff_sampling_format(state, video_parameters):
    """(11.4.4)"""
    custom_color_diff_format_flag = read_bool(state)
    # (C.3) Check level allows custom color difference sampling
    ## Begin not in spec
    assert_level_constraint(
        state, "custom_color_diff_format_flag", custom_color_diff_format_flag
    )
    ## End not in spec

    if custom_color_diff_format_flag:
        video_parameters["color_diff_format_index"] = read_uint(state)

        # (11.4.4) Index shall be a known value
        ## Begin not in spec
        assert_in_enum(
            video_parameters["color_diff_format_index"],
            ColorDifferenceSamplingFormats,
            BadColorDifferenceSamplingFormat,
        )
        ## End not in spec

        # (C.3) Check level allows this value
        ## Begin not in spec
        assert_level_constraint(
            state,
            "color_diff_format_index",
            video_parameters["color_diff_format_index"],
        )
Ejemplo n.º 6
0
def transform_parameters(state):
    """(12.4.1)"""
    state["wavelet_index"] = read_uint(state)

    # (12.4.1) Check wavelet type is supported
    ## Begin not in spec
    assert_in_enum(state["wavelet_index"], WaveletFilters, BadWaveletIndex)
    ## End not in spec

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

    state["dwt_depth"] = read_uint(state)

    # (C.3) Check level allows this wavelet depth
    assert_level_constraint(state, "dwt_depth",
                            state["dwt_depth"])  ## Not in spec

    state["wavelet_index_ho"] = state["wavelet_index"]
    state["dwt_depth_ho"] = 0

    if state["major_version"] >= 3:
        extended_transform_parameters(state)

    slice_parameters(state)

    quant_matrix(state)
Ejemplo n.º 7
0
def pixel_aspect_ratio(state, video_parameters):
    """(11.4.7)"""
    custom_pixel_aspect_ratio_flag = read_bool(state)
    # (C.3) Check level allows custom pixel aspect ratio
    ## Begin not in spec
    assert_level_constraint(
        state, "custom_pixel_aspect_ratio_flag", custom_pixel_aspect_ratio_flag
    )
    ## End not in spec

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

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

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

            # Errata: spec fails to require ratio to be non-zero on either side
            #
            # (11.4.7) ratio must not contain zeros
            ## Begin not in spec
            if (
                video_parameters["pixel_aspect_ratio_numer"] == 0
                or video_parameters["pixel_aspect_ratio_denom"] == 0
            ):
                raise PixelAspectRatioContainsZeros(
                    video_parameters["pixel_aspect_ratio_numer"],
                    video_parameters["pixel_aspect_ratio_denom"],
                )
            ## End not in spec
        else:
            # (11.4.7) Pixel aspect ratio preset must be a known value
            ## Begin not in spec
            assert_in_enum(index, PresetPixelAspectRatios, BadPresetPixelAspectRatio)
            ## End not in spec

            preset_pixel_aspect_ratio(video_parameters, index)
Ejemplo n.º 8
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)
Ejemplo n.º 9
0
def test_assert_in_enum():
    class CustomException(Exception):
        pass

    assert_in_enum(0x10, ParseCodes, CustomException)
    assert_in_enum(ParseCodes.end_of_sequence, ParseCodes, CustomException)

    with pytest.raises(CustomException) as exc_info:
        assert_in_enum(-1, ParseCodes, CustomException)
    assert exc_info.type is CustomException
    assert exc_info.value.args == (-1,)
Ejemplo n.º 10
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)
Ejemplo n.º 11
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)
Ejemplo n.º 12
0
def sequence_header(state):
    """(11.1)"""
    # Record this sequence_header as it appears in the bitstream
    ## Begin not in spec
    this_sequence_header_offset = tell(state)[0]
    record_bitstream_start(state)
    ## End not in spec

    parse_parameters(state)

    base_video_format = read_uint(state)

    # (11.4.1) Check base video format is supported
    ## Begin not in spec
    assert_in_enum(base_video_format, BaseVideoFormats, BadBaseVideoFormat)
    ## End not in spec

    # (C.3) Check level allows this base format
    ## Begin not in spec
    assert_level_constraint(state, "base_video_format", base_video_format)
    ## End not in spec

    video_parameters = source_parameters(state, base_video_format)

    state["picture_coding_mode"] = read_uint(state)

    # (11.5) Ensure picture coding mode is valid
    ## Begin not in spec
    assert_in_enum(
        state["picture_coding_mode"], PictureCodingModes, BadPictureCodingMode
    )
    ## End not in spec

    # (C.3) Check level allows this picture coding mode
    ## Begin not in spec
    assert_level_constraint(state, "picture_coding_mode", state["picture_coding_mode"])
    ## End not in spec

    set_coding_parameters(state, video_parameters)

    # Errata: The spec only says the frame_height must be an integer multiple
    # of the color_diff_height but, in addition, the luma_height should be a
    # multiple and the color_diff_width should be a multiple of
    # luma_width/frame_width
    #
    # (11.6.2) Check frame_height is an integer multiple of color_diff_height
    ## Begin not in spec
    if (
        # Prevent divide-by-zero in tests below
        state["luma_height"] == 0
        or state["luma_width"] == 0
        or state["color_diff_height"] == 0
        or state["color_diff_width"] == 0
        or
        # Actually check multiples
        video_parameters["frame_height"] % state["luma_height"] != 0
        or video_parameters["frame_width"] % state["luma_width"] != 0
        or video_parameters["frame_height"] % state["color_diff_height"] != 0
        or video_parameters["frame_width"] % state["color_diff_width"] != 0
    ):
        raise PictureDimensionsNotMultipleOfFrameDimensions(
            state["luma_width"],
            state["luma_height"],
            state["color_diff_width"],
            state["color_diff_height"],
            video_parameters["frame_width"],
            video_parameters["frame_height"],
        )
    ## End not in spec

    # (11.1) Check that the this sequence_header is byte-for-byte identical
    # with the previous sequence_header in the sequence
    ## Begin not in spec
    this_sequence_header_bytes = record_bitstream_finish(state)
    if "_last_sequence_header_bytes" in state:
        if this_sequence_header_bytes != state["_last_sequence_header_bytes"]:
            raise SequenceHeaderChangedMidSequence(
                state["_last_sequence_header_offset"],
                state["_last_sequence_header_bytes"],
                this_sequence_header_offset,
                this_sequence_header_bytes,
            )
    state["_last_sequence_header_bytes"] = this_sequence_header_bytes
    state["_last_sequence_header_offset"] = this_sequence_header_offset
    ## End not in spec

    return video_parameters
Ejemplo n.º 13
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