Warning: This is an old version. The latest stable version is Version 4.0.0.
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()
|