Skip to content

Commit d844e63

Browse files
committed
Merge branch 'main' into membrane-website-integration
2 parents f31ff65 + 3acf4fc commit d844e63

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+2170
-163
lines changed

README.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# membrane_tutorials
2+
23
Repository which contains text and assets used in Membrane Framework tutorials.
34
The following tutorials are now available:
4-
+ [Get Started Tutorial](https://tutorials.membraneframework.org/tutorials/get_started/simple_pipeline.html)
5-
+ [Videoroom Tutorial](https://tutorials.membraneframework.org/tutorials/videoroom/)
5+
6+
- [Get Started Tutorial](https://tutorials.membraneframework.org/tutorials/get_started/simple_pipeline.html)
7+
- [Videoroom Tutorial](https://tutorials.membraneframework.org/tutorials/videoroom/)

basic_pipeline/01_Introduction.md

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Introduction
2+
3+
In this tutorial, we will create our very own Membrane Framework consisting of our custom which will fulfill the multimedia processing task.
4+
Despite the fact that the multimedia processing task we will be facing will be really simple, we will need to deal with some problems occurring in real-life scenarios.
5+
At the same time, we will make ourselves comfortable with some concepts of multimedia streaming as well as get in touch with the nomenclature used in this field.
6+
Prepare for an adventure!
7+
8+
## Environment preparation
9+
10+
In order to be able to proceed with the tutorial, you need to have Elixir installed: [How to install Elixir](https://elixir-lang.org/install.html).
11+
We assume, that you are at least slightly familiar with that language - if that is not true, we would like to strongly encourage you to take a look at the [official Elixir tutorial](https://elixir-lang.org/getting-started/introduction.html).
12+
Once you are ready with the Elixir, you can get the project template we have prepared for you:
13+
14+
```
15+
git clone https:/github.com/membraneframework/membrane_basic_pipeline_tutorial
16+
cd membrane_basic_pipeline_tutorial
17+
git checkout template/start
18+
mix deps.get
19+
```
20+
21+
As you can see, the template's code is put on the `template/start` branch of the repository.
22+
In the repository, there is also a `template/end` branch, where you can find the completed template.
23+
If you find yourself lost during the tutorial feel free to check the implementation proposed by us, put on this branch.
24+
25+
## Use Case
26+
27+
Imagine that there is a conversation occurring between two peers and the chat is based on a question-answer scheme.
28+
Each of the peers sends its part of the conversation (that means - the first peer sends questions and the second peers sends the answers to them). We refer to each sentence sent by the peers as a **frame**.
29+
However, due to network limitations each frame sent by the peers is fragmented since only a few chars can be sent at the same time - that means, a single frame is sent as a sequence of **packets**.
30+
In a real network there is a parameter called MTU (*Maximum Transmission Unit*) which is the maximum number of bytes which can be send in a single packet. For the Ethernet II MTU is equal to 1500 bytes. We wanted to simulate the situation,
31+
in which the data needs to be fragmented in order to be transmitted - but we decided to choose a small MTU so that this fragmentation is easy to be spotted.
32+
Each packet consists of the *header* (describing where the particular bunch of characters it transports should be put) and the *body* - aforementioned bunch of characters.
33+
Below you can see an exemplary frame sent by one peer to the other. It gets fragmented into multiple packets, which later on are sent via the network (during that process their order will probably get messed). On the second peer's side, the packets get assembled into the original frame.
34+
![Example Chat](assets/images/example_chat.drawio.png)
35+
36+
### Packet format
37+
38+
Here is how each packet looks like:
39+
40+
```
41+
[seq:<sequence_id>][frameid:<frame_id>][timestamp:<timestamp>]<text>
42+
```
43+
44+
where:
45+
46+
- sequence_id - the ordering number of the packet (relative to each of the peers). It reflects the position of a particular packet in the packets' stream.
47+
- frame_id - the identifier which consists of the number of the frame to which the body of a given packet belongs, optionally followed by a single **'e'** character (meaning that the packet is the **e**nding packet of the frame). Note that frames are numbered relatively to each peer in that conversation and that frame_id does not describe the global order of the frames in the final file.
48+
- timestamp - a number indicating a time at which a given sentence was said. Timestamp describes the order of the frames from both peers.
49+
- text - the proper body of the packet, in our case - a bunch of characters which could be sent in a single packet.
50+
51+
### Packets generator
52+
53+
We have equipped you with the tool which produces the packets in the format described previously, based on the input conversation. You can use it as a mix task, by typing:
54+
55+
```
56+
mix generate_input --packetsPerFrame <packets_per_frame> <input_file_path>
57+
```
58+
59+
where:
60+
61+
- *input_file_path* is a path to the file which contains the text of the conversation. The input file consists of multiple lines of the following format:
62+
63+
```
64+
<speaker id>: <text>
65+
```
66+
67+
- *packets_per_frame* is a number of packets on which each frame will be dismantled
68+
69+
Based on the input file content, that command will create multiple files, `<input_file_path>.<speaker id>.<input file format>` . For instance: `input.txt` with input from speakers `A` and `B` will be split into `input.A.txt` and `input.B.txt` files.
70+
The first file will contain the shuffled list of packets made from the `A` speaker's lines from the input file and the second file will contain a shuffled list of packets made out of the `B` speaker's lines of the input file. That `shuffle` is a way to simulate the imperfectness of the network - in real-life scenario, the order in which the packets are received is not always the same as the order in which they were sent. [Here](https://www.openmymind.net/How-Unreliable-Is-UDP/) you can read about this phenomenon occurring while using UDP.
71+
Below you can see the steps which are taken during the input files generation:<br>
72+
![Example Input](assets/images/example_input.drawio.png)
73+
Create a file with your own input conversation occurring between two speakers or use the `input.txt` file where we have provided you such a conversation. Generate the files containing packets, with the use of `mix generate_input` task.
74+
75+
## Task description
76+
77+
By the end of this chapter you should have generated the files containing packets (i.e. `input.A.txt` and `input.B.txt`).
78+
79+
Your task is to assemble the conversation together from those packets. In the first step you will reproduce the sentences sent by each of the peers by gathering the words sent in packets in the appropriate order. In multimedia processing, we would say that you need to reproduce the *frame* out of the *transport layer packets*. Later on you need to put those *frames* in the correct order, producing the *raw data stream*.
80+
The resulting file should be the same as the input file from which you have created two packets list with the use of the `InputFilesGenerator`.
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# System architecture
2+
3+
Once we know what should be done, let's start thinking how should our system look like!
4+
5+
First, let's get familiar with some terms. In the Membrane Framework, there is a concept of the `pipeline` which consists of multiple `elements`. Elements are linked with the use of the `pads`, which can be input pads or output pads.
6+
Depending on what type of pads the particular element is equipped with, we distinguish the following types of elements:
7+
8+
- Source - element with only output pads, the first element of each pipeline. It is responsible for fetching the data and transmitting it through the output pad.
9+
- Filter - element with both the input pads and the output pads. Its purpose is to get the data via the input pad, transform it and finally transmit the processed data via the output pad.
10+
- Sink - element with only input pads, the last element of the pipeline. It can be responsible for storing or playing the data received via the input pad.
11+
Between the pads, the `buffers` are being sent.
12+
Buffers sent between the pads should be of the same type. In the Membrane Framework nomenclature, we say, that the pads should have corresponding capabilities - `caps`.
13+
One might wonder when does the event of the buffers being sent occurs - well, it depends on the pad's mode!
14+
If the pad works in the *pull* mode, the buffer is sent when it is demanded by the succeeding element in the pipeline.
15+
Otherwise, the pad works in the *push* mode, which means that it is pushing the buffers once they are ready, independently from the fact if the following elements want (and are capable of processing) it.
16+
In our pipeline, all the pads will work in the *pull* mode, which inducts a flow control by a [backpressure](https://medium.com/@jayphelps/backpressure-explained-the-flow-of-data-through-software-2350b3e77ce7) mechanism.
17+
18+
## Scheme
19+
20+
![Pipeline scheme](assets/images/basic_pipeline.png) <br>
21+
As you can see, our pipeline will consist of two twin branches, one per each of the peers. The branches will be merged with the `Mixer` element and the result produced by this element will be put in the file with the `Sink` elements.
22+
Here you can find the description of the particular elements of the system.
23+
24+
## Elements description
25+
26+
- **Source** - that element is responsible for reading the list of packets from the file.
27+
- **Ordering Buffer** - this element is responsible for reordering the packets based on their sequence id. The most important part of this element is the buffer, within which there is a place for all the packets, identified by the packet's sequence id. Once the new packet is received, it is placed in the proper place in the buffer, depending on the sequence id. If there is a consistent part of packets "at the bottom of the buffer" (which means - packets with the subsequent sequence ids, which haven't already been sent yet), then this part is sent via the output pad. That is how we make sure that the next element will receive elements sorted by the sequence id.
28+
Below you can see how the Ordering Buffer is expected to work, once the message "How are you doing?" will be sent in the four packets, each with one word, and received in the following order: (are, you, how, doing?) <br>
29+
![Ordering Buffer](assets/images/ordering_buffer.drawio.png) <br>
30+
- **Depayloader** - responsible for assembling the packets into the frames. Since the depayloader receives the packets in the order of their sequence id (which means - the order in which they were 'sent'), it is capable of separating out the particular frames, basing on the **e** (ending packet of the frame) characters at the end of the frame id. This element also reads the timestamp from the packets' headers and puts it into buffer's 'pts' (*Presentation timestamp*) field.
31+
- **Mixer** - responsible for mixing the frames received via two input pads. The order in which the frames are mixed is based on their 'pts' (*Presentation timestamp*).
32+
- **Sink** - this element is responsible for writing the received frames to the file. Since the Mixer takes care of sorting the frames based on the timestamp, Sink can take advantage of the fact that the frames will be ordered and write them to the file in the order they are received.
33+
34+
Now, that you have some high-level understanding of the system we can get down to implementation.

0 commit comments

Comments
 (0)