Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge outstanding ⮡ tarent/DTAG-LLCTO/AML changes #46

Open
wants to merge 32 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
46a6d8d
repair file types (symbolic link vs. regular file)
mirabilos Jun 30, 2020
9b623e4
apply the changes I know are absolutely correct
mirabilos Jun 30, 2020
37ee23a
add build instructions for everything found in this repository
mirabilos Jun 22, 2020
71a43ad
apply another bugfix from the two other RtpQueue impl files
mirabilos Jun 30, 2020
c2c519e
use #include instead of symbolic links
mirabilos Jul 3, 2020
38c6ed4
normalise whitespace before merging to facilitate it
mirabilos Jul 3, 2020
781b8ef
normalise whitespace before merging to facilitate it
mirabilos Jul 3, 2020
f358c80
Merge branch 'master' of https://github.com/EricssonResearch/scream
mirabilos Jul 3, 2020
ded7b3c
whitespace, again
mirabilos Jul 3, 2020
394e024
Merge branch 'master' into round2
mirabilos Jul 3, 2020
0c94fbe
Merge branch 'master' of https://github.com/EricssonResearch/scream i…
mirabilos Jul 3, 2020
246b900
unify RtpQueue as well, with tiny ifdefs
mirabilos Jul 3, 2020
4acc9d5
Merge branches 'master' and 'round2' into round3
mirabilos Jun 27, 2022
78a46d3
do not commit generated files (binaries, especially)
mirabilos Jun 27, 2022
2ee76bc
update build instructions, link all subdirs’ READMEs, etc.
mirabilos Jun 27, 2022
9bf048e
fix whitespace: files with trailing CR
mirabilos Jun 27, 2022
eed6c63
fix whitespace: extra WS at EOL/EOF
mirabilos Jun 27, 2022
49d1f82
fix whitespace: space before tab in indent
mirabilos Jun 27, 2022
5a6770b
drop unused local_rtp_addr
mirabilos Jun 27, 2022
664c854
somewhat fix option parsing
mirabilos Jun 27, 2022
1ad599a
fix file comment
mirabilos Jun 27, 2022
ac18754
g/c now-unused constants
mirabilos Jun 27, 2022
2aad25f
fix pasto in comment
mirabilos Jun 27, 2022
acb4836
drop unused dummy_rtcp_addr
mirabilos Jun 27, 2022
64c0293
g/c unused sender_rtcp_addr
mirabilos Jun 27, 2022
734358c
don’t shadow int recvlen
mirabilos Jun 27, 2022
5f735ce
move sender_rtp_addr to #if branch using it locally
mirabilos Jun 27, 2022
a8c988d
fix error message
mirabilos Jun 27, 2022
7081b38
fix -ect -1
mirabilos Jun 27, 2022
2eef619
fix command line option documentations
mirabilos Jun 28, 2022
91b4880
more shadowed variables
mirabilos Jun 28, 2022
87e04ab
fix actually stopping threads
mirabilos Jul 5, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,4 @@ INCLUDE_DIRECTORIES(
${scream_SOURCE_DIR}/../include
)

ADD_SUBDIRECTORY( code)
ADD_SUBDIRECTORY( code)
107 changes: 76 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@
This project includes an implementation of SCReAM, a mobile optimised congestion control algorithm for realtime interactive media.

## Algorithm
SCReAM (**S**elf-**C**locked **R**at**e** **A**daptation for **M**ultimedia) is a congestion control algorithm devised mainly for Video.
Congestion control for WebRTC media is currently being standardized in the IETF RMCAT WG, the scope of the working group is to define requirements for congestion control and also to standardize a few candidate solutions.
SCReAM is a congestion control candidate solution for WebRTC developed at Ericsson Research and optimized for good performance in wireless access.
SCReAM (**S**elf-**C**locked **R**at**e** **A**daptation for **M**ultimedia) is a congestion control algorithm devised mainly for Video.
Congestion control for WebRTC media is currently being standardized in the IETF RMCAT WG, the scope of the working group is to define requirements for congestion control and also to standardize a few candidate solutions.
SCReAM is a congestion control candidate solution for WebRTC developed at Ericsson Research and optimized for good performance in wireless access.

The algorithm is an IETF experimental standard [1], a Sigcomm paper [2] and [3] explains the rationale behind the design of the algorithm in more detail. A comparison against GCC (Google Congestion Control) is shown in [4]. Final presentations are found in [5] and [6]. A short [video](https://www.youtube.com/watch?v=_jBFu-Y0wwo) exemplifies the use of SCReAM in a small vehicle, remote controlled over a public LTE network. [7] explains the rationale behind the use of SCReAM in remote controlled applications over LTE/5G.

Unlike many other congestion control algorithms that are rate based i.e. they estimate the network throughput and adjust the media bitrate accordingly, SCReAM is self-clocked which essentially means that the algorithm does not send in more data into a network than what actually exits the network.

To achieve this, SCReAM implements a feedback protocol over RTCP that acknowledges received RTP packets.
A congestion window is determined from the feedback, this congestion window determines how many RTP packets that can be in flight i.e. transmitted by not yet acknowledged, an RTP queue is maintained at the sender side to temporarily store the RTP packets pending transmission, this RTP queue is mostly empty but can temporarily become larger when the link throughput decreases.
The congestion window is frequently adjusted for minimal e2e delay while still maintaining as high link utilization as possible. The use of self-clocking in SCReAM which is also the main principle in TCP has proven to work particularly well in wireless scenarios where the link throughput may change rapidly. This enables a congestion control which is robust to channel jitter, introduced by e.g. radio resource scheduling while still being able to respond promptly to reduced link throughput.
To achieve this, SCReAM implements a feedback protocol over RTCP that acknowledges received RTP packets.
A congestion window is determined from the feedback, this congestion window determines how many RTP packets that can be in flight i.e. transmitted by not yet acknowledged, an RTP queue is maintained at the sender side to temporarily store the RTP packets pending transmission, this RTP queue is mostly empty but can temporarily become larger when the link throughput decreases.
The congestion window is frequently adjusted for minimal e2e delay while still maintaining as high link utilization as possible. The use of self-clocking in SCReAM which is also the main principle in TCP has proven to work particularly well in wireless scenarios where the link throughput may change rapidly. This enables a congestion control which is robust to channel jitter, introduced by e.g. radio resource scheduling while still being able to respond promptly to reduced link throughput.
SCReAM is optimized in house in a state of the art LTE system simulator for optimal performance in deployments where the LTE radio conditions are limiting. In addition, SCReAM is also optimized for good performance in simple bottleneck case such as those given in home gateway deployments. SCReAM is verified in simulator and in a testbed to operate in a rate range from ~20kbps up to 100Mbps.
The fact that SCReAM maintains a RTP queue on the sender side opens up for further optimizations to congestion, for instance it is possible to discard the contents of the RTP queue and replace with an I frame in order to refresh the video quickly at congestion.

Expand All @@ -22,14 +22,14 @@ Below is shown an example of SCReAM congestion control when subject to a bottlen

Figure 1 : Simple bottleneck simulation SCReAM

## ECN (Explicit Congestion Notification)
SCReAM supports "classic" ECN, i.e. that the sending rate is reduced as a result of one or more ECN marked RTP packets in one RTT, similar to the guidelines in RFC3168. .
## ECN (Explicit Congestion Notification)
SCReAM supports "classic" ECN, i.e. that the sending rate is reduced as a result of one or more ECN marked RTP packets in one RTT, similar to the guidelines in RFC3168. .

In addition SCReAM also supports L4S, i.e that the sending rate is reduced proportional to the fraction of the RTP packets that are ECN marked. This enables lower network queue delay.
In addition SCReAM also supports L4S, i.e that the sending rate is reduced proportional to the fraction of the RTP packets that are ECN marked. This enables lower network queue delay.

Below is shown three simulation examples with a simple 50Mbps bottleneck that changes to 25Mbps after 50s, the min RTT is 20ms. The video trace is from NVENC.

The graphs show that ECN improves on the e2e delay and that the use of L4S reduces the delay considerably more.
The graphs show that ECN improves on the e2e delay and that the use of L4S reduces the delay considerably more.

L4S gives a somewhat lower media rate, the reason is that a larger headroom is added to ensure the low delay, considering the varying output rate of the video encoder. This is self-adjusting by inherent design, the average bitrate would increase if the frame size variations are smaller.

Expand All @@ -38,10 +38,10 @@ Note carefully that the scales in the graphs differ, especially the delay graph
![Simple bottleneck simulation SCReAM no ECN support](https://github.com/EricssonResearch/scream/blob/master/images/scream_noecn_2.png)

Figure 2 : SCReAM without ECN support

![Simple bottleneck simulation SCReAM with ECN support](https://github.com/EricssonResearch/scream/blob/master/images/scream_ecn_2.png)

Figure 3 : SCReAM with ECN support ECN beta = 0.8. CoDel with default settings (5ms, 100ms)
Figure 3 : SCReAM with ECN support ECN beta = 0.8. CoDel with default settings (5ms, 100ms)

![Simple bottleneck simulation SCReAM with L4S support](https://github.com/EricssonResearch/scream/blob/master/images/scream_l4s_2.png)

Expand All @@ -51,9 +51,9 @@ Figure 4 : SCReAM with L4S support. L4S ramp-marker (Th_low=2ms, Th_high=10ms)

The two videos below show a simple test with a simple 3Mbps bottleneck (CoDel AQM, ECN cabable). The first video is with ECN disabled in the sender, the other is with ECN enabled. SCReAM is here used with a Panasonic WV-SBV111M IP camera. One may argue that one can disable CoDel to avoid the packet losses, unfortunately one then lose the positive properties with CoDel, mentioned earlier.

[Without ECN](https://www.youtube.com/watch?v=J0po78q1QkU "Without ECN")
[Without ECN](https://www.youtube.com/watch?v=J0po78q1QkU "Without ECN")

[With ECN](https://www.youtube.com/watch?v=qIe0ubw9jPw "With ECN")
[With ECN](https://www.youtube.com/watch?v=qIe0ubw9jPw "With ECN")

The green areas that occur due to packet loss is an artifact in the conversion of the RTP dump.
## Real life test
Expand All @@ -62,17 +62,17 @@ A real life test of SCReAM is performed with the following setup in a car:
- Sony Camcorder placed on dashboard, HDMI output used
- Antrica ANT-35000A video encoder with 1000-8000kbps encoding range and 1080p50 mode
- Laptop with a SCReAM sender running
- Sony Xperia phone in WiFi tethering mode
- Sony Xperia phone in WiFi tethering mode

A SCReAM receiver that logged the performance and stored the received RTP packets was running in an office. The video traffic was thus transmitted in LTE uplink.The video was played out to file with GStreamer, the jitter buffer was disabled to allow for the visibility of the delay jitter artifacts,

Below is a graph that shows the bitrate, the congestion window and the queue delay.
Below is a graph that shows the bitrate, the congestion window and the queue delay.

![Log from ](https://github.com/EricssonResearch/scream/blob/master/images/SCReAM_LTE_UL.png)

Figure 5 : Trace from live drive test

The graph shows that SCReAM manages high bitrate video streaming with low e2e delay despite demanding conditions both in terms of variable throughput and in a changing output bitrate from the video encoder. Packet losses occur relatively frequently, the exact reason is unknown but seem to be related to handover events, normally packet loss should not occure in LTE-UL, however this seems to be the case with the used cellphone.
The graph shows that SCReAM manages high bitrate video streaming with low e2e delay despite demanding conditions both in terms of variable throughput and in a changing output bitrate from the video encoder. Packet losses occur relatively frequently, the exact reason is unknown but seem to be related to handover events, normally packet loss should not occure in LTE-UL, however this seems to be the case with the used cellphone.
The delay increases between 1730 and 1800s, the reason here is that the available throughput was lower than the lowest possible coder bitrate. An encoder with a wider rate range would be able to make it possible to keep the delay low also in this case.

A video from the experiment is found at the link below. The artifacts and overall video quality can be correlated aginst the graph above.
Expand Down Expand Up @@ -104,17 +104,17 @@ A few support classes for experimental use are implemented in:

- NetQueue : Simple delay and bandwidth limitation

For more information on how to use the code in multimedia clients or in experimental platforms, please see [https://github.com/EricssonResearch/scream/blob/master/SCReAM-description.pptx](https://github.com/EricssonResearch/scream/blob/master/SCReAM-description.pptx?raw=true)
For more information on how to use the code in multimedia clients or in experimental platforms, please see [https://github.com/EricssonResearch/scream/blob/master/SCReAM-description.pptx](https://github.com/EricssonResearch/scream/blob/master/SCReAM-description.pptx?raw=true)


## References
[1] https://tools.ietf.org/html/rfc8298

[2] Sigcomm paper http://dl.acm.org/citation.cfm?id=2631976
[2] Sigcomm paper http://dl.acm.org/citation.cfm?id=2631976

[3] Sigcomm presentation http://conferences.sigcomm.org/sigcomm/2014/doc/slides/150.pdf

[4] IETF RMCAT presentation, comparison against Google Congestion Control (GCC) http://www.ietf.org/proceedings/90/slides/slides-90-rmcat-3.pdf
[4] IETF RMCAT presentation, comparison against Google Congestion Control (GCC) http://www.ietf.org/proceedings/90/slides/slides-90-rmcat-3.pdf

[5] IETF RMCAT presentation (final for WGLC) : https://www.ietf.org/proceedings/96/slides/slides-96-rmcat-0.pdf

Expand All @@ -138,20 +138,65 @@ The feedback overhead depends on the media bitrate. The table below shows the IP
| 30000 | 500 |
+-----------------------------------------------------+

## Build
# How to build this repository?

We assume you have git already installed, since you checked this out.

The SCReAM code comes in two (three) applications

- Windows based test application : This application implements a simple bottleneck and does only local simulation. Open the scream.sln application in Visual studio and build.
- Linux based BW test application : Makes in possible to benchmark the throughput live networks and test beds. The tool models a video encoder. See https://github.com/EricssonResearch/scream/blob/master/SCReAM-description.pptx for further instructions.
- gstreamer plugin : This application is kept in ./code/gscream . It is however currently not maintained and may not work properly
- Windows-based test application: This application implements a simple bottleneck and does only local simulation. Open the scream.sln application in Visual studio and build.
- Linux-based bandwidth test application: Makes in possible to benchmark the throughput live networks and test beds. The tool models a video encoder. See https://github.com/EricssonResearch/scream/blob/master/SCReAM-description.pptx for further instructions.
- gstreamer plugin: This application is kept in ./code/gscream . It is however currently not maintained and may not work properly

## BW test tool

To build the bandwidth test application (this has been tested on Debian buster and Ubuntu 16.04 and later), install some generic build dependencies first:

sudo apt-get install autoconf autopoint bison build-essential cmake flex gettext libtool pkg-config yasm

cmake . && make

creates `bin/scream_bw_test_rx`
and `bin/scream_bw_test_tx`

## gscream

### install dependencies

sudo apt-get install gstreamer1.0-{doc,libav,tools,x,plugins-{base,good,bad,ugly}}
sudo apt-get install libglib2.0-dev liborc-0.4-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev

### build plugins

cd code/gscream/gst-gscreamrx/gst-plugin
./autogen.sh && make
cd rx tx
./autogen.sh && make
cd ../../../..

creates `code/gscream/gst-gscreamrx/gst-plugin/src/.libs/libgstgscreamrx.so`
and `code/gscream/gst-gscreamtx/gst-plugin/src/.libs/libgstgscreamtx.so`
which, with a `sudo make install` in the respective directories, will be
installed into `/usr/local/lib/gstreamer-1.0/`.

### build test applications

cd code/gscream
make

creates `code/gscream/gscream_app_rpi_tx`,
`code/gscream/gscream_app_rx` and `code/gscream/gscream_app_tx`

See [`code/gscream/readme.txt`](./code/gscream/readme.txt) for
what to do with these files.

### Build SCReAM BW test application
## gstscream (Rust)

The SCReAM BW test application runs on e.g Ubuntu 16.04 and later. The build steps are:
See [`gstscream/README.md`](./gstscream/README.md) about this.

```
cmake .
make
```
## multicam

You need git, cmake, make and g++ installed
See [`multicam/sender/README.md`](./multicam/sender/README.md) and
[`multicam/receiver/README.md`](./multicam/receiver/README.md) for
building instructions,
then read [`multicam/README.md`](./multicam/README.md) for info.
5 changes: 2 additions & 3 deletions Sierra-RV50X-logger.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

import requests
import json
import datetime
Expand Down Expand Up @@ -81,12 +80,12 @@ def send_to_udp_socket(result):
UDP_IP = "127.0.0.1"
UDP_PORT = 35000
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(bytes(result, 'utf-8'), (UDP_IP, UDP_PORT))
sock.sendto(bytes(result, 'utf-8'), (UDP_IP, UDP_PORT))

# params = ['Cellular IP Address', 'ESN/EID/IMEI']
params = param_ids.keys()
try:
while True:
while True:
result = make_request(params)
#result = make_request(payload)
#print('result:', json.dumps(result, indent=4))
Expand Down
17 changes: 9 additions & 8 deletions code/NetQueue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <algorithm>

using namespace std;

/*
* Implements a simple RTP packet queue
*/
Expand Down Expand Up @@ -40,10 +41,10 @@ NetQueue::NetQueue(float delay_, float rate_, float jitter_, bool isL4s_) {
tQueueAvg = 0.0;
}

void NetQueue::insert(float time,
void *rtpPacket,
void NetQueue::insert(float time,
void *rtpPacket,
unsigned int ssrc,
int size,
int size,
unsigned short seqNr,
bool isCe) {
int prevHead = head;
Expand All @@ -57,7 +58,7 @@ void NetQueue::insert(float time,
items[head]->tQueue = time;
items[head]->isCe = isCe;
if (rate > 0) {
float delay = size*8.0f / rate;
float delay = size*8.0f / rate;
if (prevHead != -1 && items[prevHead]->used) {
items[head]->tRelease = items[prevHead]->tRelease + delay;
}
Expand All @@ -69,10 +70,10 @@ void NetQueue::insert(float time,
nextTx = items[head]->tRelease;
}

bool NetQueue::extract(float time,
void *rtpPacket,
bool NetQueue::extract(float time,
void *rtpPacket,
unsigned int &ssrc,
int& size,
int& size,
unsigned short& seqNr,
bool& isCe) {
if (items[tail]->used == false) {
Expand Down Expand Up @@ -122,7 +123,7 @@ bool NetQueue::extract(float time,
int NetQueue::sizeOfQueue() {
int size = 0;
for (int n=0; n < NetQueueSize; n++) {
if (items[n]->used)
if (items[n]->used)
size += items[n]->size;
}
return size;
Expand Down
9 changes: 4 additions & 5 deletions code/NetQueue.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#ifndef NET_QUEUE
#define NET_QUEUE


class NetQueueItem {
public:
NetQueueItem();
Expand All @@ -26,10 +25,10 @@ class NetQueue {
int size,
unsigned short seqNr,
bool isCe = false);
bool extract(float time,
void *rtpPacket,
bool extract(float time,
void *rtpPacket,
unsigned int &ssrc,
int& size,
int& size,
unsigned short &seqNr,
bool &isCe);
int sizeOfQueue();
Expand All @@ -54,4 +53,4 @@ class NetQueue {
float tQueueAvg;
};

#endif
#endif
42 changes: 40 additions & 2 deletions code/RtpQueue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ bool RtpQueue::pop(void **rtpPacket, int& size, unsigned short& seqNr, bool &isM
{
if (items[tail]->used == false) {
*rtpPacket = NULL;
return false;
sizeOfNextRtp_ = -1;
return false;
} else {
size = items[tail]->size;

Expand All @@ -64,14 +64,52 @@ bool RtpQueue::pop(void **rtpPacket, int& size, unsigned short& seqNr, bool &isM
seqNr = items[tail]->seqNr;
isMark = items[tail]->isMark;
items[tail]->used = false;
tail++; if (tail == kRtpQueueSize) tail = 0;
bytesInQueue_ -= size;
sizeOfQueue_ -= 1;
tail++; if (tail == kRtpQueueSize) tail = 0;
computeSizeOfNextRtp();
return true;
}
}

#ifdef GSCREAM
void RtpQueue::push(GstBuffer *buffer, int size, unsigned short seqNr, float ts) {
int ix = head+1;
if (ix == kRtpQueueSize) ix = 0;
if (items[ix]->used) {
/*
* RTP queue is full, do a drop tail i.e ignore new RTP packets
*/
return;
}
head = ix;
items[head]->seqNr = seqNr;
items[head]->size = size;
items[head]->ts = ts;
items[head]->used = true;
items[head]->buffer = buffer;
bytesInQueue_ += size;
sizeOfQueue_ += 1;
computeSizeOfNextRtp();
}

GstBuffer* RtpQueue::pop(unsigned short& seqNr) {
if (items[tail]->used == false) {
sizeOfNextRtp_ = -1;
return 0;
} else {
GstBuffer *buffer = items[tail]->buffer;
seqNr = items[tail]->seqNr;
items[tail]->used = false;
bytesInQueue_ -= items[tail]->size;
sizeOfQueue_ -= 1;
tail++; if (tail == kRtpQueueSize) tail = 0;
computeSizeOfNextRtp();
return buffer;
}
}
#endif

void RtpQueue::computeSizeOfNextRtp() {
if (!items[tail]->used) {
sizeOfNextRtp_ = - 1;
Expand Down
Loading