def encode_and_decode(stream):
    f = BytesIO()
    autofill_and_serialise_stream(f, stream)
    f.seek(0)

    pictures = []
    state = State(
        _output_picture_callback=lambda p, vp, pcm: pictures.append(p))
    init_io(state, f)
    parse_stream(state)

    return pictures
    def serialise_and_decode_pictures(self, stream):
        f = BytesIO()
        autofill_and_serialise_stream(f, stream)

        pictures = []
        state = State(
            _output_picture_callback=lambda pic, vp, pcm: pictures.append(pic))
        f.seek(0)
        decoder.init_io(state, f)
        decoder.parse_stream(state)

        return pictures
Пример #3
0
def check_codec_features_valid(codec_feature_sets):
    """
    Verify that the codec features requested don't themselves violate the spec
    (e.g. violate a level constraint). This is done by generating then
    validating a bitstream containing a single mid-gray frame.

    Prints an error to stderr and calls :py:func:`sys.exit` if a problem is
    encountered.
    """
    logging.info("Checking codec feature sets are valid...")
    for name, codec_features in codec_feature_sets.items():
        logging.info("Checking %r...", name)
        f = BytesIO()

        # Sanity-check the color format (since this won't raise a validation
        # error but will result in a useless gamut being available).
        sanity = sanity_check_video_parameters(codec_features["video_parameters"])
        if not sanity:
            logging.warning(
                "Color specification for codec configuration %r be malformed: %s",
                name,
                sanity.explain(),
            )

        # Generate a minimal bitstream
        try:
            autofill_and_serialise_stream(f, static_gray(codec_features))
        except UnsatisfiableCodecFeaturesError as e:
            sys.stderr.write(
                "Error: Codec configuration {!r} is invalid:\n".format(name)
            )
            terminal_width = get_terminal_size()[0]
            sys.stderr.write(wrap_paragraphs(e.explain(), terminal_width))
            sys.stderr.write("\n")
            sys.exit(4)
        f.seek(0)

        # Validate it meets the spec
        state = State()
        init_io(state, f)
        try:
            parse_stream(state)
        except ConformanceError as e:
            sys.stderr.write(
                "Error: Codec configuration {!r} is invalid:\n".format(name)
            )
            terminal_width = get_terminal_size()[0]
            sys.stderr.write(wrap_paragraphs(e.explain(), terminal_width))
            sys.stderr.write("\n")
            sys.exit(4)
Пример #4
0
def test_is_end_of_stream():
    f = BytesIO(b"\xFF")
    state = State()
    decoder.init_io(state, f)

    # At start of stream
    assert decoder.is_end_of_stream(state) is False

    # Part-way through byte
    decoder.read_nbits(state, 4)
    assert decoder.is_end_of_stream(state) is False

    # At end of stream
    decoder.read_nbits(state, 4)
    assert decoder.is_end_of_stream(state) is True
Пример #5
0
    def run(self):
        try:
            self._file = open(self._filename, "rb")
            self._filesize_bytes = os.path.getsize(self._filename)
        except Exception as e:
            # Catch-all exception handler excuse: Catching only file-related
            # exceptions is challenging, particularly in a backward-compatible
            # manner. However, none of the above are known to produce
            # exceptions *except* due to file-related issues.
            self._print_error(str(e))
            return 1

        self._state = State(_output_picture_callback=self._output_picture)
        init_io(self._state, self._file)

        if self._show_status:
            self._update_status_line("Starting bitstream validation...")

        try:
            parse_stream(self._state)
            self._hide_status_line()
            if tell(self._state) == (0, 7):
                sys.stdout.flush()
                sys.stderr.write(
                    "Warning: 0 bytes read, bitstream is empty.\n")
            print(
                "No errors found in bitstream. Verify decoded pictures to confirm conformance."
            )
            return 0
        except ConformanceError as e:
            # Bitstream failed validation
            exc_type, exc_value, exc_tb = sys.exc_info()
            self._hide_status_line()
            self._print_conformance_error(e, traceback.extract_tb(exc_tb))
            self._print_error("non-conformant bitstream (see above)")
            return 2
        except Exception as e:
            # Internal error (shouldn't happen(!))
            self._hide_status_line()
            self._print_error("internal error in bitstream validator: {}: {} "
                              "(probably a bug in this program)".format(
                                  type(e).__name__,
                                  str(e),
                              ))
            return 3
Пример #6
0
def test_tell():
    f = BytesIO(b"\xAA\xFF")
    state = State()
    decoder.init_io(state, f)

    # At start of stream
    assert decoder.tell(state) == (0, 7)

    # Part-way through byte
    decoder.read_nbits(state, 4)
    assert decoder.tell(state) == (0, 3)

    # In next byte
    decoder.read_nbits(state, 8)
    assert decoder.tell(state) == (1, 3)

    # At EOF
    decoder.read_nbits(state, 4)
    assert decoder.tell(state) == (2, 7)
Пример #7
0
def serialize_and_decode(sequence):
    # Serialise
    f = BytesIO()
    autofill_and_serialise_stream(f, Stream(sequences=[sequence]))

    # Setup callback to capture decoded pictures
    decoded_pictures = []

    def output_picture_callback(picture, video_parameters,
                                picture_coding_mode):
        decoded_pictures.append(picture)

    # Feed to conformance checking decoder
    f.seek(0)
    state = State(_output_picture_callback=output_picture_callback)
    init_io(state, f)
    parse_stream(state)

    return decoded_pictures
Пример #8
0
def check_for_signal_clipping(sequence):
    """
    Given a :py:class:`vc2_conformance.bitstream.Sequence`, return True if any
    picture component signal was clipped during decoding.
    """
    # NB: Internally we just check for saturated signal levels. This way we
    # avoid the need to modify the decoder to remove the clipper and all that
    # faff...

    # Serialise
    f = BytesIO()
    # NB: Deepcopy required due to autofill_and_serialise_stream mutating the
    # stream
    stream = Stream(sequences=[deepcopy(sequence)])
    autofill_and_serialise_stream(f, stream)
    f.seek(0)

    # Decode and look for saturated pixel values
    state = State()
    may_have_clipped = [False]

    def output_picture_callback(picture, video_parameters, picture_coding_mode):
        components_and_depths = [
            ("Y", state["luma_depth"]),
            ("C1", state["color_diff_depth"]),
            ("C2", state["color_diff_depth"]),
        ]

        for component, depth in components_and_depths:
            min_value = min(min(row) for row in picture[component])
            max_value = max(max(row) for row in picture[component])
            if min_value == 0:
                may_have_clipped[0] = True
            if max_value == (1 << depth) - 1:
                may_have_clipped[0] = True

    state["_output_picture_callback"] = output_picture_callback
    init_io(state, f)
    parse_stream(state)

    return may_have_clipped[0]
Пример #9
0
 def test_non_empty_file(self):
     f = BytesIO(b"\xAA\xFF")
     state = State()
     decoder.init_io(state, f)
     assert decoder.read_nbits(state, 16) == 0xAAFF