Code Example: Source and Sink

In this example shows how to use the otacast.Source() and otacast.Sink(). The Source and Sink enables support for memory mapped IO.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
#!/usr/bin/env python
# encoding: utf-8

"""An example showing how to OTAcast Source and Sink."""

# License for Commercial Usage
# Distributed under the "OTACAST EVALUATION LICENSE 1.2"
# Licensees holding a valid commercial license may use this project in
# accordance with the standard license agreement terms provided with the
# Software (see accompanying file LICENSE.rst or
# https://www.steinwurf.com/license), unless otherwise different terms and
# conditions are agreed in writing between Licensee and Steinwurf ApS in which
# case the license will be regulated by that separate written agreement.
# License for Non-Commercial Usage
# Distributed under the "OTACAST RESEARCH LICENSE 1.2"
# Licensees holding a valid research license may use this project in accordance
# with the license agreement terms provided with the Software
# See accompanying file LICENSE.rst or https://www.steinwurf.com/license

import otacast
import filecmp
import tempfile
import os


def generate_file(bytes):
    print(f"Generating file of {bytes / 1000 / 1000.0} Mb ", end="", flush=True)
    fd, name = tempfile.mkstemp()
    f = os.fdopen(fd, "wb")
    max_chunk = bytes // 5
    while bytes != 0:
        chunk = min(max_chunk, bytes)
        f.write(os.urandom(chunk))
        bytes -= chunk
        print(".", end="", flush=True)

    f.close()
    print(" Done!")
    return name


def main():

    # Generate a random file
    file_path = generate_file(1000 * 1000 * 40)  # 40MB

    # Instantiate file source
    source = otacast.Source()

    # The symbol bytes determine the size of the produced symbols.
    # In most cases it makes sense to make this value fit the MTU size of the
    # network.
    symbol_bytes = 1350

    # The width manages a tradeoff between code
    # effectiveness and computational complexity.
    # A higher width causes higher code effectiveness, but also a higher memory
    # footprint and computational complexity.
    width = otacast.CodecWidth._32

    # You can either configure the source giving the specific width and
    # symbol_bytes as seperate arguments, or gather them in a set.
    source_config = {width, symbol_bytes}
    source.configure(*source_config)
    source.open(file_path)

    output_directory = tempfile.mkdtemp(suffix="otacast.out")

    # Instantiate file sink
    sink = otacast.Sink()
    sink.open(output_directory)

    # We create a meta-packet containing the meta information the source shares
    # with the sink
    meta_packet = bytearray(otacast.Source.meta_packet_size(source))

    # Source writes the meta packet to the meta packet buffer
    otacast.Source.meta_packet_serialize(source, meta_packet)

    # The sink unpacks the data into a dictionary
    sink_config = otacast.Sink.meta_packet_deserialize(meta_packet)
    if sink_config is None:
        raise Exception("Could not deserialize meta packet")

    sink.configure(**sink_config)

    # This bytearray will contain the generated symbols.
    symbol = bytearray(source.packet_size)

    while not sink.is_complete():

        # Generate an encoded packet
        source.write_packet(symbol)
        # Decode the encoded packet
        sink.read_packet(symbol)

    if filecmp.cmp(file_path, sink.output_file_path, shallow=False):
        print("Decoding finished successfully!")
    else:
        print("Something went wrong!")

    # Close source and sink
    source.close()
    sink.close()


if __name__ == "__main__":
    main()
Versions
4.0.0
3.2.0
3.1.0
3.0.0
2.0.0
1.0.1
Development
latest