├── .gitignore
├── CMakeLists.txt
├── L4S-Results.pdf
├── LICENSE
├── README.md
├── SCReAM-BW-test-tool.docx
├── SCReAM-BW-test-tool.pptx
├── SCReAM-description.pptx
├── SCReAM-test-tool-one-pager.pptx
├── Sierra-RV50X-logger.py
├── code
├── CMakeLists.txt
├── NetQueue.cpp
├── NetQueue.h
├── OooQueue.cpp
├── OooQueue.h
├── RtpQueue.cpp
├── RtpQueue.h
├── ScreamRx.cpp
├── ScreamRx.h
├── ScreamTx.cpp
├── ScreamTx.h
├── ScreamV2Tx.cpp
├── ScreamV2Tx.h
├── ScreamV2TxStream.cpp
├── TxList.h
├── VideoEnc.cpp
├── VideoEnc.h
├── scream_01.vcxproj
├── scream_01.vcxproj.user
├── scream_receiver.cpp
├── scream_sender.cpp
├── scream_v_a.cpp
├── stdafx.cpp
├── stdafx.h
├── targetver.h
└── wrapper_lib
│ ├── CMakeLists.txt
│ ├── meson.build
│ ├── screamtx_plugin_wrapper.cpp
│ └── screamtxbw_plugin_wrapper.cpp
├── examples
├── trace-dualpi-50Mbps-25ms-l4s-txrx.txt
├── trace-dualpi-50Mbps-25ms-l4s.txt
├── trace-dualpi-50Mbps-25ms-nol4s-txrx.txt
└── trace-dualpi-50Mbps-25ms-nol4s.txt
├── gstscream
├── .gitignore
├── 2717.patch
├── Cargo.lock
├── Cargo.toml
├── README.md
├── build.rs
├── scripts
│ ├── build.sh
│ ├── env.sh
│ ├── receiver.sh
│ ├── receiver_3.sh
│ ├── receiver_bw.sh
│ ├── screamtx_stats.py
│ ├── sender.sh
│ ├── sender_3.sh
│ ├── sender_bw.sh
│ └── sysctl.sh
├── src
│ ├── lib.rs
│ ├── receiver.rs
│ ├── screamrx
│ │ ├── ScreamRx.rs
│ │ ├── ecn.rs
│ │ ├── imp.rs
│ │ └── mod.rs
│ ├── screamtx
│ │ ├── imp.rs
│ │ └── mod.rs
│ ├── screamtxbw
│ │ ├── imp.rs
│ │ └── mod.rs
│ ├── sender.rs
│ └── sender_util.rs
└── udp_ecn_diff.txt
├── images
├── L4S-100Mbps-25ms-0-4-0-TCP.png
├── L4S-100Mbps-25ms-0-4-TCP.png
├── L4S-100Mbps-25ms-r-50-0-4-TCP.png
├── SCReAM-V2-L4S.png
├── SCReAM-V2-RTT-25ms-1360B.png
├── SCReAM-V2-noL4S.png
├── SCReAM_LTE_UL.png
├── image_1.png
├── image_2.png
├── scream_ecn.png
├── scream_ecn_2.png
├── scream_ecn_keyframe.png
├── scream_l4s.png
├── scream_l4s_2.png
├── scream_noecn.png
├── scream_noecn_2.png
└── scream_noecn_keyframe.png
├── multicam
├── README.md
├── receiver
│ ├── LICENSE.dat
│ ├── README.md
│ ├── killitall.sh
│ ├── rendermedia-intel.sh
│ ├── rendermedia.sh
│ ├── scream
│ │ ├── CMakeLists.txt
│ │ └── code
│ │ │ ├── CMakeLists.txt
│ │ │ └── scream_receiver.cpp
│ ├── startreceiver-intel.sh
│ └── startreceiver.sh
└── sender
│ ├── 6_bkg_L4S_flows.scream
│ ├── LICENSE.dat
│ ├── README.md
│ ├── default.scream
│ ├── gst-codec-ctrl
│ └── gst-plugin
│ │ ├── AUTHORS
│ │ ├── COPYING
│ │ ├── ChangeLog
│ │ ├── INSTALL
│ │ ├── Makefile.am
│ │ ├── Makefile.in
│ │ ├── NEWS
│ │ ├── README
│ │ ├── aclocal.m4
│ │ ├── autogen.sh
│ │ ├── autom4te.cache
│ │ ├── output.0
│ │ ├── output.1
│ │ ├── requests
│ │ ├── traces.0
│ │ └── traces.1
│ │ ├── compile
│ │ ├── config.guess
│ │ ├── config.h
│ │ ├── config.h.in
│ │ ├── config.h.in~
│ │ ├── config.log
│ │ ├── config.status
│ │ ├── config.sub
│ │ ├── configure
│ │ ├── configure.ac
│ │ ├── depcomp
│ │ ├── install-sh
│ │ ├── libtool
│ │ ├── ltmain.sh
│ │ ├── missing
│ │ ├── src
│ │ ├── .deps
│ │ │ └── libgstcodecctrl_la-gstcodecctrl.Plo
│ │ ├── .libs
│ │ │ ├── libgstcodecctrl.exp
│ │ │ ├── libgstcodecctrl.lai
│ │ │ └── libgstcodecctrl.so
│ │ ├── Makefile.am
│ │ ├── Makefile.in
│ │ ├── gstcodecctrl.cpp
│ │ ├── gstcodecctrl.h
│ │ ├── gstplugin.cpp
│ │ ├── gstplugin.h
│ │ ├── gsttransform.c
│ │ ├── gsttransform.h
│ │ └── targetver.h
│ │ └── stamp-h1
│ ├── killitall.sh
│ ├── scream
│ ├── CMakeLists.txt
│ └── code
│ │ ├── CMakeLists.txt
│ │ └── scream_sender.cpp
│ ├── startsender.sh
│ └── startsender_2.sh
├── plot_1_stream.m
├── plot_1_stream_s.m
├── plot_4_stream.m
├── plot_cdf.m
├── plot_thp_delay.m
├── plot_thp_delay_new.m
├── plot_txrx.m
├── scream.sln
├── scream_ecn_keyframe.png
├── scream_noecn_keyframe.png
├── test-record.md
├── test_v_a.m
├── traces
├── trace_flat.txt
├── trace_key.txt
└── trace_no_key.txt
└── version-history.md
/.gitignore:
--------------------------------------------------------------------------------
1 | *.a
2 | *.la
3 | *.lo
4 | *.o
5 | CMakeCache.txt
6 | CMakeFiles/
7 | Makefile
8 | bin/
9 | cmake_install.cmake
10 | code/gscream/gscream_app_rpi_tx
11 | code/gscream/gscream_app_rx
12 | code/gscream/gscream_app_tx
13 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.6)
2 |
3 | PROJECT( scream )
4 |
5 | message("Source Dir:" ${scream_SOURCE_DIR})
6 |
7 | SET(EXECUTABLE_OUTPUT_PATH ${scream_SOURCE_DIR}/bin)
8 | SET(LIBRARY_OUTPUT_PATH ${scream_SOURCE_DIR}/lib)
9 | SET(RUNTIME_OUTPUT_DIRECTORY ${scream_SOURCE_DIR}/bin)
10 |
11 | SET(scream_BIN ${scream_SOURCE_DIR}/bin)
12 |
13 | message("scream_SOURCE_DIR directories:" ${scream_SOURCE_DIR})
14 |
15 | IF(UNIX)
16 | add_definitions(-std=c++0x)
17 | ENDIF(UNIX)
18 |
19 | IF(WIN32)
20 | IF(MSVC12)
21 | message("Detected MSVC12 compiler")
22 | set(MSVC_VER VC12)
23 | ELSEIF(MSVC11)
24 | message("Detected MSVC11 compiler")
25 | set(MSVC_VER VC11)
26 | ELSEIF(MSVC10)
27 | message("Detected MSVC10 compiler")
28 | set(MSVC_VER VC10)
29 | ELSEIF(MSVC14)
30 | message("Detected MSVC14 compiler")
31 | set(MSVC_VER VC14)
32 | ELSE(MSVC12)
33 | message("WARNING: Unknown/unsupported MSVC version")
34 | ENDIF(MSVC12)
35 | ENDIF(WIN32)
36 |
37 | if( CMAKE_SIZEOF_VOID_P EQUAL 8 )
38 | # 64bit
39 | message("Detected 64-bit build - compiling with -fPIC")
40 | SET(CMAKE_CXX_FLAGS "-fPIC -fpermissive -pthread -DV2")
41 | else( CMAKE_SIZEOF_VOID_P EQUAL 8 )
42 | # 32 bit
43 | message("Detected 32-bit build")
44 | SET(CMAKE_CXX_FLAGS "-fPIC -fpermissive -pthread -DV2")
45 | endif( CMAKE_SIZEOF_VOID_P EQUAL 8 )
46 |
47 | SET(screamIncludes
48 | ${scream_SOURCE_DIR}
49 | ${scream_SOURCE_DIR}/code
50 | )
51 |
52 | message("screamIncludes directories:" ${screamIncludes})
53 |
54 | # lib directories
55 | IF(WIN32)
56 | SET(screamLink
57 | ${scream_SOURCE_DIR}/../lib
58 | )
59 | ELSEIF(UNIX)
60 | SET(screamLink
61 | ${scream_SOURCE_DIR}/../lib
62 | /usr/local/lib
63 | /usr/lib
64 | )
65 | ENDIF(WIN32)
66 |
67 | SET(LibDir
68 | ${scream_SOURCE_DIR}/../lib
69 | )
70 |
71 | message("LibDir directories:" ${LibDir})
72 |
73 | # Include directories
74 | INCLUDE_DIRECTORIES(
75 | ${scream_SOURCE_DIR}/../include
76 | )
77 |
78 | ADD_SUBDIRECTORY( code)
79 |
--------------------------------------------------------------------------------
/L4S-Results.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricssonResearch/scream/5d5e4ca2c41ad62875314e5e8d2571efd58aad6a/L4S-Results.pdf
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015, Ericsson AB. All rights reserved.
2 |
3 | Redistribution and use in source and binary forms, with or without modification,
4 | are permitted provided that the following conditions are met:
5 |
6 | 1. Redistributions of source code must retain the above copyright notice, this
7 | list of conditions and the following disclaimer.
8 |
9 | 2. Redistributions in binary form must reproduce the above copyright notice, this
10 | list of conditions and the following disclaimer in the documentation and/or other
11 | materials provided with the distribution.
12 |
13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
17 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
19 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
20 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
21 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
22 | OF SUCH DAMAGE.
23 |
--------------------------------------------------------------------------------
/SCReAM-BW-test-tool.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricssonResearch/scream/5d5e4ca2c41ad62875314e5e8d2571efd58aad6a/SCReAM-BW-test-tool.docx
--------------------------------------------------------------------------------
/SCReAM-BW-test-tool.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricssonResearch/scream/5d5e4ca2c41ad62875314e5e8d2571efd58aad6a/SCReAM-BW-test-tool.pptx
--------------------------------------------------------------------------------
/SCReAM-description.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricssonResearch/scream/5d5e4ca2c41ad62875314e5e8d2571efd58aad6a/SCReAM-description.pptx
--------------------------------------------------------------------------------
/SCReAM-test-tool-one-pager.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricssonResearch/scream/5d5e4ca2c41ad62875314e5e8d2571efd58aad6a/SCReAM-test-tool-one-pager.pptx
--------------------------------------------------------------------------------
/Sierra-RV50X-logger.py:
--------------------------------------------------------------------------------
1 |
2 | import requests
3 | import json
4 | import datetime
5 | import time
6 | import socket
7 |
8 | # OUT_FILE = 'data.txt'
9 | # This simple application logs the Sierra RV50X (possibly other Sierra modems too)
10 | # The data is echoed to 127.0.0.1:35000, the SCReAM wrappers can get the data this
11 | # way and then include it the SCReAM logging
12 | # >python3 Sierra-RV50X-logger.py
13 |
14 |
15 | base_url = 'http://192.168.13.31:9191'
16 | username = 'user'
17 | password = '12345'
18 |
19 | login_url = '{}/xml/Connect.xml'.format(base_url)
20 | login_payload = '''
21 |
22 | {}
23 |
24 |
25 | '''.format(username, password)
26 |
27 | req_url = '{}/cgi-bin/Embedded_Ace_Get_Task.cgi'.format(base_url)
28 | req_headers = {
29 | 'Content-Type': 'text/xml',
30 | }
31 |
32 | # Param name to id map
33 | param_ids = {
34 | 'Cellular IP Address': 303,
35 | 'ESN/EID/IMEI': 10,
36 | 'Active Frequency Band': 671,
37 | 'SIM ID': 771,
38 | 'Cell ID': 773,
39 | 'RSRP': 10210,
40 | 'SINR': 10209,
41 | 'RSSI': 261,
42 | }
43 |
44 | param_names = dict(map(lambda tup: (tup[1], tup[0]), param_ids.items()))
45 |
46 | # payload = '303,12001,12002,10,771,11202,10701,10702,10704,785,773,774,775,671,674,672,675,1105,1104,10230,10298,5030,1082,1083,12005,12006,1091,1136,2753,5046,283,284,10283,10284,281,282,51006,52007,52008,53000,53101,53200,12003,12003,12003,12003'
47 | #payload = '303,12001,10'
48 | payload = '10210,10209,261,773'
49 |
50 | def make_params_payload(params):
51 | param_list = map(lambda param: str(param_ids[param]), params)
52 | return ','.join(param_list)
53 |
54 | def parse_pair(pair):
55 | [pid_str, value] = pair.split('=')
56 | pid = int(pid_str)
57 | param_name = param_names[pid] if pid in param_names else 'param {}'.format(pid)
58 | return (param_name, value)
59 |
60 | def parse_params(data):
61 | pairs = data.split('!')[:-1]
62 | return dict(map(lambda pair: parse_pair(pair), pairs))
63 |
64 | def make_request(params):
65 | with requests.Session() as s:
66 | p = s.post(login_url, data=login_payload)
67 | print('login response text:', p.text)
68 |
69 | #payload = make_params_payload(params)
70 |
71 | r = s.post(req_url, headers=req_headers, data=payload)
72 | # print('request text:', r.text)
73 |
74 | return {
75 | 'timestamp': datetime.datetime.now().isoformat(),
76 | 'data': parse_params(r.text),
77 | }
78 | # return None
79 |
80 | def send_to_udp_socket(result):
81 | UDP_IP = "127.0.0.1"
82 | UDP_PORT = 35000
83 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
84 | sock.sendto(bytes(result, 'utf-8'), (UDP_IP, UDP_PORT))
85 |
86 | # params = ['Cellular IP Address', 'ESN/EID/IMEI']
87 | params = param_ids.keys()
88 | try:
89 | while True:
90 | result = make_request(params)
91 | #result = make_request(payload)
92 | #print('result:', json.dumps(result, indent=4))
93 | print(result)
94 | send_to_udp_socket(json.dumps(result))
95 | time.sleep(1)
96 | except KeyboardInterrupt:
97 | print('\n Terminated from keyboard. \n')
98 |
99 |
100 | # with open(OUT_FILE, 'a') as f:
101 | # f.write('row\n')
102 |
--------------------------------------------------------------------------------
/code/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # source files
2 |
3 | SET(HEADERS
4 | ScreamRx.h
5 | ScreamTx.h
6 | RtpQueue.h
7 | )
8 |
9 | SET(SRC_SENDER
10 | ScreamTx.cpp
11 | ScreamV2Tx.cpp
12 | ScreamV2TxStream.cpp
13 | RtpQueue.cpp
14 | scream_sender.cpp
15 | )
16 |
17 | SET(SRC_RECEIVER
18 | ScreamRx.cpp
19 | scream_receiver.cpp
20 | )
21 |
22 | set(CMAKE_BUILD_TYPE Debug)
23 |
24 | INCLUDE_DIRECTORIES(
25 | ${screamIncludes}
26 | )
27 |
28 | LINK_DIRECTORIES(
29 | ${screamLink}
30 | )
31 |
32 | ADD_EXECUTABLE(scream_bw_test_tx ${SRC_SENDER} ${HEADERS})
33 | ADD_EXECUTABLE(scream_bw_test_rx ${SRC_RECEIVER} ${HEADERS})
34 |
35 | TARGET_LINK_LIBRARIES (
36 | scream_bw_test_tx
37 | ${screamLibs} pthread
38 | )
39 |
40 | TARGET_LINK_LIBRARIES (
41 | scream_bw_test_rx
42 | ${screamLibs} pthread
43 | )
44 |
--------------------------------------------------------------------------------
/code/NetQueue.cpp:
--------------------------------------------------------------------------------
1 | #include "NetQueue.h"
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | using namespace std;
9 | /*
10 | * Implements a simple RTP packet queue
11 | */
12 |
13 | const float l4sThLo = 0.004f;
14 | const float l4sThHi = 0.008f;
15 | NetQueueItem::NetQueueItem() {
16 | packet = 0;
17 | used = false;
18 | size = 0;
19 | seqNr = 0;
20 | timeStamp = 0;
21 | tRelease = 0.0;
22 | tQueue = 0.0;
23 | }
24 |
25 | NetQueue::NetQueue(float delay_, float rate_, float jitter_, bool isL4s_) {
26 | for (int n=0; n < NetQueueSize; n++) {
27 | items[n] = new NetQueueItem();
28 | }
29 | head = -1;
30 | tail = 0;
31 | nItems = 0;
32 | rate = rate_;
33 | delay = delay_;
34 | jitter = jitter_;
35 | lastQueueLow = 0.0;
36 | // nextTx = 0;
37 | sendTime = 0;
38 | isL4s = isL4s_;
39 | bytesTx = 0;
40 | lastRateUpdateT = 0;
41 | pDrop = 0.0f;
42 | prevRateFrac = 0.0f;
43 | tQueueAvg = 0.0;
44 |
45 | }
46 |
47 | float pMarkList[] = {0.0,0.5000,1.0000,1.5000,2.0000,5.0000,10.0000,20.0000,30.0000,40.0000,50.0000 };
48 | float markCarry = 0.0f;
49 | void NetQueue::insert(float time,
50 | void* rtpPacket,
51 | unsigned int ssrc,
52 | int size,
53 | unsigned short seqNr,
54 | bool isCe,
55 | bool isMark,
56 | unsigned int timeStamp) {
57 | int prevHead = head;
58 | if (false && nItems > 1000)
59 | return;
60 | nItems++;
61 | head++; if (head == NetQueueSize) head = 0;
62 | items[head]->used = true;
63 | items[head]->packet = rtpPacket;
64 | items[head]->ssrc = ssrc;
65 | items[head]->size = size;
66 | items[head]->seqNr = seqNr;
67 | items[head]->timeStamp = timeStamp;
68 | float tmp = 0;
69 | if (rate > 0)
70 | tmp += size * 8 / rate;
71 | sendTime = std::max(sendTime, time) + tmp;
72 | items[head]->tRelease = sendTime + delay + jitter * (rand() / float(RAND_MAX));;
73 | items[head]->tQueue = time;
74 | if (rate > 0) {
75 | float qDelay = items[tail]->tRelease - items[tail]->tQueue;
76 | if (isL4s) {
77 | int ix = int(time / 60.0f);
78 | //float pMark = pMarkList[ix] / 100.0;
79 | float pMark = std::max(0.0f, std::min(1.0f, (qDelay - l4sThLo) / (l4sThHi - l4sThLo)));
80 | markCarry += pMark;
81 | //if (markCarry >= 1.0f) {
82 | if ((rand() % 1000) / 1000.0 < pMark) {
83 | markCarry -= 1.0f;
84 | isCe = true;
85 | }
86 | } else {
87 | if (qDelay > 0.03) {
88 | isCe = true;
89 | }
90 | }
91 | }
92 |
93 |
94 | items[head]->isCe = isCe;
95 | items[head]->isMark = isMark;
96 | }
97 |
98 | bool NetQueue::extract(float time,
99 | void* rtpPacket,
100 | unsigned int& ssrc,
101 | int& size,
102 | unsigned short& seqNr,
103 | bool& isCe,
104 | bool& isMark,
105 | unsigned int& timeStamp) {
106 | if (items[tail]->used == false) {
107 | lastQueueLow = time;
108 | return false;
109 | }
110 | else {
111 | if (time >= items[tail]->tRelease) {
112 | // items[tail]->tReleaseExt = time;
113 | rtpPacket = items[tail]->packet;
114 | seqNr = items[tail]->seqNr;
115 | timeStamp = items[tail]->timeStamp;
116 | ssrc = items[tail]->ssrc;
117 | size = items[tail]->size;
118 | isCe = items[tail]->isCe;
119 | isMark = items[tail]->isMark;
120 |
121 | items[tail]->used = false;
122 |
123 | bytesTx += size;
124 | tail++; if (tail == NetQueueSize) tail = 0;
125 | nItems = std::max(0, nItems - 1);
126 |
127 | return true;
128 | }
129 | return false;
130 | }
131 | }
132 |
133 |
134 |
135 |
136 | int NetQueue::sizeOfQueue() {
137 | int size = 0;
138 | for (int n=0; n < NetQueueSize; n++) {
139 | if (items[n]->used)
140 | size += items[n]->size;
141 | }
142 | return size;
143 | }
144 |
145 | const float rateUpdateT = 0.05f;
146 |
147 | void NetQueue::updateRate(float time) {
148 | if (time - lastRateUpdateT >= rateUpdateT && rate > 0) {
149 | float dT = time - lastRateUpdateT;
150 | float rateT = bytesTx * 8 / dT;
151 | bytesTx = 0;
152 | lastRateUpdateT = time;
153 | float rateFrac = rateT / rate - 0.9f;
154 | rateFrac /= 0.2f;
155 | rateFrac = std::max(0.0f, std::min(1.0f, rateFrac));
156 | pDrop = 0.9f*pDrop + 0.1f*rateFrac;
157 | pDrop = std::min(1.0f, std::max(0.0f, pDrop));
158 | prevRateFrac = rateFrac;
159 | if (false && pDrop > 0)
160 | cerr << pDrop << endl;;
161 | }
162 | }
163 |
--------------------------------------------------------------------------------
/code/NetQueue.h:
--------------------------------------------------------------------------------
1 | #ifndef NET_QUEUE
2 | #define NET_QUEUE
3 |
4 |
5 | class NetQueueItem {
6 | public:
7 | NetQueueItem();
8 | void* packet;
9 | unsigned int ssrc;
10 | int size;
11 | unsigned short seqNr;
12 | unsigned int timeStamp;
13 | float tRelease;
14 | // float tReleaseExt;
15 | float tQueue;
16 | bool isCe;
17 | bool isMark;
18 | bool used;
19 | };
20 | const int NetQueueSize = 10000;
21 | class NetQueue {
22 | public:
23 |
24 | NetQueue(float delay, float rate=0.0f, float jitter=0.0f, bool isL4s = false);
25 |
26 | void insert(float time,
27 | void *rtpPacket,
28 | unsigned int ssrc,
29 | int size,
30 | unsigned short seqNr,
31 | bool isCe,
32 | bool isMark,
33 | unsigned int timeStamp);
34 | bool extract(float time,
35 | void *rtpPacket,
36 | unsigned int &ssrc,
37 | int& size,
38 | unsigned short &seqNr,
39 | bool &isCe,
40 | bool &isMark,
41 | unsigned int& timeStamp);
42 | int sizeOfQueue();
43 |
44 | void updateRate(float time);
45 |
46 | NetQueueItem *items[NetQueueSize];
47 | int head; // Pointer to last inserted item
48 | int tail; // Pointer to the oldest item
49 | int nItems;
50 | float delay;
51 | float rate;
52 | float jitter;
53 | float sendTime;
54 | // float nextTx;
55 | float lastQueueLow;
56 | bool isL4s;
57 | int bytesTx;
58 | float lastRateUpdateT;
59 | float pDrop;
60 | float prevRateFrac;
61 | float tQueueAvg;
62 | };
63 |
64 | #endif
--------------------------------------------------------------------------------
/code/OooQueue.cpp:
--------------------------------------------------------------------------------
1 | #include "OooQueue.h"
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | using namespace std;
9 | /*
10 | * Implements a simple RTP packet queue
11 | */
12 |
13 | OooQueueItem::OooQueueItem() {
14 | packet = 0;
15 | used = false;
16 | size = 0;
17 | seqNr = 0;
18 | tRelease = 0.0;
19 | tQueue = 0.0;
20 | }
21 |
22 | OooQueue::OooQueue(float maxDelay_) {
23 | for (int n=0; n < OooQueueSize; n++) {
24 | items[n] = new OooQueueItem();
25 | }
26 | item = new OooQueueItem();
27 | nItems = 0;
28 | maxDelay = maxDelay_;
29 | prevTRelease = 0;
30 | nDelayed;
31 | }
32 |
33 | bool OooQueue::insert(float time,
34 | void* rtpPacket,
35 | unsigned int ssrc,
36 | int size,
37 | unsigned short seqNr,
38 | bool isCe,
39 | bool isMark,
40 | unsigned int timeStamp) {
41 |
42 | float delay = maxDelay; //rand()* maxDelay / RAND_MAX;
43 | //if (delay > 0.0001f) {
44 | if (maxDelay > 0.0f && (seqNr % 2048 < 20) && seqNr > 100 && seqNr % 1 == 0) {//}&& seqNr < 3000) {
45 | /*
46 | * put in queue to apply OOO delay
47 | */
48 | int ix = -1;
49 | for (int n = 0; n < OooQueueSize; n++) {
50 | if (!items[n]->used) {
51 | ix = n;
52 | continue;
53 | }
54 | }
55 | if (ix == -1) {
56 | cerr << "Too many OOO packets, increase OooQueueSize" << endl;
57 | exit(-1);
58 | }
59 | OooQueueItem* tmp = item;
60 | tmp->tRelease = time;
61 | tmp = items[ix];
62 | //cerr << time << " " << seqNr << endl;
63 | if (false || nDelayed == 0) {
64 | tmp->tRelease = time + delay;
65 | }
66 | else {
67 | //tmp->tRelease = time + maxDelay;
68 | tmp->tRelease = prevTRelease - 0.0001;
69 | }
70 | prevTRelease = tmp->tRelease;
71 | tmp->used = true;
72 | tmp->packet = rtpPacket;
73 | tmp->ssrc = ssrc;
74 | tmp->size = size;
75 | tmp->seqNr = seqNr;
76 | tmp->timeStamp = timeStamp;
77 | tmp->isCe = isCe;
78 | tmp->isMark = isMark;
79 | tmp->tQueue = time;
80 | nDelayed++;
81 | return true;
82 | }
83 | nDelayed = 0;
84 |
85 | return false;
86 | }
87 |
88 | bool OooQueue::extract(float time,
89 | void* rtpPacket,
90 | unsigned int& ssrc,
91 | int& size,
92 | unsigned short& seqNr,
93 | bool& isCe,
94 | bool& isMark,
95 | unsigned int& timeStamp) {
96 |
97 | OooQueueItem* tmp = item;
98 | for (int n = 0; n < OooQueueSize; n++) {
99 | if (items[n]->used && items[n]->tRelease < time) {
100 | tmp = items[n];
101 | }
102 | }
103 |
104 | if (tmp->used) {
105 | rtpPacket = tmp->packet;
106 | seqNr = tmp->seqNr;
107 | timeStamp = tmp->timeStamp;
108 | ssrc = tmp->ssrc;
109 | size = tmp->size;
110 | isCe = tmp->isCe;
111 | isMark = tmp->isMark;
112 | tmp->used = false;
113 |
114 | return true;
115 | } else {
116 | return false;
117 | }
118 |
119 | }
120 |
--------------------------------------------------------------------------------
/code/OooQueue.h:
--------------------------------------------------------------------------------
1 | #ifndef OOO_QUEUE
2 | #define OOO_QUEUE
3 |
4 |
5 | class OooQueueItem {
6 | public:
7 | OooQueueItem();
8 | void* packet;
9 | unsigned int ssrc;
10 | int size;
11 | unsigned short seqNr;
12 | unsigned long timeStamp;
13 | float tRelease;
14 | float tQueue;
15 | bool isCe;
16 | bool isMark;
17 | bool used;
18 | };
19 | const int OooQueueSize = 512;
20 | class OooQueue {
21 | public:
22 |
23 | OooQueue(float maxDelay);
24 |
25 | /*
26 | * Return true of packet is delayed, otherwise false
27 | */
28 | bool insert(float time,
29 | void *rtpPacket,
30 | unsigned int ssrc,
31 | int size,
32 | unsigned short seqNr,
33 | bool isCe,
34 | bool isMark,
35 | unsigned int timeStamp);
36 | bool extract(float time,
37 | void* rtpPacket,
38 | unsigned int& ssrc,
39 | int& size,
40 | unsigned short& seqNr,
41 | bool& isCe,
42 | bool& isMark,
43 | unsigned int& timeStamp);
44 |
45 | OooQueueItem *items[OooQueueSize];
46 | OooQueueItem *item;
47 | int nItems;
48 | float maxDelay;
49 | int nDelayed;
50 | float prevTRelease;
51 | };
52 |
53 | #endif
--------------------------------------------------------------------------------
/code/RtpQueue.cpp:
--------------------------------------------------------------------------------
1 | #include "RtpQueue.h"
2 | #include
3 | #include
4 | using namespace std;
5 | /*
6 | * Implements a simple RTP packet queue
7 | */
8 |
9 | RtpQueueItem::RtpQueueItem() {
10 | used = false;
11 | size = 0;
12 | seqNr = 0;
13 | timeStamp = 0;
14 | }
15 |
16 |
17 | RtpQueue::RtpQueue() {
18 | for (int n = 0; n < kRtpQueueSize; n++) {
19 | items[n] = new RtpQueueItem();
20 | }
21 | head = -1;
22 | tail = 0;
23 | nItems = 0;
24 | sizeOfLastFrame = 0;
25 | bytesInQueue_ = 0;
26 | sizeOfQueue_ = 0;
27 | sizeOfNextRtp_ = -1;
28 | }
29 |
30 | bool RtpQueue::push(void* rtpPacket, int size, uint32_t ssrc, unsigned short seqNr, bool isMark, float ts, uint32_t timeStamp) {
31 | std::unique_lock lock(queue_operation_mutex_);
32 | int ix = head + 1;
33 | if (ix == kRtpQueueSize) ix = 0;
34 | if (items[ix]->used) {
35 | /*
36 | * RTP queue is full, do a drop tail i.e ignore new RTP packets
37 | */
38 | return (false);
39 | }
40 | head = ix;
41 | items[head]->seqNr = seqNr;
42 | items[head]->timeStamp = timeStamp;
43 | items[head]->ssrc = ssrc;
44 | items[head]->size = size;
45 | items[head]->ts = ts;
46 | items[head]->isMark = isMark;
47 | items[head]->used = true;
48 | bytesInQueue_ += size;
49 | sizeOfQueue_ += 1;
50 | #ifndef IGNORE_PACKET
51 | items[head]->packet = rtpPacket;
52 | #endif
53 | computeSizeOfNextRtp();
54 | return (true);
55 | }
56 | bool RtpQueue::pop(void** rtpPacket, int& size, uint32_t& ssrc, unsigned short& seqNr, bool& isMark, uint32_t& timeStamp)
57 | {
58 | std::unique_lock lock(queue_operation_mutex_);
59 | if (items[tail]->used == false) {
60 | *rtpPacket = NULL;
61 | sizeOfNextRtp_ = -1;
62 | return false;
63 | }
64 | else {
65 | size = items[tail]->size;
66 |
67 | #ifndef IGNORE_PACKET
68 | * rtpPacket = items[tail]->packet;
69 | #endif
70 | seqNr = items[tail]->seqNr;
71 | timeStamp = items[tail]->timeStamp;
72 | ssrc = items[tail]->ssrc;
73 | isMark = items[tail]->isMark;
74 | items[tail]->used = false;
75 | /*
76 | * Thread safe update of tail to avoid that tail points outside
77 | * array, which can cause e.g RtpQueue::getDelay to give a
78 | * segmentation fault.
79 | * This should not really be needed because
80 | * we use mutex to make the pop function atomic
81 | */
82 | if (tail == kRtpQueueSize - 1)
83 | tail = 0;
84 | else
85 | tail++;
86 | bytesInQueue_ -= size;
87 | sizeOfQueue_ -= 1;
88 | computeSizeOfNextRtp();
89 | return true;
90 | }
91 | }
92 |
93 | void RtpQueue::computeSizeOfNextRtp() {
94 | if (!items[tail]->used) {
95 | sizeOfNextRtp_ = -1;
96 | }
97 | else {
98 | sizeOfNextRtp_ = items[tail]->size;
99 | }
100 | }
101 |
102 | int RtpQueue::sizeOfNextRtp() {
103 | return sizeOfNextRtp_;
104 | }
105 |
106 | int RtpQueue::seqNrOfNextRtp() {
107 | if (!items[tail]->used) {
108 | return -1;
109 | }
110 | else {
111 | return items[tail]->seqNr;
112 | }
113 | }
114 |
115 | int RtpQueue::seqNrOfLastRtp() {
116 | if (!items[head]->used) {
117 | return -1;
118 | }
119 | else {
120 | return items[head]->seqNr;
121 | }
122 | }
123 |
124 | int RtpQueue::bytesInQueue() {
125 | return bytesInQueue_;
126 | }
127 |
128 | int RtpQueue::sizeOfQueue() {
129 | return sizeOfQueue_;
130 | }
131 |
132 | float RtpQueue::getDelay(float currTs) {
133 | if (items[tail]->used == false) {
134 | return 0;
135 | }
136 | else {
137 | return currTs - items[tail]->ts;
138 | }
139 | }
140 |
141 | bool RtpQueue::sendPacket(void** rtpPacket, int& size, uint32_t& ssrc, unsigned short& seqNr, bool& isMark, uint32_t& timeStamp) {
142 | if (sizeOfQueue() > 0) {
143 | pop(rtpPacket, size, ssrc, seqNr, isMark, timeStamp);
144 | return true;
145 | }
146 | return false;
147 | }
148 |
149 | #ifndef IGNORE_PACKET
150 | extern void packet_free(void* buf, uint32_t ssrc);
151 | #endif
152 | int RtpQueue::clear() {
153 | uint16_t seqNr;
154 | uint32_t timeStamp;
155 | uint32_t ssrc;
156 | int freed = 0;
157 | int size;
158 | void* buf;
159 | while (sizeOfQueue() > 0) {
160 | bool isMark;
161 | pop(&buf, size, ssrc, seqNr, isMark, timeStamp);
162 | if (buf != NULL) {
163 | freed++;
164 | #ifndef IGNORE_PACKET
165 | packet_free(buf, ssrc);
166 | #endif
167 | }
168 | }
169 | return (freed);
170 | }
171 |
--------------------------------------------------------------------------------
/code/RtpQueue.h:
--------------------------------------------------------------------------------
1 | #ifndef RTP_QUEUE
2 | #define RTP_QUEUE
3 |
4 | #include
5 | #include
6 | /*
7 | * Implements a simple RTP packet queue, one RTP queue
8 | * per stream {SSRC,PT}
9 | */
10 |
11 | class RtpQueueIface {
12 | public:
13 | virtual int clear() = 0;
14 | virtual int sizeOfNextRtp() = 0;
15 | virtual int seqNrOfNextRtp() = 0;
16 | virtual int seqNrOfLastRtp() = 0;
17 | virtual int bytesInQueue() = 0; // Number of bytes in queue
18 | virtual int sizeOfQueue() = 0; // Number of items in queue
19 | virtual float getDelay(float currTs) = 0;
20 | virtual int getSizeOfLastFrame() = 0;
21 | };
22 |
23 | class RtpQueueItem {
24 | public:
25 | RtpQueueItem();
26 | void* packet;
27 | int size;
28 | uint32_t ssrc;
29 | unsigned short seqNr;
30 | unsigned long timeStamp;
31 | float ts;
32 | bool isMark;
33 | bool used;
34 | };
35 |
36 | const int kRtpQueueSize = 1024;
37 | class RtpQueue : public RtpQueueIface {
38 | public:
39 | RtpQueue();
40 |
41 | bool push(void* rtpPacket, int size, uint32_t ssrc, unsigned short seqNr, bool isMark, float ts, uint32_t timeStamp);
42 | bool pop(void** rtpPacket, int& size, uint32_t& ssrc, unsigned short& seqNr, bool& isMark, uint32_t& timeStamp);
43 | int sizeOfNextRtp();
44 | int seqNrOfNextRtp();
45 | int seqNrOfLastRtp();
46 | int bytesInQueue(); // Number of bytes in queue
47 | int sizeOfQueue(); // Number of items in queue
48 | float getDelay(float currTs);
49 | bool sendPacket(void** rtpPacket, int& size, uint32_t& ssrc, unsigned short& seqNr, bool& isMark, uint32_t& timeStamp);
50 | int clear();
51 | int getSizeOfLastFrame() { return sizeOfLastFrame; };
52 | void setSizeOfLastFrame(int sz) { sizeOfLastFrame = sz; };
53 | void computeSizeOfNextRtp();
54 |
55 | RtpQueueItem* items[kRtpQueueSize];
56 | int head; // Pointer to last inserted item
57 | int tail; // Pointer to the oldest item
58 | int nItems;
59 | int sizeOfLastFrame;
60 |
61 | int bytesInQueue_;
62 | int sizeOfQueue_;
63 | int sizeOfNextRtp_;
64 | std::mutex queue_operation_mutex_;
65 | };
66 |
67 | #endif
68 |
--------------------------------------------------------------------------------
/code/ScreamRx.h:
--------------------------------------------------------------------------------
1 | #ifndef SCREAM_RX
2 | #define SCREAM_RX
3 | #include
4 | #include
5 | const int kReportedRtpPackets = 32;
6 | const int kRxHistorySize = 512;
7 |
8 | /*
9 | * This module implements the receiver side of SCReAM.
10 | * As SCReAM is a sender based congestion control, the receiver side is
11 | * actually dumber than dumb. In essense the only thing that it does is to
12 | * + Record receive time stamps and RTP sequence numbers for incoming RTP packets
13 | * + Generate RTCP feedback elements
14 | * + Calculate an appropriate RTCP feedback interval
15 | * See https://github.com/EricssonResearch/scream/blob/master/SCReAM-description.pptx
16 | * for details on how it is integrated in audio/video platforms.
17 | * A full implementation needs the additional code for
18 | * + Other obvious stuff such as RTP payload depacketizer, video+audio deoders, rendering, dejitterbuffers
19 | * It is recommended that RTCP feedback for multiple streams are bundled in one RTCP packet.
20 | * However as low bitrate media (e.g audio) requires a lower feedback rate than high bitrate media (e.g video)
21 | * it is possible to include RTCP feedback for the audio stream more seldom. The code for this is T.B.D
22 | *
23 | * Internal time is represented as the mid 32 bits of the NTP timestamp (see RFC5905)
24 | * This means that the high order 16 bits is time in seconds and the low order 16 bits
25 | * is the fraction. The NTP time stamp is thus in Q16 i.e 1.0sec is represented
26 | * by the value 65536.
27 | * All internal time is measured in NTP time, this is done to avoid wraparound issues
28 | * that can otherwise occur every 18 hour or so
29 | */
30 |
31 | class ScreamRx {
32 | public:
33 | ScreamRx(uint32_t ssrc, int ackDiff = -1, int nReportedRtpPackets = kReportedRtpPackets); // SSRC of this RTCP session
34 | ~ScreamRx();
35 |
36 | /*
37 | * One instance is created for each source SSRC
38 | */
39 | class Stream {
40 | public:
41 | Stream(uint32_t ssrc);
42 |
43 | bool isMatch(uint32_t ssrc_) { return ssrc == ssrc_; };
44 |
45 | bool checkIfFlushAck(uint32_t ackDiff);
46 |
47 | /*
48 | * Receive RTP packet
49 | */
50 | void receive(uint32_t time_ntp,
51 | void* rtpPacket,
52 | int size,
53 | uint16_t seqNr,
54 | bool isEcnCe,
55 | uint8_t ceBits,
56 | bool isMarker,
57 | uint32_t timeStamp);
58 |
59 | /*
60 | * Get SCReAM standardized RTCP feedback
61 | * return FALSE if no pending feedback available
62 | */
63 | bool getStandardizedFeedback(uint32_t time_ntp,
64 | unsigned char* buf,
65 | int& size);
66 |
67 | /*
68 | * Get SCReAM standardized RTCP feedback for OOO RTP packets, i.e packets that
69 | * are received more than kReportedRtpPackets behind highestSeqNrTx
70 | * return FALSE if no pending feedback available
71 | */
72 | bool getStandardizedFeedbackOoo(uint32_t time_ntp,
73 | unsigned char* buf,
74 | int& size);
75 |
76 |
77 | uint32_t ssrc; // SSRC of stream (source SSRC)
78 | uint32_t receiveTimestamp; // Wall clock time
79 | uint16_t highestSeqNr; // Highest received sequence number
80 | uint16_t highestSeqNrTx; // Highest fed back sequence number
81 | uint16_t oooLowSeqNr; // Lowest OOO RTP received sequence number
82 | int numOooDetected; // Number of OOO RTP packets
83 |
84 |
85 | uint8_t ceBitsHist[kRxHistorySize]; // Vector of CE bits for last
86 | // received RTP packets
87 | uint32_t rxTimeHist[kRxHistorySize]; // Receive time for last
88 | // received RTP packets
89 | uint16_t seqNrHist[kRxHistorySize]; // Seq Nr of last received
90 | // received RTP packets
91 | bool isOooHist[kRxHistorySize]; // Packet is received OOO
92 | uint32_t lastFeedbackT_ntp; // Last time feedback transmitted for
93 | // this SSRC
94 | int nRtpSinceLastRtcp; // Number of RTP packets since last transmitted RTCP
95 |
96 | bool firstReceived;
97 |
98 | int nReportedRtpPackets;
99 |
100 | bool doFlush;
101 | };
102 |
103 | /*
104 | * Check to ensure that ACKs can cover also large holes in
105 | * in the received sequence number space. These cases can frequently occur when
106 | * SCReAM is used in frame discard mode i.e. when real video rate control is
107 | * not possible
108 | */
109 | bool checkIfFlushAck();
110 |
111 | /*
112 | * At least one stream has received OOO RTP packets, this necessitates transmission of
113 | * extra RTCP packets to cover the hole
114 | */
115 | bool isOooDetected();
116 |
117 | /*
118 | * Function is called each time an RTP packet is received
119 | */
120 | void receive(uint32_t time_ntp,
121 | void* rtpPacket,
122 | uint32_t ssrc,
123 | int size,
124 | uint16_t seqNr,
125 | uint8_t ceBits,
126 | bool isMarker,
127 | uint32_t timeStamp);
128 |
129 | /*
130 | * Return TRUE if an RTP packet has been received and there is
131 | * pending feedback
132 | */
133 | bool isFeedback(uint32_t time_ntp);
134 |
135 | /*
136 | * Return RTCP feedback interval (Q16)
137 | */
138 | uint32_t getRtcpFbInterval();
139 |
140 | /*
141 | * Create standardized feedback according to
142 | * https://datatracker.ietf.org/doc/rfc8888/
143 | * It is up to the wrapper application to prepend this RTCP
144 | * with SR or RR when needed
145 | */
146 | bool createStandardizedFeedback(uint32_t time_ntp, bool isMark, unsigned char* buf, int& size);
147 |
148 | /*
149 | * Create standardized feedback according to
150 | * https://datatracker.ietf.org/doc/rfc8888/ ...
151 | * That catches up with OOO RTP packets
152 | * It is up to the wrapper application to prepend this RTCP
153 | * with SR or RR when needed
154 | */
155 | bool createStandardizedFeedbackOoo(uint32_t time_ntp, bool isMark, unsigned char* buf, int& size);
156 |
157 | /*
158 | * Get last feedback transmission time in NTP domain (Q16)
159 | */
160 | uint32_t getLastFeedbackT() { return lastFeedbackT_ntp; };
161 |
162 | uint32_t lastFeedbackT_ntp;
163 | int bytesReceived;
164 | uint32_t lastRateComputeT_ntp;
165 | float averageReceivedRate;
166 | uint32_t rtcpFbInterval_ntp;
167 | uint32_t ssrc;
168 |
169 | //int getIx(uint32_t ssrc);
170 | //int ix;
171 | int ackDiff;
172 |
173 | int nReportedRtpPackets;
174 | /*
175 | * Variables for multiple steams handling
176 | */
177 | std::list streams;
178 | };
179 |
180 | #endif
181 |
--------------------------------------------------------------------------------
/code/ScreamTx.cpp:
--------------------------------------------------------------------------------
1 | #include "ScreamTx.h"
2 | #include
3 |
4 | static const uint32_t kMinTimeForMinMaxStatistics_ntp = 5*65536;
5 |
6 | ScreamTx::ScreamTx() {
7 | statistics = new Statistics(this);
8 | }
9 |
10 | ScreamTx::~ScreamTx() {
11 | delete statistics;
12 | }
13 |
14 | ScreamTx::Statistics::Statistics(ScreamTx* parent_) {
15 | parent = parent_;
16 | sumRateTx = 0.0f;
17 | sumRateLost = 0.0f;
18 | sumRateCe = 0.0f;
19 | avgRateTx = 0.0f;
20 | minRate = 1e9f;
21 | maxRate = 0.0f;
22 | avgRtt = 0.0f;
23 | sumRtt = 0.0f;
24 | minRtt = 10.0f;
25 | maxRtt = 0.0f;
26 | avgQueueDelay = 0.0f;
27 | maxQueueDelay = 0.0f;
28 | lossRate = 0.0f;
29 | lossRateLong = 0.0f;
30 | ceRate = 0.0f;
31 | ceRateLong = 0.0f;
32 | rateLostAcc = 0.0f;
33 | rateCeAcc = 0.0f;
34 | rateLostN = 0;
35 | nStatisticsItems++;
36 | n00 = 0;
37 | n10 = 0;
38 | n01 = 0;
39 | n11 = 0;
40 | nEcn = 0;
41 | for (int n = 0; n < kLossRateHistSize; n++) {
42 | lossRateHist[n] = 0.0f;
43 | ceRateHist[n] = 0.0f;
44 | }
45 | lossRateHistPtr = 0;
46 | }
47 |
48 | void ScreamTx::Statistics::add(uint32_t time_ntp, float rateTx, float rateLost, float rateCe, float rtt, float queueDelay) {
49 | nStatisticsItems++;
50 | const float alpha = 0.98f;
51 | sumRateTx += rateTx;
52 | sumRateLost += rateLost;
53 | sumRateCe += rateCe;
54 | sumRtt += rtt;
55 | minRtt = std::min(minRtt,rtt);
56 | maxRtt = std::max(maxRtt,rtt);
57 | sumQueueDelay += queueDelay;
58 | maxQueueDelay = std::max(maxQueueDelay, queueDelay);
59 | if (time_ntp > kMinTimeForMinMaxStatistics_ntp) {
60 | minRate = std::min(minRate, rateTx);
61 | maxRate = std::max(maxRate, rateTx);
62 | }
63 | if (avgRateTx == 0.0f) {
64 | avgRateTx = rateTx;
65 | avgRtt = rtt;
66 | avgQueueDelay = queueDelay;
67 | }
68 | else {
69 | avgRateTx = alpha * avgRateTx + (1.0f - alpha) * rateTx;
70 | rateLostAcc += rateLost;
71 | rateCeAcc += rateCe;
72 | rateLostN++;
73 | if (rateLostN == 10) {
74 | rateLostAcc /= 10;
75 | rateCeAcc /= 10;
76 | rateLostN = 0;
77 | float lossRate = 0.0f;
78 | float ceRate = 0.0f;
79 | if (rateTx > 0) {
80 | lossRate = rateLostAcc / rateTx * 100.0f;
81 | ceRate = rateCeAcc / rateTx * 100.0f;
82 | }
83 | lossRateHist[lossRateHistPtr] = lossRate;
84 | ceRateHist[lossRateHistPtr] = ceRate;
85 | lossRateHistPtr = (lossRateHistPtr + 1) % kLossRateHistSize;
86 | }
87 | avgRtt = alpha * avgRtt + (1.0f - alpha) * rtt;
88 | avgQueueDelay = alpha * avgQueueDelay + (1.0f - alpha) * queueDelay;
89 | }
90 | lossRate = 0.0f;
91 | ceRate = 0.0f;
92 | for (int n = 0; n < kLossRateHistSize; n++) {
93 | lossRate += lossRateHist[n];
94 | ceRate += ceRateHist[n];
95 | }
96 | lossRate /= kLossRateHistSize;
97 | ceRate /= kLossRateHistSize;
98 | lossRateLong = 0.0f;
99 | ceRateLong = 0.0f;
100 | if (sumRateTx > 100000.0f) {
101 | lossRateLong = sumRateLost / sumRateTx * 100.0f;
102 | ceRateLong = sumRateCe / sumRateTx * 100.0f;
103 | }
104 | }
105 |
106 | void ScreamTx::Statistics::addEcn(uint8_t ecn) {
107 | nEcn++;
108 | switch (ecn) {
109 | case 0x00:
110 | n00++;
111 | break;
112 | case 0x02:
113 | n10++;
114 | break;
115 | case 0x01:
116 | n01++;
117 | break;
118 | case 0x03:
119 | n11++;
120 | break;
121 | default:
122 | break;
123 | }
124 | }
125 |
126 | void ScreamTx::Statistics::printFinalSummary() {
127 | printf("\n======================== Summary ==========================\n");
128 | printf(" Bitrate min/max/avg [kbps] : %5.0f/%5.0f/%5.0f\n",minRate/1000.0f,maxRate/1000.0f,
129 | sumRateTx/nStatisticsItems/1000.0f);
130 | printf(" RTT min/max/avg [s] : %2.3f/%2.3f/%2.3f\n",minRtt,maxRtt,sumRtt/nStatisticsItems);
131 | printf(" Queue delay max/avg [s] : %2.3f/%2.3f\n",maxQueueDelay,sumQueueDelay/nStatisticsItems);
132 | printf(" Packet loss avg [%%] : %4.3f\n", lossRateLong);
133 | int tmp = std::max(1, nEcn);
134 | printf(" ECN/L4S NotECT/ECT(0)/ECT(1)/CE [%%] : %4.1f/%4.1f/%4.1f/%4.1f\n",
135 | 100.0f * float(n00) / tmp,
136 | 100.0f * float(n10) / tmp,
137 | 100.0f * float(n01) / tmp,
138 | 100.0f * float(n11) / tmp);
139 | printf("===========================================================\n");
140 | }
141 |
142 | void ScreamTx::Statistics::getSummary(float time, char s[]) {
143 | int tmp = std::max(1, nEcn);
144 | sprintf(s, "%s summary %5.1f Transmit rate = %5.0fkbps, PLR = %5.2f%%(%5.2f%%), CE = %5.2f%%(%5.2f%%)[%4.1f%%, %4.1f%%, %4.1f%%, %4.1f%%], RTT = %5.3fs, Queue delay = %5.3fs",
145 | parent->logTag,
146 | time,
147 | avgRateTx / 1000.0f,
148 | lossRate,
149 | lossRateLong,
150 | ceRate,
151 | ceRateLong,
152 | 100.0f * float(n00) / tmp,
153 | 100.0f * float(n10) / tmp,
154 | 100.0f * float(n01) / tmp,
155 | 100.0f * float(n11) / tmp,
156 | avgRtt,
157 | avgQueueDelay);
158 | }
159 |
160 | float ScreamTx::Statistics::getStatisticsItem(StatisticsItem item) {
161 | switch (item) {
162 | case AVG_RATE:
163 | return avgRateTx;
164 | break;
165 | case LOSS_RATE:
166 | return lossRate;
167 | break;
168 | case LOSS_RATE_LONG:
169 | return lossRateLong;
170 | break;
171 | case CE_RATE:
172 | return ceRate;
173 | break;
174 | case CE_RATE_LONG:
175 | return ceRateLong;
176 | break;
177 | case AVG_RTT:
178 | return avgRtt;
179 | break;
180 | case AVG_QUEUE_DELAY:
181 | return avgQueueDelay;
182 | break;
183 | }
184 | return 0.0f;
185 | }
186 |
187 | void ScreamTx::getStatistics(float time, char* s) {
188 | statistics->getSummary(time, s);
189 | }
190 |
191 | float ScreamTx::getStatisticsItem(StatisticsItem item) {
192 | return statistics->getStatisticsItem(item);
193 | }
194 |
195 | void ScreamTx::printFinalSummary() {
196 | statistics->printFinalSummary();
197 | }
198 |
199 |
--------------------------------------------------------------------------------
/code/TxList.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricssonResearch/scream/5d5e4ca2c41ad62875314e5e8d2571efd58aad6a/code/TxList.h
--------------------------------------------------------------------------------
/code/VideoEnc.cpp:
--------------------------------------------------------------------------------
1 | #include "VideoEnc.h"
2 | #include "RtpQueue.h"
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | using namespace std;
10 |
11 | static const int kRtpOverHead = 12;
12 |
13 | uint32_t SSRC = 1;
14 | VideoEnc::VideoEnc(RtpQueue* rtpQueue_, float frameRate_, char *fname, int ixOffset_, float sluggishness_) {
15 | rtpQueue = rtpQueue_;
16 | frameRate = frameRate_;
17 | ix = ixOffset_;
18 | nFrames = 0;
19 | seqNr = 0;
20 | timeStamp = 0;
21 | nominalBitrate = 0.0;
22 | sluggishness = sluggishness_;
23 | FILE *fp = fopen(fname,"r");
24 | char s[100];
25 | float sum = 0.0;
26 | bytes = 0.0f;
27 | while (fgets(s,99,fp)) {
28 | if (nFrames < MAX_FRAMES - 1) {
29 | float x = atof(s);
30 | frameSize[nFrames] = x;
31 | nFrames++;
32 | sum += x;
33 | }
34 | }
35 | float t = nFrames / frameRate;
36 | nominalBitrate = sum * 8 / t;
37 | fclose(fp);
38 | }
39 |
40 | void VideoEnc::setTargetBitrate(float targetBitrate_) {
41 | targetBitrate = targetBitrate_;
42 | }
43 |
44 | int VideoEnc::encode(float time) {
45 |
46 | int rtpBytes = 0;
47 | char rtpPacket[2000];
48 | float tmp = (int)(frameSize[ix] / nominalBitrate * targetBitrate);
49 | if (bytes > 0)
50 | bytes = bytes * (sluggishness)+(1.0 - sluggishness) * tmp;
51 | else
52 | bytes = tmp;
53 |
54 | int tmp2 = (int) bytes;
55 | //nominalBitrate = 0.95*nominalBitrate + 0.05*frameSize[ix] * frameRate * 8;
56 | ix++; if (ix == nFrames) ix = 0;
57 | while (tmp2 > 0) {
58 | int rtpSize = std::min(mss, tmp2);
59 | bool isMarker = rtpSize < mss;
60 | tmp2 -= rtpSize;
61 | rtpSize += kRtpOverHead;
62 | rtpBytes += rtpSize;
63 | rtpQueue->push(rtpPacket, rtpSize, SSRC, seqNr, isMarker, time, timeStamp);
64 | seqNr++;
65 | timeStamp = (unsigned long)(time * 90000);
66 | }
67 | rtpQueue->setSizeOfLastFrame(rtpBytes);
68 | return rtpBytes;
69 | }
70 |
71 |
--------------------------------------------------------------------------------
/code/VideoEnc.h:
--------------------------------------------------------------------------------
1 | #ifndef VIDEO_ENC
2 | #define VIDEO_ENC
3 |
4 | class RtpQueue;
5 | #define MAX_FRAMES 10000
6 | class VideoEnc {
7 | public:
8 | VideoEnc(RtpQueue* rtpQueue, float frameRate, char *fname, int ixOffset=0, float sluggishness = 0.0);
9 |
10 | int encode(float time);
11 |
12 | void setTargetBitrate(float targetBitrate);
13 |
14 | void setMss(int mss_) {
15 | mss = mss_;
16 | }
17 |
18 | RtpQueue* rtpQueue;
19 | float frameSize[MAX_FRAMES];
20 | int nFrames;
21 | float targetBitrate;
22 | float frameRate;
23 | float nominalBitrate;
24 | unsigned int seqNr;
25 | unsigned long timeStamp;
26 | int ix;
27 | int mss;
28 |
29 | float sluggishness;
30 | float bytes;
31 | };
32 |
33 |
34 | #endif
--------------------------------------------------------------------------------
/code/scream_01.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 | {995F8DF3-7BE9-4B48-89EA-4F64046D68C2}
15 | Win32Proj
16 | scream_01
17 | 10.0
18 |
19 |
20 |
21 | Application
22 | true
23 | Unicode
24 | v143
25 |
26 |
27 | Application
28 | false
29 | true
30 | Unicode
31 | v143
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | false
45 |
46 |
47 | false
48 |
49 |
50 |
51 | NotUsing
52 | Level3
53 | Disabled
54 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);IGNORE_PACKET
55 | %(AdditionalIncludeDirectories)
56 |
57 |
58 | Console
59 | true
60 | %(AdditionalLibraryDirectories)
61 | %(AdditionalDependencies);Ws2_32.lib
62 |
63 |
64 |
65 |
66 | Level3
67 | NotUsing
68 | MaxSpeed
69 | true
70 | true
71 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);IGNORE_PACKET
72 | %(AdditionalIncludeDirectories)
73 |
74 |
75 | Console
76 | true
77 | true
78 | true
79 | %(AdditionalLibraryDirectories)
80 | %(AdditionalDependencies);Ws2_32.lib
81 | true
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 |
109 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/code/scream_01.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/code/stdafx.cpp:
--------------------------------------------------------------------------------
1 | // stdafx.cpp : source file that includes just the standard includes
2 | // scream_01.pch will be the pre-compiled header
3 | // stdafx.obj will contain the pre-compiled type information
4 |
5 | #include "stdafx.h"
6 |
7 | // TODO: reference any additional headers you need in STDAFX.H
8 | // and not in this file
9 |
--------------------------------------------------------------------------------
/code/stdafx.h:
--------------------------------------------------------------------------------
1 | // stdafx.h : include file for standard system include files,
2 | // or project specific include files that are used frequently, but
3 | // are changed infrequently
4 | //
5 |
6 | #pragma once
7 |
8 | #ifdef _WIN32
9 | #include "targetver.h"
10 | #include
11 | #include
12 | #else
13 | #include "unistd.h" // for sleep
14 | #endif
15 |
16 | // TODO: reference additional headers your program requires here
17 | #include
18 | #include
19 | #include
20 | #include
21 |
22 |
--------------------------------------------------------------------------------
/code/targetver.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | // Including SDKDDKVer.h defines the highest available Windows platform.
4 |
5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
7 |
8 | #include
9 |
--------------------------------------------------------------------------------
/code/wrapper_lib/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # source files
2 |
3 | #set(CMAKE_VERBOSE_MAKEFILE ON)
4 |
5 | set(BUILD_SHARED_LIBS on)
6 |
7 | SET(HEADERS
8 | ../ScreamTx.h
9 | ../RtpQueue.h
10 | )
11 |
12 | SET(SRCS
13 | ../RtpQueue.cpp
14 | ../ScreamTx.cpp
15 | ../ScreamV2Tx.cpp
16 | ../ScreamV2TxStream.cpp
17 | screamtxbw_plugin_wrapper.cpp
18 | screamtx_plugin_wrapper.cpp
19 | )
20 |
21 | set(CMAKE_BUILD_TYPE Debug)
22 |
23 | if(BUILD_SHARED_LIBS)
24 | set(CMAKE_CXX_FLAGS " -DV2 -I.. ${CMAKE_CXX_FLAGS_INIT} ")
25 | add_library(scream SHARED ${SRCS})
26 |
27 | else()
28 |
29 | set(CMAKE_CXX_FLAGS " -DV2 -g -I .. ${CMAKE_CXX_FLAGS_INIT} -fPIC")
30 | add_library(scream STATIC ${SRCS})
31 | endif()
32 |
33 |
34 | INCLUDE_DIRECTORIES(
35 | ${screamIncludes}
36 | )
37 |
--------------------------------------------------------------------------------
/code/wrapper_lib/meson.build:
--------------------------------------------------------------------------------
1 | project('scream', 'cpp', version : '0.0.1', license : 'BSD')
2 | add_project_arguments('-DV2', language : 'cpp')
3 |
4 | cc = meson.get_compiler('cpp')
5 |
6 | is_window = target_machine.system() == 'windows'
7 | sources = [
8 | 'screamtx_plugin_wrapper.cpp',
9 | '../RtpQueue.cpp',
10 | '../ScreamTx.cpp',
11 | '../ScreamV2Tx.cpp',
12 | '../ScreamV2TxStream.cpp',
13 | ]
14 |
15 | incdir = include_directories('..')
16 |
17 | threads_dep = dependency('threads')
18 | winsock_dep = cc.find_library('ws2_32', required: is_window)
19 |
20 | library('scream',
21 | sources : sources,
22 | include_directories : incdir,
23 | dependencies : [threads_dep, winsock_dep],
24 | install : true
25 | )
26 |
--------------------------------------------------------------------------------
/gstscream/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 |
--------------------------------------------------------------------------------
/gstscream/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "gstscream"
3 | version = "0.6.0"
4 | authors = ["Jacob Teplitsky"]
5 | repository = "https://github.com/EricssonResearch/scream.git"
6 | license = "BSD 2-clause"
7 | edition = "2021"
8 | description = "Rust Gstscream Scream Plugin"
9 |
10 | [dependencies]
11 | gst = { package = "gstreamer", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git" }
12 | gst-base = { package = "gstreamer-base", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git" }
13 | gst-video = { package = "gstreamer-video", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git" }
14 | gst-sys = { package = "gstreamer-sys", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git" }
15 | gst-rtp = { package = "gstreamer-rtp", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git" }
16 |
17 | once_cell = "1.0"
18 | array-init = "0.1.1"
19 | hashbrown="0.9.0"
20 | lazy_static = "1.3.0"
21 | libc = "0.2.68"
22 | failure = "0.1"
23 | gtypes = "0.2.0"
24 | chrono = "0.4"
25 | clap = { version = "4.5.11", features=["env","derive"] }
26 |
27 | [lib]
28 | name = "gstscream"
29 | crate-type = ["cdylib", "rlib", "staticlib"]
30 | path = "src/lib.rs"
31 |
32 | [[bin]]
33 | name="scream_sender"
34 | path="src/sender.rs"
35 |
36 | [[bin]]
37 | name="scream_receiver"
38 | path="src/receiver.rs"
39 |
40 | [build-dependencies]
41 | gst-plugin-version-helper = { git = "https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git" }
42 |
43 | [features]
44 | screamrx-only = []
45 | ecn-enabled = []
46 | screamtxbw-enabled = []
47 |
48 | default = []
49 |
--------------------------------------------------------------------------------
/gstscream/README.md:
--------------------------------------------------------------------------------
1 | # Installation
2 |
3 | [rust](https://doc.rust-lang.org/book/ch01-01-installation.html#installing-rustup-on-linux-or-macos)
4 |
5 | [gstreamer](https://gstreamer.freedesktop.org/documentation/installing/on-linux.html?gi-language=c)
6 |
7 | # Building gstscream and sample applications
8 | Should be possible to build and run on Windows (not tested)
9 | However SCReAM BW can't be built for Windows.
10 | Therefore modify build.sh to remove --features screamtxbw-enabled
11 | ```bash
12 | ./scripts/build.sh
13 | ```
14 |
15 | # Environment Variables are set in script/env.sh
16 | ```bash
17 | export SENDER_STATS_TIMER=500 # default 1000 ms
18 | export SENDER_STATS_FILE_NAME="xxx.csv" # default sender_scream_stats.csv
19 | ```
20 | See script/env.sh to set
21 | ECN_ENABLED, USE_SCREAM, SENDER_IP, RECEIVER_IP, ENCODER, DECODER, ENC_ID
22 |
23 | # Tuning Linux system
24 | ```bash
25 | sudo ./scripts/sysctl.sh
26 | ```
27 | # Running remote rendering test applications
28 | ```bash
29 | # first window
30 | ./scripts/receiver.sh
31 | # second window
32 | ./scripts/sender.sh
33 | ```
34 | # Running remote rendering test applications with 3 video screams
35 | ```bash
36 | # first window
37 | ./scripts/receiver_3.sh
38 | # second window
39 | ./scripts/sender_3.sh
40 | ```
41 | # Running SCReAM BW test applications
42 | ```bash
43 | # first window
44 | ./scripts/receiver_bw.sh
45 | # second window
46 | ./scripts/sender_bw.sh
47 | ```
48 | # To use unattended machine:
49 | ```shell
50 | #ssh-1 window
51 | systemctl isolate multi-user.target
52 | sudo Xorg
53 |
54 | #ssh-2 window
55 | export DISPLAY=:0
56 | ./receiver_run.sh
57 | #ssh-3 window
58 | export DISPLAY=:0
59 | ./sender_run.sh
60 | ```
61 |
62 | # __Be aware of legal implications of using software build with gpl=enabled__
63 |
64 | # Modifying gstreamer to use L4S
65 | Based on patch [https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2717]
66 | ```bash
67 | cd scream/..
68 | git clone https://gitlab.freedesktop.org/gstreamer/gstreamer.git
69 | cd gstreamer
70 | meson setup --prefix=/path/to/install/prefix build
71 |
72 | # to build x264, you might want to add to meson setup
73 | -Dgst-plugins-ugly:x264=enabled -Dgpl=enabled
74 |
75 | meson compile -C build
76 | patch -p1 < scream/gstscream/udp_ecn_diff.txt
77 | meson compile -C build
78 | meson install -C build
79 | ```
80 | # Build and run with modified gstreamer
81 | ## Modify scripts/env.sh
82 | set ECN_ENABLED=1
83 | Make sure that MY_GST_INSTALL points to the correct install directory.
84 | ## Build
85 | ./scripts/build.sh
86 | ## Run
87 | Use receiver and sender scripts described earlier
88 | Receiver should print once "screamrx/imp.rs ecn-enabled"
89 | If export GST_DEBUG="screamrx:7" is set, the following trace log should be displayed:
90 | screamrx src/screamrx/imp.rs ..... ecn_ce 1
91 |
92 | # Issues
93 | [Issues with using tc](https://github.com/EricssonResearch/scream/issues/44#issuecomment-1112448356 )
94 |
95 | # Logging
96 | File `gstscream/src/sender_util.rs` provides an example of how to retrieve periodic statistics
97 | from the SCReAM library into a `.csv` file. Below is an explanation for some of the important
98 | fields:
99 |
100 | * `time-ns` Time in ns of getting log record.
101 | * `queueDelay` The estimated network queue delay, i.e time a packet is read from
102 | internal RTP queue and time a packer read by receiver screamrx element. It is "estimated"
103 | because the clocks on the sender and receiver sides are not synchronized. (In sec)
104 |
105 | * `queueDelayMax` The maximum value of `queueDelay` in seconds, which is reset after
106 | printing logs.
107 |
108 | * `queueDelayMin` The minimum value of `queueDelay` in seconds, which is reset after
109 | printing logs. Together, queueDelayXXX fields indicate size of jitter.
110 |
111 | * `rtpQueueDelay` The duration for which RTP packets are kept in the RTP queue.
112 | If `rtpQueueDelay` exceeds a hardcoded threshold the RTP queue
113 | is completely emptied. Number of cleared packets added to Counter packetetsRtpCleared
114 |
115 | * `acketsLost` Unacked packets outside window are considered lost. They might be received by receiver.
116 | Used to calculate "targetBitrate"
117 |
118 | * `rateRtp vs. rateTransmitted` `rateRtp` is the moving avr bitrate including RTP header
119 | of packet read by screamtx element, while `rateTransmitted` is the transmitted bitrate. These
120 | can differ if RTP packets are queued on the sender side. (In kbit/sec)
121 |
122 |
123 | * `rtpQueueBytes and rtpQueueSize` These represent bytes in the RTP queue and the number of packets,
124 | respectively, at the time of logging. Not average.
125 |
126 | * `targetBitrate` SCReAM recommended to encoder at the time of logging. Not avr.
127 |
128 | * `bytesInFlightLog` Max of bytesInFlight for time between two log records.
129 |
130 | * `Cwnd` Congestion Window the amount of data that can be sent into the network before needing an acknowledgment. in Bytes
131 |
132 | * `srtt` Smoothed Round-Trip Time. a measure to estimate the round-trip time(RTT) in seconds
133 |
134 | # building graphs in send_graphs directory
135 | ```bash
136 | ./scripts/screamtx_stats.py sender_scream_stats_0.csv
137 | ```
138 | # Arguments:
139 | Scream has many parameters kept for historical reasons or for development. Current SCReAM is self
140 | adjusting with default parameters.
141 | Here are few that you might want to set
142 | * `-minrate, -maxrate, initrate` in kbit/sec
143 | If encoder you are using uses bit/sec as bitrate property, you'll have to convert in your code when you set encoder
144 | bitrate property.
145 | * `force_idr` If packet loss is detected, gstscream, will send :UpstreamForceKeyUnitEvent, no more
146 | often than every 100ms
147 | There is alternative way to receiver application to send upstream GstForceKeyUnit event. In
148 | this case -force_idr should not be set
149 |
150 |
--------------------------------------------------------------------------------
/gstscream/build.rs:
--------------------------------------------------------------------------------
1 | fn main() {
2 | gst_plugin_version_helper::info();
3 | }
4 |
--------------------------------------------------------------------------------
/gstscream/scripts/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | SCRIPT_PATH=$(realpath $0)
3 | SCRIPT_DIR=$(dirname $SCRIPT_PATH)
4 | source $SCRIPT_DIR/env.sh
5 | SCREAMLIB_DIR=$SCRIPT_DIR/../../code/wrapper_lib
6 | cd $SCREAMLIB_DIR; cmake .; make
7 | cd $SCRIPT_DIR
8 | export RUSTFLAGS="$RUSTFLAGS -L$SCREAMLIB_DIR"
9 | if (($ECN_ENABLED == 1)); then
10 | cargo build --features ecn-enabled,screamtxbw-enabled
11 | cargo clippy --features ecn-enabled,screamtxbw-enabled
12 | else
13 | cargo build --features screamtxbw-enabled
14 | cargo clippy --features screamtxbw-enabled
15 | fi
16 |
17 |
--------------------------------------------------------------------------------
/gstscream/scripts/env.sh:
--------------------------------------------------------------------------------
1 | export ECN_ENABLED=0
2 | if (($ECN_ENABLED == 1)); then
3 | export SET_ECN="set-ecn=1"
4 | export SCREAMTX_PARAM_ECT="-ect 1"
5 | export RETRIEVE_ECN="retrieve-ecn=true"
6 | MY_GST_INSTALL=$(readlink -f $SCRIPT_DIR/../../../udp_gstreamer/install)
7 | echo "MY_GST_INSTALL=$MY_GST_INSTALL"
8 | export GST_PLUGIN_PATH=$MY_GST_INSTALL/lib/x86_64-linux-gnu
9 | export GST_PLUGIN_PATH=$GST_PLUGIN_PATH:$MY_GST_INSTALL/lib/x86_64-linux-gnu/gstreamer-1.0
10 | export GST_PLUGIN_PATH=$GST_PLUGIN_PATH:/usr/lib/x86_64-linux-gnu/gstreamer-1.0
11 |
12 | export LD_LIBRARY_PATH=$MY_GST_INSTALL/lib/x86_64-linux-gnu
13 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MY_GST_INSTALL/lib/x86_64-linux-gnu/gstreamer-1.0
14 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/x86_64-linux-gnu/gstreamer-1.0
15 |
16 | export PATH=$MY_GST_INSTALL/bin:$PATH
17 | export PKG_CONFIG_PATH=$MY_GST_INSTALL/lib/x86_64-linux-gnu/pkgconfig
18 | export PYTHONPATH=${PYTHONPATH}:$MY_GST_INSTALL/lib/python3/site-packages/
19 | LP=$(pkg-config --libs-only-L gstreamer-1.0 )
20 | export RUSTFLAGS="$LP $RUSTFLAGS"
21 | fi
22 |
23 | SCREAMLIB_DIR=$SCRIPT_DIR/../../code/wrapper_lib
24 | SCREAM_TARGET_DIR=$SCRIPT_DIR/../target/debug/
25 | export GST_PLUGIN_PATH=$SCREAM_TARGET_DIR:$GST_PLUGIN_PATH
26 | export LD_LIBRARY_PATH=$SCREAMLIB_DIR:$LD_LIBRARY_PATH
27 |
28 | echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH"
29 | echo "GST_PLUGIN_PATH=$GST_PLUGIN_PATH"
30 |
31 | export ENC_ID=264
32 |
33 | SENDER_IP=127.0.0.2
34 | RECEIVER_IP=127.0.0.1
35 |
36 | PORT0_RTP=30112
37 | PORT0_RTCP=30113
38 |
39 | PORT1_RTP=30114
40 | PORT1_RTCP=30115
41 |
42 | PORT2_RTP=30116
43 | PORT2_RTCP=30117
44 |
45 | #ENCODER="x${ENC_ID}enc speed-preset=ultrafast tune=zerolatency key-int-max=10000 "
46 | #only for x264:
47 | ENCODER="x264enc speed-preset=ultrafast tune=fastdecode+zerolatency key-int-max=10000 "
48 |
49 | #ENCODER="nvh${ENC_ID}enc zerolatency=true preset=low-latency-hq rc-mode=cbr-ld-hq gop-size=-1 "
50 |
51 | DECODER=avdec_h${ENC_ID}
52 | #DECODER=nvh${ENC_ID}dec
53 | #
54 |
55 | USE_SCREAM=1
56 | #if you set USE_SCREAM=0, modify key-int-max or gop-size in ENCODER above to periodically resend I frames
57 |
--------------------------------------------------------------------------------
/gstscream/scripts/receiver.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | SCRIPT_PATH=$(realpath $0)
3 | SCRIPT_DIR=$(dirname $SCRIPT_PATH)
4 | source $SCRIPT_DIR/env.sh
5 |
6 | QUEUE="queue max-size-buffers=2 max-size-bytes=0 max-size-time=0"
7 |
8 | if (($USE_SCREAM == 1)); then
9 | SCREAMRX0="! screamrx name=screamrx0 screamrx0.src "
10 | SCREAMRX0_RTCP="screamrx0.rtcp_src ! f0."
11 | else
12 | SCREAMRX0=""
13 | SCREAMRX0_RTCP=""
14 | fi
15 |
16 | VIDEOSINK="videoconvert ! fpsdisplaysink video-sink=\"ximagesink\""
17 | #VIDEOSINK="glupload ! glcolorconvert ! fpsdisplaysink video-sink=\"glimagesinkelement\""
18 | #VIDEOSINK="fakesink"
19 |
20 | export RECVPIPELINE="rtpbin latency=10 name=r \
21 | udpsrc port=$PORT0_RTP address=$RECEIVER_IP $RETRIEVE_ECN ! \
22 | queue $SCREAMRX0 ! application/x-rtp, media=video, encoding-name=H${ENC_ID}, clock-rate=90000 ! r.recv_rtp_sink_0 r. ! rtph${ENC_ID}depay ! h${ENC_ID}parse ! $DECODER name=videodecoder0 ! $QUEUE ! $VIDEOSINK \
23 | r.send_rtcp_src_0 ! funnel name=f0 ! queue ! udpsink host=$SENDER_IP port=$PORT0_RTCP sync=false async=false \
24 | $SCREAMRX0_RTCP udpsrc port=$PORT0_RTCP ! r.recv_rtcp_sink_0 \
25 | "
26 |
27 | export GST_DEBUG="2,screamrx:2"
28 | killall -9 scream_receiver
29 | $SCREAM_TARGET_DIR/scream_receiver
30 |
--------------------------------------------------------------------------------
/gstscream/scripts/receiver_3.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | SCRIPT_PATH=$(realpath $0)
3 | SCRIPT_DIR=$(dirname $SCRIPT_PATH)
4 | source $SCRIPT_DIR/env.sh
5 |
6 | QUEUE="queue max-size-buffers=2 max-size-bytes=0 max-size-time=0"
7 |
8 | if (($USE_SCREAM == 1)); then
9 | SCREAMRX0="! screamrx name=screamrx0 screamrx0.src "
10 | SCREAMRX0_RTCP="screamrx0.rtcp_src ! f0."
11 | #
12 | SCREAMRX1="! screamrx name=screamrx1 screamrx1.src "
13 | SCREAMRX1_RTCP="screamrx1.rtcp_src ! f1."
14 | #
15 | SCREAMRX2="! screamrx name=screamrx2 screamrx2.src "
16 | SCREAMRX2_RTCP="screamrx2.rtcp_src ! f2."
17 | else
18 | SCREAMRX0=""
19 | SCREAMRX0_RTCP=""
20 | SCREAMRX1=""
21 | SCREAMRX1_RTCP=""
22 | SCREAMRX2=""
23 | SCREAMRX2_RTCP=""
24 | fi
25 |
26 | DECODER=avdec_h${ENC_ID}
27 | #DECODER=nvh${ENC_ID}dec
28 | VIDEOSINK="videoconvert ! fpsdisplaysink video-sink=\"ximagesink\""
29 | #VIDEOSINK="fakesink"
30 |
31 | export RECVPIPELINE="rtpbin latency=10 name=r \
32 | udpsrc port=$PORT0_RTP address=$RECEIVER_IP $RETRIEVE_ECN ! \
33 | queue $SCREAMRX0 ! application/x-rtp, media=video, encoding-name=H${ENC_ID}, clock-rate=90000 ! r.recv_rtp_sink_0 r. ! rtph${ENC_ID}depay ! h${ENC_ID}parse ! $DECODER name=videodecoder0 ! $QUEUE ! $VIDEOSINK \
34 | r.send_rtcp_src_0 ! funnel name=f0 ! queue ! udpsink host=$SENDER_IP port=$PORT0_RTCP sync=false async=false \
35 | $SCREAMRX0_RTCP udpsrc port=$PORT0_RTCP ! r.recv_rtcp_sink_0 \
36 | \
37 | udpsrc port=$PORT1_RTP address=$RECEIVER_IP $RETRIEVE_ECN ! \
38 | queue $SCREAMRX1 ! application/x-rtp, media=video, encoding-name=H${ENC_ID}, clock-rate=90000 ! r.recv_rtp_sink_1 r. ! rtph${ENC_ID}depay ! h${ENC_ID}parse ! $DECODER name=videodecoder1 ! $QUEUE ! $VIDEOSINK \
39 | r.send_rtcp_src_1 ! funnel name=f1 ! queue ! udpsink host=$SENDER_IP port=$PORT1_RTCP sync=false async=false \
40 | $SCREAMRX1_RTCP udpsrc port=$PORT1_RTCP ! r.recv_rtcp_sink_1 \
41 | \
42 | udpsrc port=$PORT2_RTP address=$RECEIVER_IP $RETRIEVE_ECN ! \
43 | queue $SCREAMRX2 ! application/x-rtp, media=video, encoding-name=H${ENC_ID}, clock-rate=90000 ! r.recv_rtp_sink_2 r. ! rtph${ENC_ID}depay ! h${ENC_ID}parse ! $DECODER name=videodecoder2 ! $QUEUE ! $VIDEOSINK \
44 | r.send_rtcp_src_2 ! funnel name=f2 ! queue ! udpsink host=$SENDER_IP port=$PORT2_RTCP sync=false async=false \
45 | $SCREAMRX2_RTCP udpsrc port=$PORT2_RTCP ! r.recv_rtcp_sink_2 \
46 | "
47 |
48 | export GST_DEBUG="screamrx:2"
49 | killall -9 scream_receiver
50 | $SCREAM_TARGET_DIR/scream_receiver
51 |
--------------------------------------------------------------------------------
/gstscream/scripts/receiver_bw.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | SCRIPT_PATH=$(realpath $0)
3 | SCRIPT_DIR=$(dirname $SCRIPT_PATH)
4 | source $SCRIPT_DIR/env.sh
5 |
6 | export RECVPIPELINE="rtpbin latency=10 name=r udpsrc port=$PORT0_RTP address=$RECEIVER_IP ! screamrx name=screamrx screamrx.src ! fakesink r.send_rtcp_src_0 ! funnel name=f ! udpsink host=$SENDER_IP port=$PORT0_RTCP sync=false async=false screamrx.rtcp_src ! f. "
7 |
8 | killall -9 scream_receiver
9 | $SCREAM_TARGET_DIR/scream_receiver
10 |
--------------------------------------------------------------------------------
/gstscream/scripts/screamtx_stats.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | import matplotlib.pyplot as plt
3 | import pandas as pd
4 | import sys
5 | import pathlib
6 |
7 | input_file = sys.argv[1]
8 |
9 | df = pd.read_csv(input_file)
10 |
11 | graph_dir = 'send_graphs/'
12 |
13 | pathlib.Path(graph_dir).mkdir(parents=True, exist_ok=True)
14 |
15 | df['time-sec'] = df['time-ns'] / 1e9
16 |
17 | df['packetsLostRate'] = df['packetsLost'].diff().fillna(0) / df['time-sec'].diff().fillna(1)
18 |
19 | def plot_queue_delay(ax):
20 | ax.plot(df['time-sec'], df['queueDelay'], label='Queue Delay')
21 | ax.plot(df['time-sec'], df['queueDelayMax'], label='Queue Delay Max', linestyle='--')
22 | ax.plot(df['time-sec'], df['queueDelayMinAvg'], label='Queue Delay Min Avg', linestyle='--')
23 | ax.set_xlabel('Time (seconds)')
24 | ax.set_ylabel('Delay (seconds)')
25 | ax.set_title('Queue Delay over Time')
26 | ax.legend()
27 | ax.grid(True)
28 |
29 | def plot_packets_loss_rate(ax):
30 | ax.plot(df['time-sec'], df['packetsLostRate'], label='Packet Loss Rate', color='green')
31 | ax.set_xlabel('Time (seconds)')
32 | ax.set_ylabel('Packet Loss Rate')
33 | ax.set_title('Packet Loss Rate over Time')
34 | ax.grid(True)
35 |
36 | def plot_bitrates(ax):
37 | ax.plot(df['time-sec'], df['rateRtp'], label='Rate RTP', color='blue')
38 | ax.plot(df['time-sec'], df['rateTransmitted'], label='Rate Transmitted', color='orange')
39 | ax.plot(df['time-sec'], df['rateAcked'], label='Rate Acked', color='purple')
40 | ax.plot(df['time-sec'], df['targetBitrate'], label='Target Bitrate', color='brown')
41 | ax.set_xlabel('Time (seconds)')
42 | ax.set_ylabel('Bitrate (kbit/sec)')
43 | ax.set_title('Comparison of Bitrates over Time')
44 | ax.legend()
45 | ax.grid(True)
46 |
47 | def plot_cwnd_srtt(ax):
48 | ax.plot(df['time-sec'], df['cwnd'], label='Congestion Window', color='tab:red')
49 | ax.set_xlabel('Time (seconds)')
50 | ax.set_ylabel('Congestion Window (Bytes)', color='tab:red')
51 | ax.tick_params(axis='y', labelcolor='tab:red')
52 | ax2 = ax.twinx()
53 | ax2.plot(df['time-sec'], df['sRtt'], label='Smoothed RTT', color='tab:blue')
54 | ax2.set_ylabel('SRTT (seconds)', color='tab:blue')
55 | ax2.tick_params(axis='y', labelcolor='tab:blue')
56 | ax.set_title('Congestion Window and SRTT over Time')
57 |
58 | fig_queue_delay, ax_queue_delay = plt.subplots(figsize=(12, 6))
59 | plot_queue_delay(ax_queue_delay)
60 | fig_queue_delay.tight_layout()
61 | fig_queue_delay.savefig(graph_dir + 'queue_delay_plot.png', dpi=300)
62 |
63 | fig_packets_loss_rate, ax_packets_loss_rate = plt.subplots(figsize=(12, 6))
64 | plot_packets_loss_rate(ax_packets_loss_rate)
65 | fig_packets_loss_rate.tight_layout()
66 | fig_packets_loss_rate.savefig(graph_dir + 'packets_loss_rate_plot.png', dpi=300)
67 |
68 | fig_bitrate, ax_bitrate = plt.subplots(figsize=(12, 6))
69 | plot_bitrates(ax_bitrate)
70 | fig_bitrate.tight_layout()
71 | fig_bitrate.savefig(graph_dir + 'bitrate_plot.png', dpi=300)
72 |
73 | fig_cwnd_srtt, ax_cwnd_srtt = plt.subplots(figsize=(12, 6))
74 | plot_cwnd_srtt(ax_cwnd_srtt)
75 | fig_cwnd_srtt.tight_layout()
76 | fig_cwnd_srtt.savefig(graph_dir + 'cwnd_srtt_plot.png', dpi=300)
77 |
78 | fig_combined_vertical, axs_combined_vertical = plt.subplots(4, figsize=(12, 24))
79 | plot_queue_delay(axs_combined_vertical[0])
80 | plot_packets_loss_rate(axs_combined_vertical[1])
81 | plot_bitrates(axs_combined_vertical[2])
82 | plot_cwnd_srtt(axs_combined_vertical[3])
83 | fig_combined_vertical.tight_layout()
84 | fig_combined_vertical.subplots_adjust(hspace=0.5)
85 | fig_combined_vertical.savefig(graph_dir + 'combined_plot_vertical.png', dpi=300)
86 |
87 | fig_combined_grid, axs_combined_grid = plt.subplots(2, 2, figsize=(16, 12))
88 | plot_queue_delay(axs_combined_grid[0, 0])
89 | plot_packets_loss_rate(axs_combined_grid[0, 1])
90 | plot_bitrates(axs_combined_grid[1, 0])
91 | plot_cwnd_srtt(axs_combined_grid[1, 1])
92 | fig_combined_grid.tight_layout()
93 | fig_combined_grid.subplots_adjust(hspace=0.5, wspace=0.3)
94 | fig_combined_grid.savefig(graph_dir + 'combined_plot_grid.png', dpi=300)
95 |
--------------------------------------------------------------------------------
/gstscream/scripts/sender.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | SCRIPT_PATH=$(realpath $0)
3 | export SCRIPT_DIR=$(dirname $SCRIPT_PATH)
4 | source $SCRIPT_DIR/env.sh
5 |
6 | INIT_ENC_BITRATE=5000
7 |
8 | if (($USE_SCREAM == 1)); then
9 | INIT_ENC_BITRATE=500
10 | #NOSUMMARY=" -nosummary"
11 | #
12 |
13 | SCREAMTX0="queue ! screamtx name=\"screamtx0\" params=\"$NOSUMMARY -forceidr $SCREAMTX_PARAM_ECT -initrate $INIT_ENC_BITRATE -minrate 200 -maxrate 8000\" ! queue !"
14 | SCREAMTX0_RTCP="screamtx0.rtcp_sink screamtx0.rtcp_src !"
15 | else
16 | SCREAMTX0=""
17 | SCREAMTX0_RTCP=""
18 | fi
19 |
20 | VIDEOSRC="videotestsrc is-live=true pattern=snow ! video/x-raw,format=I420,width=1280,height=720,framerate=50/1"
21 |
22 | export SENDPIPELINE="rtpbin name=r \
23 | $VIDEOSRC ! $ENCODER name=encoder0 bitrate=$INIT_ENC_BITRATE ! rtph${ENC_ID}pay config-interval=-1 ! $SCREAMTX0 r.send_rtp_sink_0 r.send_rtp_src_0 ! udpsink host=$RECEIVER_IP port=$PORT0_RTP sync=false $SET_ECN \
24 | udpsrc port=$PORT0_RTCP address=$SENDER_IP ! queue ! $SCREAMTX0_RTCP r.recv_rtcp_sink_0 \
25 | r.send_rtcp_src_0 ! udpsink host=$RECEIVER_IP port=$PORT0_RTCP sync=false async=false \
26 | "
27 | export GST_DEBUG="2,screamtx:2"
28 | killall -9 scream_sender
29 | $SCREAM_TARGET_DIR/scream_sender --verbose
30 |
--------------------------------------------------------------------------------
/gstscream/scripts/sender_3.sh:
--------------------------------------------------------------------------------
1 | SCRIPT_PATH=$(realpath $0)
2 | SCRIPT_DIR=$(dirname $SCRIPT_PATH)
3 | source $SCRIPT_DIR/env.sh
4 |
5 | INIT_ENC_BITRATE=5000
6 |
7 | #needed for lo and other low latency links
8 | NETSIM="netsim min-delay=10 !"
9 |
10 | if (($USE_SCREAM == 1)); then
11 | INIT_ENC_BITRATE=500
12 | #NOSUMMARY=" -nosummary"
13 | #
14 | SCREAMTX0="queue ! screamtx name=\"screamtx0\" params=\"$NOSUMMARY -forceidr -priority 1.0 $SCREAMTX_PARAM_ECT -initrate $INIT_ENC_BITRATE -minrate 200 -maxrate 8000\" ! queue !"
15 | SCREAMTX0_RTCP="screamtx0.rtcp_sink screamtx0.rtcp_src !"
16 | #
17 | SCREAMTX1="queue ! screamtx name=\"screamtx1\" params=\"$NOSUMMARY -forceidr -priority 0.5 $SCREAMTX_PARAM_ECT -initrate $INIT_ENC_BITRATE -minrate 200 -maxrate 15000\" ! queue !"
18 | SCREAMTX1_RTCP="screamtx1.rtcp_sink screamtx1.rtcp_src !"
19 | #
20 | SCREAMTX2="queue ! screamtx name=\"screamtx2\" params=\"$NOSUMMARY -forceidr -priority 0.2 $SCREAMTX_PARAM_ECT -initrate $INIT_ENC_BITRATE -minrate 200 -maxrate 1000\" ! queue !"
21 | SCREAMTX2_RTCP="screamtx2.rtcp_sink screamtx2.rtcp_src !"
22 | else
23 | SCREAMTX0=""
24 | SCREAMTX0_RTCP=""
25 | SCREAMTX1=""
26 | SCREAMTX1_RTCP=""
27 | SCREAMTX2=""
28 | SCREAMTX2_RTCP=""
29 | fi
30 |
31 |
32 | VIDEOSRC="videotestsrc is-live=true pattern=snow ! video/x-raw,format=I420,width=1280,height=720,framerate=50/1"
33 |
34 | export SENDPIPELINE="rtpbin name=r \
35 | $VIDEOSRC ! $ENCODER name=encoder0 bitrate=$INIT_ENC_BITRATE ! rtph${ENC_ID}pay config-interval=-1 ! $SCREAMTX0 r.send_rtp_sink_0 r.send_rtp_src_0 ! $NETSIM udpsink host=$RECEIVER_IP port=$PORT0_RTP sync=false $SET_ECN \
36 | udpsrc port=$PORT0_RTCP address=$SENDER_IP ! queue ! $SCREAMTX0_RTCP r.recv_rtcp_sink_0 \
37 | r.send_rtcp_src_0 ! udpsink host=$RECEIVER_IP port=$PORT0_RTCP sync=false async=false \
38 | \
39 | $VIDEOSRC ! $ENCODER name=encoder1 bitrate=$INIT_ENC_BITRATE ! rtph${ENC_ID}pay config-interval=-1 ! $SCREAMTX1 r.send_rtp_sink_1 r.send_rtp_src_1 ! $NETSIM udpsink host=$RECEIVER_IP port=$PORT1_RTP sync=false $SET_ECN \
40 | udpsrc port=$PORT1_RTCP address=$SENDER_IP ! queue ! $SCREAMTX1_RTCP r.recv_rtcp_sink_1 \
41 | r.send_rtcp_src_1 ! udpsink host=$RECEIVER_IP port=$PORT1_RTCP sync=false async=false \
42 | \
43 | $VIDEOSRC ! $ENCODER name=encoder2 bitrate=$INIT_ENC_BITRATE ! rtph${ENC_ID}pay config-interval=-1 ! $SCREAMTX2 r.send_rtp_sink_2 r.send_rtp_src_2 ! $NETSIM udpsink host=$RECEIVER_IP port=$PORT2_RTP sync=false $SET_ECN \
44 | udpsrc port=$PORT2_RTCP address=$SENDER_IP ! queue ! $SCREAMTX2_RTCP r.recv_rtcp_sink_2 \
45 | r.send_rtcp_src_1 ! udpsink host=$RECEIVER_IP port=$PORT2_RTCP sync=false async=false \
46 | "
47 |
48 | export GST_DEBUG="2,screamtx:2"
49 | killall -9 scream_sender
50 | $SCREAM_TARGET_DIR/scream_sender --verbose
51 |
--------------------------------------------------------------------------------
/gstscream/scripts/sender_bw.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | SCRIPT_PATH=$(realpath $0)
3 | SCRIPT_DIR=$(dirname $SCRIPT_PATH)
4 | source $SCRIPT_DIR/env.sh
5 |
6 | export SENDPIPELINE=" screamtxbw name=encoder0 params=\"-numframes 10000 -initrate 1000 -ssrc 1\" ! queue ! tee name=t t. ! queue ! screamtx name=screamtx0 params=\" -forceidr -ect 1 -initrate 2500 -minrate 500 -maxrate 10000 \" ! udpsink host=$RECEIVER_IP port=$PORT0_RTP sync=false t. ! queue ! fakesink silent=false sync=false rtpbin name=r udpsrc port=$PORT0_RTCP address=$SENDER_IP ! queue ! screamtx0.rtcp_sink screamtx0.rtcp_src ! r.recv_rtcp_sink_0 "
7 |
8 | killall -9 scream_sender
9 | export RUST_BACKTRACE=1
10 | $SCREAM_TARGET_DIR/scream_sender
11 |
--------------------------------------------------------------------------------
/gstscream/scripts/sysctl.sh:
--------------------------------------------------------------------------------
1 | set -v
2 | sudo sysctl -w net.core.rmem_max=26214400
3 | sudo sysctl -w net.core.rmem_max=26214400
4 | sudo sysctl -w net.ipv4.udp_rmem_min=409600
5 |
6 | sudo sysctl -w net.core.wmem_max=26214400
7 | sudo sysctl -w net.core.wmem_default=26214400
8 | sudo sysctl -w net.core.rmem_max=26214400
9 | sudo sysctl -w net.core.rmem_default=26214400
10 |
11 |
--------------------------------------------------------------------------------
/gstscream/src/lib.rs:
--------------------------------------------------------------------------------
1 | use gst::glib;
2 |
3 | mod screamrx;
4 | #[cfg(not(feature = "screamrx-only"))]
5 | mod screamtx;
6 | #[cfg(all(not(feature = "screamrx-only"), feature = "screamtxbw-enabled"))]
7 | mod screamtxbw;
8 |
9 | // Plugin entry point that should register all elements provided by this plugin,
10 | // and everything else that this plugin might provide (e.g. typefinders or device providers).
11 | fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
12 | #[cfg(not(feature = "screamrx-only"))]
13 | screamtx::register(plugin)?;
14 | #[cfg(all(not(feature = "screamrx-only"), feature = "screamtxbw-enabled"))]
15 | screamtxbw::register(plugin)?;
16 | screamrx::register(plugin)?;
17 | Ok(())
18 | }
19 |
20 | // Static plugin metdata that is directly stored in the plugin shared object and read by GStreamer
21 | // upon loading.
22 | // Plugin name, plugin description, plugin entry point function, version number of this plugin,
23 | // license of the plugin, source package name, binary package name, origin where it comes from
24 | // and the date/time of release.
25 | gst::plugin_define!(
26 | scream,
27 | env!("CARGO_PKG_DESCRIPTION"),
28 | plugin_init,
29 | concat!(env!("CARGO_PKG_VERSION"), "-", env!("COMMIT_ID")),
30 | "Proprietary",
31 | env!("CARGO_PKG_NAME"),
32 | env!("CARGO_PKG_NAME"),
33 | env!("CARGO_PKG_REPOSITORY"),
34 | env!("BUILD_REL_DATE")
35 | );
36 |
--------------------------------------------------------------------------------
/gstscream/src/receiver.rs:
--------------------------------------------------------------------------------
1 | #![allow(clippy::uninlined_format_args)]
2 | extern crate failure;
3 | use std::fmt::Display;
4 |
5 | use clap::Parser;
6 | use failure::Error;
7 |
8 | extern crate gtypes;
9 |
10 | use gst::glib;
11 | use gst::glib::prelude::*;
12 | use gst::prelude::*;
13 |
14 | extern crate chrono;
15 |
16 | #[derive(clap::Parser)]
17 | #[command(version, about, long_about = None)]
18 | struct Arguments {
19 | #[arg(env)]
20 | /// The gstreamer pipeline to use for the receiver application.
21 | recvpipeline: String,
22 | /// Encoder Id , such as 264, 265
23 | #[arg(env, default_value_t = 264)]
24 | enc_id: u32,
25 | }
26 |
27 | fn main() {
28 | let args = Arguments::parse();
29 | println!("{args}");
30 | gst::init().expect("Failed to initialize");
31 |
32 | let main_loop = glib::MainLoop::new(None, false);
33 |
34 | start(&main_loop, args).expect("Failed to start");
35 | }
36 |
37 | fn start(main_loop: &glib::MainLoop, args: Arguments) -> Result<(), Error> {
38 | let pls: String = args.recvpipeline;
39 | println!("RECVPIPELINE={}", pls);
40 | let pipeline = gst::parse::launch(&pls).unwrap();
41 |
42 | let pipeline = pipeline.downcast::().unwrap();
43 | let pipeline_clone = pipeline.clone();
44 | let bin = pipeline.upcast::();
45 | let rtpbin = bin.by_name("r").unwrap();
46 | rtpbin.connect("new-jitterbuffer", false, move |_values| None);
47 | rtpbin.connect("request-pt-map", false, move |values| {
48 | let encoder_name = if args.enc_id == 265 { "H265" } else { "H264" };
49 | let pt = values[2].get::().expect("Invalid argument");
50 | println!("got pt: {pt}");
51 | match pt {
52 | 96 => Some(
53 | gst::Caps::builder("application/x-rtp")
54 | .field("media", "video")
55 | .field("clock-rate", 90000i32)
56 | .field("encoding-name", encoder_name)
57 | .field("rtcp-fb-nack-pli", true)
58 | .build()
59 | .to_value(),
60 | ),
61 | _ => None,
62 | }
63 | });
64 |
65 | let pipeline = bin.upcast::();
66 | pipeline
67 | .set_state(gst::State::Playing)
68 | .expect("Failed to set pipeline to `Playing`");
69 |
70 | let main_loop_clone = main_loop.clone();
71 | let bus = pipeline_clone.bus().unwrap();
72 | let _bus_watch = bus
73 | .add_watch(move |_, msg| {
74 | use gst::MessageView;
75 |
76 | let main_loop = &main_loop_clone;
77 | match msg.view() {
78 | MessageView::Eos(..) => {
79 | println!("### got Eos message");
80 | main_loop.quit();
81 | }
82 | MessageView::Error(err) => {
83 | println!(
84 | "### error from {:?}: {} ({:?})",
85 | err.src().map(|s| s.path_string()),
86 | err.error(),
87 | err.debug()
88 | );
89 | main_loop.quit();
90 | }
91 | _ => (),
92 | };
93 | glib::ControlFlow::Continue
94 | })
95 | .expect("failed to add bus watch");
96 |
97 | main_loop.run();
98 | pipeline
99 | .set_state(gst::State::Null)
100 | .expect("Failed to set pipeline to `Null`");
101 |
102 | Ok(())
103 | }
104 |
105 | impl Display for Arguments {
106 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107 | write!(f, "Configuration:\n\t- Pipeline {}", self.recvpipeline)
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/gstscream/src/screamrx/ecn.rs:
--------------------------------------------------------------------------------
1 | #[cfg(feature = "ecn-enabled")]
2 | mod feature_specific {
3 | use crate::screamrx::imp::CAT;
4 | use gst_sys::GstMeta;
5 | use gtypes::GType;
6 | use libc::c_int;
7 | // Enums
8 | pub type GstNetEcnCp = c_int;
9 |
10 | #[derive(Copy, Clone)]
11 | #[repr(C)]
12 | pub struct GstNetEcnMeta {
13 | pub meta: GstMeta,
14 | pub cp: GstNetEcnCp,
15 | }
16 |
17 | #[link(name = "gstnet-1.0")]
18 | extern "C" {
19 |
20 | //=========================================================================
21 | // GstNetEcnMeta
22 | //=========================================================================
23 | pub fn gst_net_ecn_meta_api_get_type() -> GType;
24 |
25 | }
26 |
27 | pub fn get_ecn(buffer: gst::Buffer, pad: &gst::Pad) -> u8 {
28 | let ecn_ce: u8;
29 | let ecn_meta: *mut GstNetEcnMeta;
30 | unsafe {
31 | ecn_meta =
32 | gst_sys::gst_buffer_get_meta(buffer.as_mut_ptr(), gst_net_ecn_meta_api_get_type())
33 | as *mut GstNetEcnMeta;
34 | }
35 | if ecn_meta.is_null() {
36 | gst::debug!(CAT, obj = pad, "Buffer did not contain an ECN meta");
37 | ecn_ce = 0;
38 | } else {
39 | unsafe {
40 | ecn_ce = (*ecn_meta).cp as u8;
41 | }
42 | }
43 | ecn_ce
44 | }
45 | }
46 | #[cfg(not(feature = "ecn-enabled"))]
47 | mod default {
48 | pub fn get_ecn(_buffer: gst::Buffer, _pad: &gst::Pad) -> u8 {
49 | 0
50 | }
51 | }
52 | #[cfg(feature = "ecn-enabled")]
53 | pub use feature_specific::get_ecn;
54 |
55 | #[cfg(not(feature = "ecn-enabled"))]
56 | pub use default::get_ecn;
57 |
--------------------------------------------------------------------------------
/gstscream/src/screamrx/mod.rs:
--------------------------------------------------------------------------------
1 | use gst::glib;
2 | use gst::glib::prelude::*;
3 |
4 | mod imp;
5 |
6 | mod ScreamRx;
7 |
8 | mod ecn;
9 |
10 | // The public Rust wrapper type for our element
11 | glib::wrapper! {
12 | pub struct Screamrx(ObjectSubclass) @extends gst::Element, gst::Object;
13 | }
14 |
15 | // GStreamer elements need to be thread-safe. For the private implementation this is automatically
16 | // enforced but for the public wrapper type we need to specify this manually.
17 | unsafe impl Send for Screamrx {}
18 | unsafe impl Sync for Screamrx {}
19 |
20 | // Registers the type for our element, and then registers in GStreamer under
21 | // the name "rsscreamrx" for being able to instantiate it via e.g.
22 | // gst::ElementFactory::make().
23 | pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
24 | gst::Element::register(
25 | Some(plugin),
26 | "screamrx",
27 | gst::Rank::NONE,
28 | Screamrx::static_type(),
29 | )
30 | }
31 |
--------------------------------------------------------------------------------
/gstscream/src/screamtx/mod.rs:
--------------------------------------------------------------------------------
1 | use gst::glib;
2 | use gst::glib::prelude::*;
3 |
4 | mod imp;
5 |
6 | // The public Rust wrapper type for our element
7 | glib::wrapper! {
8 | pub struct Screamtx(ObjectSubclass) @extends gst::Element, gst::Object;
9 | }
10 |
11 | // GStreamer elements need to be thread-safe. For the private implementation this is automatically
12 | // enforced but for the public wrapper type we need to specify this manually.
13 | unsafe impl Send for Screamtx {}
14 | unsafe impl Sync for Screamtx {}
15 |
16 | // Registers the type for our element, and then registers in GStreamer under
17 | // the name "rsscreamtx" for being able to instantiate it via e.g.
18 | // gst::ElementFactory::make().
19 | pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
20 | gst::Element::register(
21 | Some(plugin),
22 | "screamtx",
23 | gst::Rank::NONE,
24 | Screamtx::static_type(),
25 | )
26 | }
27 |
--------------------------------------------------------------------------------
/gstscream/src/screamtxbw/mod.rs:
--------------------------------------------------------------------------------
1 | use gst::glib;
2 | use gst::glib::prelude::*;
3 |
4 | mod imp;
5 |
6 | // The public Rust wrapper type for our element
7 | glib::wrapper! {
8 | pub struct Screamtxbw(ObjectSubclass) @extends gst::Element, gst::Object;
9 | }
10 |
11 | // GStreamer elements need to be thread-safe. For the private implementation this is automatically
12 | // enforced but for the public wrapper type we need to specify this manually.
13 | unsafe impl Send for Screamtxbw {}
14 | unsafe impl Sync for Screamtxbw {}
15 |
16 | // Registers the type for our element, and then registers in GStreamer under
17 | // the name "rsscreamtxbw" for being able to instantiate it via e.g.
18 | // gst::ElementFactory::make().
19 | pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
20 | gst::Element::register(
21 | Some(plugin),
22 | "screamtxbw",
23 | gst::Rank::NONE,
24 | Screamtxbw::static_type(),
25 | )
26 | }
27 |
--------------------------------------------------------------------------------
/gstscream/src/sender.rs:
--------------------------------------------------------------------------------
1 | #![allow(clippy::uninlined_format_args)]
2 | use clap::Parser;
3 | use failure::Error;
4 | use std::fmt::Display;
5 | use std::process::exit;
6 |
7 | extern crate failure;
8 | #[macro_use]
9 | extern crate lazy_static;
10 |
11 | use gst::glib;
12 | use gst::prelude::*;
13 |
14 | mod sender_util;
15 |
16 | #[derive(clap::Parser)]
17 | #[command(version, about, long_about = None)]
18 | struct Arguments {
19 | #[arg(short, long, default_value_t = false)]
20 | /// Produces verbose logs.
21 | verbose: bool,
22 |
23 | #[arg(short, long)]
24 | /// Rate multiplication factor.
25 | ratemultiply: Option,
26 |
27 | #[arg(env)]
28 | /// The gstreamer pipeline to use for the sender application.
29 | sendpipeline: String,
30 |
31 | #[arg(env, default_value_t = 1000)]
32 | /// The logging interval for sender statistics.
33 | sender_stats_timer: u32,
34 |
35 | #[arg(env, default_value = "sender_scream_stats.csv")]
36 | /// The logging interval for sender statistics.
37 | sender_stats_file_name: std::path::PathBuf,
38 | }
39 |
40 | fn main() {
41 | let args = Arguments::parse();
42 | println!("{}", args);
43 |
44 | gst::init().expect("Failed to initialize gst_init");
45 |
46 | let main_loop = glib::MainLoop::new(None, false);
47 | start(&main_loop, args).expect("Failed to start");
48 | }
49 |
50 | fn start(main_loop: &glib::MainLoop, args: Arguments) -> Result<(), Error> {
51 | let pls = args.sendpipeline;
52 |
53 | println!("Pipeline: {}", pls);
54 | let n_encoder0 = pls.matches("name=encoder0").count();
55 | let n_encoders = pls.matches("name=encoder").count();
56 | if n_encoder0 == 0 {
57 | println!("missing name=encoder0");
58 | exit(0);
59 | }
60 |
61 | let pipeline = gst::parse::launch(&pls).unwrap();
62 | let pipeline = pipeline.downcast::().unwrap();
63 |
64 | pipeline
65 | .set_state(gst::State::Playing)
66 | .expect("Failed to set pipeline to `Playing`");
67 |
68 | let pipeline = pipeline.downcast::().unwrap();
69 |
70 | let pipeline_clone = pipeline;
71 | /* TBD
72 | * set ecn bits
73 | */
74 | for n in 0..n_encoders {
75 | let n_string = n.to_string();
76 | sender_util::stats(
77 | &pipeline_clone,
78 | n,
79 | &Some("screamtx".to_string() + &n_string),
80 | args.sender_stats_timer,
81 | args.sender_stats_file_name.clone(),
82 | );
83 | sender_util::run_time_bitrate_set(
84 | &pipeline_clone,
85 | args.verbose,
86 | &Some("screamtx".to_string() + &n_string),
87 | &Some("encoder".to_string() + &n_string),
88 | args.ratemultiply,
89 | );
90 | }
91 |
92 | let main_loop_cloned = main_loop.clone();
93 | let bus = pipeline_clone.bus().unwrap();
94 | let _bus_watch = bus
95 | .add_watch(move |_, msg| {
96 | use gst::MessageView;
97 | // println!("sender: {:?}", msg.view());
98 | match msg.view() {
99 | MessageView::Eos(..) => {
100 | println!("Bus watch Got eos");
101 | main_loop_cloned.quit();
102 | }
103 | MessageView::Error(err) => {
104 | println!(
105 | "Error from {:?}: {} ({:?})",
106 | err.src().map(|s| s.path_string()),
107 | err.error(),
108 | err.debug()
109 | );
110 | }
111 | _ => (),
112 | };
113 | glib::ControlFlow::Continue
114 | })
115 | .expect("failed to add bus watch");
116 |
117 | main_loop.run();
118 | pipeline_clone
119 | .set_state(gst::State::Null)
120 | .expect("Failed to set pipeline to `Null`");
121 | println!("Done");
122 | Ok(())
123 | }
124 | impl Display for Arguments {
125 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
126 | write!(
127 | f,
128 | "Configuration:\n\t- Verbose: {},\n\t- Ratemultiply: {:?},\n\t- Pipeline: {},\n\t- Logging interval: {},\n\t- sender_stats_file: {}",
129 | self.verbose,
130 | self.ratemultiply,
131 | self.sendpipeline,
132 | self.sender_stats_timer,
133 | self.sender_stats_file_name.display()
134 | )
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/gstscream/src/sender_util.rs:
--------------------------------------------------------------------------------
1 | #![allow(clippy::uninlined_format_args)]
2 | use std::convert::TryInto;
3 | use std::fs::File;
4 | use std::io::Write;
5 | use std::sync::{Arc, Mutex};
6 | use std::time::{Duration, SystemTime, UNIX_EPOCH};
7 |
8 | use gst::glib;
9 | use gst::prelude::*;
10 |
11 | use glib::timeout_add;
12 |
13 | #[derive(Default)]
14 | struct RateInfo {
15 | rate: u32,
16 | st: Duration,
17 | count: u32,
18 | }
19 |
20 | pub fn stats(
21 | bin: &gst::Pipeline,
22 | n: usize,
23 | screamtx_name_opt: &Option,
24 | sender_stats_timer: u32,
25 | mut sender_stats_file_name: std::path::PathBuf,
26 | ) {
27 | if sender_stats_timer == 0 {
28 | return;
29 | }
30 |
31 | if screamtx_name_opt.is_none() {
32 | println!("no scream name");
33 | return;
34 | }
35 |
36 | println!("SENDER_STATS_TIMER={}", sender_stats_timer);
37 |
38 | let pipeline_clock = bin.pipeline_clock();
39 |
40 | let repl_string = "_".to_owned() + &n.to_string() + ".csv";
41 | let file_name = match sender_stats_file_name.file_name() {
42 | Some(file) => file,
43 | None => {
44 | println!("Invalid SENDER_STATS_FILE_NAME.");
45 | return;
46 | }
47 | };
48 | let file_name = match file_name.to_str() {
49 | Some(file_name) => file_name,
50 | None => {
51 | println!("SENDER_STATS_FILE_NAME must be a utf8 encoded string");
52 | return;
53 | }
54 | }
55 | .to_string();
56 |
57 | sender_stats_file_name.set_file_name(file_name.replace(".csv", &repl_string));
58 | println!(
59 | "SENDER_STATS_FILE_NAME={}",
60 | sender_stats_file_name.display()
61 | );
62 | let mut out: File = File::create(&sender_stats_file_name).unwrap();
63 |
64 | let scream_name = screamtx_name_opt.as_ref().unwrap();
65 | let screamtx_e = match bin.by_name(scream_name) {
66 | Some(v) => v,
67 | None => {
68 | println!(" no {}", scream_name);
69 | return;
70 | }
71 | };
72 |
73 | let screamtx_e_clone = screamtx_e.clone();
74 | let stats_str_header = screamtx_e.property::("stats-header");
75 |
76 | writeln!(out, "time-ns,{}", stats_str_header).unwrap();
77 |
78 | let outp_opt: Option>> = Some(Arc::new(Mutex::new(out)));
79 |
80 | timeout_add(
81 | Duration::from_millis(sender_stats_timer as u64),
82 | move || {
83 | let stats_str = screamtx_e_clone.property::("stats");
84 |
85 | let tm = pipeline_clock.time();
86 | let ns = tm.unwrap().nseconds();
87 | let out_p = outp_opt.as_ref().unwrap();
88 | let mut fd = out_p.lock().unwrap();
89 |
90 | writeln!(fd, "{},{}", ns, stats_str).unwrap();
91 | glib::ControlFlow::Continue
92 | },
93 | );
94 | }
95 |
96 | lazy_static! {
97 | static ref RATE_INFO_PREV: Mutex = Mutex::new(RateInfo {
98 | ..RateInfo::default()
99 | });
100 | }
101 |
102 | pub fn run_time_bitrate_set(
103 | bin: &gst::Pipeline,
104 | verbose: bool,
105 | screamtx_name_opt: &Option,
106 | encoder_name_opt: &Option,
107 | ratemultiply_opt: Option,
108 | ) {
109 | if encoder_name_opt.is_none() {
110 | println!("no encoder_name_opt");
111 | return;
112 | }
113 | let ratemultiply: u32 = ratemultiply_opt.unwrap_or(1).try_into().unwrap();
114 | println!(
115 | "{:?} {:?} {:?}",
116 | encoder_name_opt, screamtx_name_opt, ratemultiply_opt
117 | );
118 | let encoder_name = encoder_name_opt.as_ref().unwrap();
119 | println!("encoder_name {:?}", encoder_name);
120 | let encoder_name_clone = encoder_name.clone();
121 | let video = bin
122 | .by_name(encoder_name)
123 | .expect("Failed to by_name encoder");
124 |
125 | let video_cloned = video;
126 | match screamtx_name_opt.as_ref() {
127 | Some(scream_name) => {
128 | match bin.by_name(scream_name) {
129 | Some(scream) => {
130 | let scream_cloned = scream.clone();
131 | scream.connect("notify::current-max-bitrate", false, move |_values| {
132 | let rate = scream_cloned.property::("current-max-bitrate");
133 | let rate = rate * ratemultiply;
134 | let prev_br:u32 = video_cloned.property::("bitrate");
135 | video_cloned
136 | .set_property("bitrate", rate);
137 | let n = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
138 |
139 | let mut rate_info_prev = RATE_INFO_PREV.lock().unwrap();
140 | let rate_prev = rate_info_prev.rate;
141 | let st_prev = rate_info_prev.st;
142 | let diff = n.as_secs() - st_prev.as_secs();
143 | if diff >= 1 {
144 | if rate != rate_prev {
145 | if verbose {
146 | println!("notif: {} {}.{:06} rate {:08} rate_prev {:08} time_prev {}.{:06} diff {} count {} prev_br {}",
147 | encoder_name_clone, n.as_secs(), n.subsec_micros(), rate, rate_prev, st_prev.as_secs(),
148 | st_prev.subsec_micros(), diff, rate_info_prev.count, prev_br);
149 | }
150 | rate_info_prev.rate = rate;
151 | rate_info_prev.st = n;
152 | rate_info_prev.count = 0;
153 | }
154 | } else {
155 | rate_info_prev.count += 1;
156 | // println!("count {}", rate_info_prev.count);
157 | }
158 | None
159 | });
160 | }
161 | None => println!("no scream signal"),
162 | }
163 | }
164 | None => println!("no scream name"),
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/images/L4S-100Mbps-25ms-0-4-0-TCP.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricssonResearch/scream/5d5e4ca2c41ad62875314e5e8d2571efd58aad6a/images/L4S-100Mbps-25ms-0-4-0-TCP.png
--------------------------------------------------------------------------------
/images/L4S-100Mbps-25ms-0-4-TCP.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricssonResearch/scream/5d5e4ca2c41ad62875314e5e8d2571efd58aad6a/images/L4S-100Mbps-25ms-0-4-TCP.png
--------------------------------------------------------------------------------
/images/L4S-100Mbps-25ms-r-50-0-4-TCP.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricssonResearch/scream/5d5e4ca2c41ad62875314e5e8d2571efd58aad6a/images/L4S-100Mbps-25ms-r-50-0-4-TCP.png
--------------------------------------------------------------------------------
/images/SCReAM-V2-L4S.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricssonResearch/scream/5d5e4ca2c41ad62875314e5e8d2571efd58aad6a/images/SCReAM-V2-L4S.png
--------------------------------------------------------------------------------
/images/SCReAM-V2-RTT-25ms-1360B.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricssonResearch/scream/5d5e4ca2c41ad62875314e5e8d2571efd58aad6a/images/SCReAM-V2-RTT-25ms-1360B.png
--------------------------------------------------------------------------------
/images/SCReAM-V2-noL4S.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricssonResearch/scream/5d5e4ca2c41ad62875314e5e8d2571efd58aad6a/images/SCReAM-V2-noL4S.png
--------------------------------------------------------------------------------
/images/SCReAM_LTE_UL.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricssonResearch/scream/5d5e4ca2c41ad62875314e5e8d2571efd58aad6a/images/SCReAM_LTE_UL.png
--------------------------------------------------------------------------------
/images/image_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricssonResearch/scream/5d5e4ca2c41ad62875314e5e8d2571efd58aad6a/images/image_1.png
--------------------------------------------------------------------------------
/images/image_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricssonResearch/scream/5d5e4ca2c41ad62875314e5e8d2571efd58aad6a/images/image_2.png
--------------------------------------------------------------------------------
/images/scream_ecn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricssonResearch/scream/5d5e4ca2c41ad62875314e5e8d2571efd58aad6a/images/scream_ecn.png
--------------------------------------------------------------------------------
/images/scream_ecn_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricssonResearch/scream/5d5e4ca2c41ad62875314e5e8d2571efd58aad6a/images/scream_ecn_2.png
--------------------------------------------------------------------------------
/images/scream_ecn_keyframe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricssonResearch/scream/5d5e4ca2c41ad62875314e5e8d2571efd58aad6a/images/scream_ecn_keyframe.png
--------------------------------------------------------------------------------
/images/scream_l4s.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricssonResearch/scream/5d5e4ca2c41ad62875314e5e8d2571efd58aad6a/images/scream_l4s.png
--------------------------------------------------------------------------------
/images/scream_l4s_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricssonResearch/scream/5d5e4ca2c41ad62875314e5e8d2571efd58aad6a/images/scream_l4s_2.png
--------------------------------------------------------------------------------
/images/scream_noecn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricssonResearch/scream/5d5e4ca2c41ad62875314e5e8d2571efd58aad6a/images/scream_noecn.png
--------------------------------------------------------------------------------
/images/scream_noecn_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricssonResearch/scream/5d5e4ca2c41ad62875314e5e8d2571efd58aad6a/images/scream_noecn_2.png
--------------------------------------------------------------------------------
/images/scream_noecn_keyframe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricssonResearch/scream/5d5e4ca2c41ad62875314e5e8d2571efd58aad6a/images/scream_noecn_keyframe.png
--------------------------------------------------------------------------------
/multicam/README.md:
--------------------------------------------------------------------------------
1 | # SCReAM multicamera platform
2 |
3 | This README describes the streaming platform for a multicamera solution with SCReAM congestion control. The platform supports up to four cameras and an overview is shown in the figures below (two camera solution).
4 | This streaming solution has been extensively tested for remote control cars but can also be used for e.g drones or remote video production.
5 |
6 | The `capture/encode` and `decode/render` blocks are implemented as GStreamer pipelines, this makes the solution portable to different platforms. The `SCReAM sender` and `SCReAM receiver` blocks builds on Linux platforms and supports ECN and L4S.
7 |
8 | The `SCReAM sender` receives RTP/UDP traffic from the `capture/render` GStreamer pipelines over local ports 30000,30002,30004,30006 and sends codec control commands (target bitrate and force IDR) on local ports 30001,30003,30005,30007. A dedicated `codecctrl` GStreamer plugin serves as an interface between the `SCReAM sender` and the video encoders in the GStreamer piplelines.
9 |
10 | The RTP/UDP streams are multiplexed in the `SCReAM sender` block and transmitted to RECEIVER_IP:UDP_PORT_VIDEO, the RTCP feedback from the receiver is also over the same UDP socket. The `SCReAM receiver` block receives the multiplexed RTP/UDP streams, generates RTCP feedback (RFC8888) to the sender and demultiplexes the streams and forwards them to the `decode/render` GStreamer pipelines.
11 |
12 |
13 | The sender side schematic is according to figure 1 below
14 |
15 | +-----------------+ Lo:30001 +-------------------+
16 | | +<-----------+ |
17 | | /dev/video0 | | |
18 | | capture/encode +----------->+ |
19 | +-----------------+ Lo:30000 | +--------------------------->
20 | | SCReAM sender | RECEIVER_IP:UDP_PORT_VIDEO
21 | +-----------------+ Lo:30003 | +<---------------------------
22 | | +<-----------+ |
23 | | /dev/video1 | | |
24 | | capture/encode +----------->+ |
25 | +-----------------+ Lo:30002 +-------------------+
26 | Figure 1
27 |
28 | The receiver side schematic is according to figure 2 below
29 |
30 | +-------------------+ +-----------------+
31 | | | Lo:30112 | |
32 | | +----------->+ Front camera |
33 | | | | decode/render |
34 | +----------------->+ | +-----------------+
35 | $1:UDP_PORT_VIDEO | SCReAM receiver |
36 | <------------------+ | +-----------------+
37 | | | Lo:30114 | |
38 | | +----------->+ Rear camera |
39 | | | | decode/render |
40 | +-------------------+ +-----------------+
41 | Figure 2
42 |
43 | ## Start streaming
44 | The sender side is started with he script
45 | `$ ./startsender.sh`
46 | Note that the IP address needs to be changed to point at the receiving side
47 |
48 | The receiver side is started with
49 | `$ ./startreceiver.sh`
50 | This scripts waits for streaming traffic to arrive on the configured UDP port, in addition it also decodes the dst_port in case a NAT has remapped this port.
51 | To ensure proper function it is recommended to start the sender side first, then the receiver side.
52 |
53 | ## Bill of materials
54 | The sender side is built on the NVIDIA Jetson platforms, other platforms and cameras are possible. The BoM for the NVIDIA Jetson is:
55 | * NVIDIA Jetson Nano Rev B01. For improved performance the Xavier NX can be used
56 | * e-CAM50_CUNANO, one or two depending on desired configuration https://www.e-consystems.com/nvidia-cameras/jetson-nano-cameras/5mp-mipi-nano-camera.asp .. or..
57 | * Raspberry PI HQ
58 | * A proper 4G or 5G modem
59 | * A battery
60 |
61 | ## Other platforms
62 | The solution is possible to implement on other Linux based platforms such as Raspberry PI 4. The `SCReAM sender` and `SCReAM receiver` should not need any changes.
63 | The GStreamer pipelines do however need modifications as other hardware video encoders and decoder blocks are used. Furthermore the parameter settings for the `codecctrl` as well as the implementation may need to be modified as different video encoders can use different units ( [bit/s] or [kbit/s] ) and also the parameter name for the target bitrate can vary.
64 |
65 | ## More than two cameras
66 | The scripts in the sender and receiver folders support up to 2 cameras. This can be extended to up to 4 cameras without modifications in the `SCReAM sender` and `SCReAM receiver` code. Platforms such as NVIDIA Jetson AGX Xavier support many cameras, for this purpose the `startsender.sh` and `rendermedia.sh` scripts should be modified to support more cameras.
67 |
--------------------------------------------------------------------------------
/multicam/receiver/LICENSE.dat:
--------------------------------------------------------------------------------
1 | Copyright (c) 2021 Ericsson AB
2 | All rights reserved.
3 | Redistribution and use in source and binary forms, with or without modification, are permitted (subject to the limitations in the disclaimer below) provided that the following conditions are met:
4 |
5 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
7 | * Neither the name of Ericsson AB nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
8 |
9 | NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
10 |
--------------------------------------------------------------------------------
/multicam/receiver/README.md:
--------------------------------------------------------------------------------
1 | # Receiver side build instructions
2 |
3 | On the receiver side it is assumed that gstreamer is already installed.
4 |
5 | The SCReAM receiver side is built with the instructions
6 | `$cd ./scream`
7 | `$cmake .`
8 | `$make`
9 |
10 |
11 | #Startup
12 |
13 | In the terminal:
14 | `$ ./startvideo.sh`
15 |
16 | To ensure proper function it is recommended to start the sender side first, then the receiver side. Or more correctly, the remote end that is connected to a cellular modem should be started first. This can avoid issues with remapped ports.
17 |
18 | To stop the programs, in the terminal:
19 | `$ ./killitall.sh`
20 |
21 | #Streaming status
22 | Streaming status is printed on stdout and also transmitted on UDP port 30200, this can be used for instance to visualize bitrate, RTT, packet loss etc in a graphical user interface
23 | An example of streaming status is:
24 | *** 396.540, 97, 0.044, 0.010, 609409, 105159, 31465, 1, 0.003, 17433, 18372, 17868, 0, 0, 0.001, 12453, 13480, 13520, 0, 0,
25 | 396.791, 86, 0.042, 0.008, 609409, 92399, 31021, 1, 0.014, 17608, 16876, 17646, 0, 0, 0.000, 12487, 13176, 13298, 0, 0,
26 | 397.042, 88, 0.043, 0.010, 609409, 95279, 31992, 1, 0.012, 17828, 17346, 17979, 0, 0, 0.004, 12573, 13907, 13936, 0, 0,
***
27 | Where the columns are (listed left to right)
28 | 1. Time [s]
29 | 2. Quality index for first camera (only)
30 | 3. Estimated queue delay [s]
31 | 4. Average RTT [s]
32 | 5. Congestion window [byte]
33 | 6. Bytes in flight [byte]
34 | 7. Total bitrate [kbps]
35 | 8. Fast increase mode indicator [0 or 1]
36 | 9. Camera 1 RTP queue delay [s]
37 | 10. Camera 1 Target bitrate [kbps]
38 | 11. Camera 1 Video coder bitrate [kbps]
39 | 12. Camera 1 Transmitted bitrate [kbps]
40 | 13. Camera 1 Loss bitrate [kbps]
41 | 14. Camera 1 Congestion marked bitrate (ECN, L4S) bitrate [kbps]
42 | 15. Camera 2 RTP queue delay [s]
43 | 16. Camera 2 Target bitrate [kbps]
44 | 17. Camera 2 Video coder bitrate [kbps]
45 | 18. Camera 2 Transmitted bitrate [kbps]
46 | 19. Camera 2 Loss bitrate [kbps]
47 | 20. Camera 2 Congestion marked bitrate (ECN, L4S) bitrate [kbps]
48 |
--------------------------------------------------------------------------------
/multicam/receiver/killitall.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | killall -9 gst-launch-1.0
4 | killall -9 scream_receiver
5 |
6 |
--------------------------------------------------------------------------------
/multicam/receiver/rendermedia-intel.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | #
3 | # The receiver side processing is illustrated below
4 | # The SCReAM receiver application receives multiplexed RTP media on port $2
5 | # and transits RTCP feedback over the same port
6 | # The received RTP media is demultiplexed and forwarded on local
7 | # ports 30112, 30114, 31016 and 30118
8 | # The video decoding assumes an NVIDIA Jetson Nano or Xavier NX platform, change to applicable
9 | # HW decoding, depending on platform
10 | #
11 | # +----------------------+ +--------------------+
12 | # | | Lo:30112 | |
13 | # | +-------------->+ Front camera |
14 | # | | | decode/render |
15 | # +------------------>+ | +--------------------+
16 | # $1:$2 | SCReAM receiver |
17 | # <-------------------+ | +--------------------+
18 | # | | Lo:30114 | |
19 | # | +-------------->+ Rear camera |
20 | # | | | decode/render |
21 | # +----------------------+ +--------------------+
22 |
23 |
24 | # Start SCReAM receiver side
25 | ./scream/bin/scream_receiver $1 $2 $3 | tee ./Data/scream_$4.txt &
26 |
27 |
28 | ## /dev/video0
29 | gst-launch-1.0 udpsrc port=30112 ! application/x-rtp,media=video,clock-rate=90000,encoding-name=H264 ! rtpjitterbuffer latency=50 ! rtph264depay ! h264parse ! vaapih264dec low-latency=true ! videoconvert ! waylandsink sync=true &
30 |
31 | ## /dev/video1
32 | gst-launch-1.0 udpsrc port=30114 ! application/x-rtp,media=video,clock-rate=90000,encoding-name=H264 ! rtpjitterbuffer latency=50 ! rtph264depay ! h264parse ! vaapih264dec low-latency=true ! videoconvert ! ximagesink sync=true &
33 |
--------------------------------------------------------------------------------
/multicam/receiver/rendermedia.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | #
3 | # The receiver side processing is illustrated below
4 | # The SCReAM receiver application receives multiplexed RTP media on port $2
5 | # and transits RTCP feedback over the same port
6 | # The received RTP media is demultiplexed and forwarded on local
7 | # ports 30112, 30114, 31016 and 30118
8 | # The video decoding assumes an NVIDIA Jetson Nano or Xavier NX platform, change to applicable
9 | # HW decoding, depending on platform
10 | #
11 | # +----------------------+ +--------------------+
12 | # | | Lo:30112 | |
13 | # | +-------------->+ Front camera |
14 | # | | | decode/render |
15 | # +------------------>+ | +--------------------+
16 | # $1:$2 | SCReAM receiver |
17 | # <-------------------+ | +--------------------+
18 | # | | Lo:30114 | |
19 | # | +-------------->+ Rear camera |
20 | # | | | decode/render |
21 | # +----------------------+ +--------------------+
22 |
23 |
24 | # Start SCReAM receiver side
25 | ./scream/bin/scream_receiver $1 $2 $3 | tee ./Data/scream_$4.txt &
26 |
27 |
28 | ## /dev/video0
29 | gst-launch-1.0 udpsrc port=30112 ! application/x-rtp,media=video,clock-rate=90000,encoding-name=H264 ! rtpjitterbuffer latency=100 ! rtph264depay ! h264parse ! omxh264dec disable-dpb=true ! nvvidconv ! nveglglessink window-x=640 window-y=360 max-lateness=2000000 sync=true &
30 |
31 | ## /dev/video1
32 | gst-launch-1.0 udpsrc port=30114 ! application/x-rtp,media=video,clock-rate=90000,encoding-name=H264 ! rtpjitterbuffer latency=100 ! rtph264depay ! h264parse ! omxh264dec disable-dpb=true ! nvvidconv ! nveglglessink window-x=960 window-y=0 sync=true &
33 |
34 |
--------------------------------------------------------------------------------
/multicam/receiver/scream/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.6)
2 |
3 | PROJECT( scream )
4 |
5 | message("Source Dir:" ${scream_SOURCE_DIR})
6 |
7 | SET(EXECUTABLE_OUTPUT_PATH ${scream_SOURCE_DIR}/bin)
8 | SET(LIBRARY_OUTPUT_PATH ${scream_SOURCE_DIR}/lib)
9 | SET(RUNTIME_OUTPUT_DIRECTORY ${scream_SOURCE_DIR}/bin)
10 |
11 | SET(scream_BIN ${scream_SOURCE_DIR}/bin)
12 |
13 | message("scream_SOURCE_DIR directories:" ${scream_SOURCE_DIR})
14 |
15 | IF(UNIX)
16 | add_definitions(-std=c++0x)
17 | ENDIF(UNIX)
18 |
19 | IF(WIN32)
20 | IF(MSVC12)
21 | message("Detected MSVC12 compiler")
22 | set(MSVC_VER VC12)
23 | ELSEIF(MSVC11)
24 | message("Detected MSVC11 compiler")
25 | set(MSVC_VER VC11)
26 | ELSEIF(MSVC10)
27 | message("Detected MSVC10 compiler")
28 | set(MSVC_VER VC10)
29 | ELSEIF(MSVC14)
30 | message("Detected MSVC14 compiler")
31 | set(MSVC_VER VC14)
32 | ELSE(MSVC12)
33 | message("WARNING: Unknown/unsupported MSVC version")
34 | ENDIF(MSVC12)
35 | ENDIF(WIN32)
36 |
37 | if( CMAKE_SIZEOF_VOID_P EQUAL 8 )
38 | # 64bit
39 | message("Detected 64-bit build - compiling with -fPIC")
40 | SET(CMAKE_CXX_FLAGS "-fPIC -fpermissive -pthread")
41 | else( CMAKE_SIZEOF_VOID_P EQUAL 8 )
42 | # 32 bit
43 | message("Detected 32-bit build")
44 | SET(CMAKE_CXX_FLAGS "-fPIC -fpermissive -pthread")
45 | endif( CMAKE_SIZEOF_VOID_P EQUAL 8 )
46 |
47 | SET(screamIncludes
48 | ${scream_SOURCE_DIR}
49 | ${scream_SOURCE_DIR}/code
50 | )
51 |
52 | message("screamIncludes directories:" ${screamIncludes})
53 |
54 | # lib directories
55 | IF(WIN32)
56 | SET(screamLink
57 | ${scream_SOURCE_DIR}/../lib
58 | )
59 | ELSEIF(UNIX)
60 | SET(screamLink
61 | ${scream_SOURCE_DIR}/../lib
62 | /usr/local/lib
63 | /usr/lib
64 | )
65 | ENDIF(WIN32)
66 |
67 | SET(LibDir
68 | ${scream_SOURCE_DIR}/../lib
69 | )
70 |
71 | message("LibDir directories:" ${LibDir})
72 |
73 | # Include directories
74 | INCLUDE_DIRECTORIES(
75 | ${scream_SOURCE_DIR}/../include
76 | )
77 |
78 | ADD_SUBDIRECTORY( code)
79 |
--------------------------------------------------------------------------------
/multicam/receiver/scream/code/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # source files
2 | SET(SRCS
3 | ../../../../code/ScreamRx.cpp
4 | scream_receiver.cpp
5 | )
6 |
7 | SET(HEADERS
8 | ../../../../code/ScreamRx.h
9 | )
10 |
11 | SET(SRC_1
12 | ${SRCS}
13 | scream_receiver.cpp
14 | )
15 |
16 | INCLUDE_DIRECTORIES(
17 | ${screamIncludes}
18 | ../../../../code/
19 | )
20 |
21 | LINK_DIRECTORIES(
22 | ${screamLink}
23 | )
24 |
25 | ADD_EXECUTABLE(scream_receiver ${SRC_1} ${HEADERS})
26 |
27 |
28 | TARGET_LINK_LIBRARIES (
29 | scream_receiver
30 | ${screamLibs}
31 | )
32 |
--------------------------------------------------------------------------------
/multicam/receiver/startreceiver-intel.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | export UDP_PORT_VIDEO=51000
4 |
5 | # UDP source ports mahy on occations become remapped, therefore this extra code is needed
6 | # to make sure that RTCP feedback to sender side finds its way through
7 | # This is normally not something that is needed if VPN is used
8 | SND_IP_PORT=$(sudo tcpdump -c 1 -n udp port $UDP_PORT_VIDEO 2> /dev/null | sed -e 's/.*IP\(.*\)>.*/\1/')
9 | UDP_SRC_PORT=$(echo $SND_IP_PORT | sed -e 's/.*\.//')
10 | SENDER_IP=$(echo $SND_IP_PORT | sed 's![^.]*$!!' | sed 's/.$//')
11 |
12 | DATE=`date +%y-%m-%d_%H%M%S`
13 | echo "Video streaming IP address and UDP source port " $SENDER_IP " " $UDP_SRC_PORT
14 |
15 | export SND_IP
16 | export UDP_SRC_PORT
17 | ./rendermedia-intel.sh $SENDER_IP $UDP_PORT_VIDEO $UDP_SRC_PORT $DATE
18 |
--------------------------------------------------------------------------------
/multicam/receiver/startreceiver.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | export UDP_PORT_VIDEO=51000
4 |
5 | # UDP source ports mahy on occations become remapped, therefore this extra code is needed
6 | # to make sure that RTCP feedback to sender side finds its way through
7 | # This is normally not something that is needed if VPN is used
8 | SND_IP_PORT=$(sudo tcpdump -c 1 -n udp port $UDP_PORT_VIDEO 2> /dev/null | sed -e 's/.*IP\(.*\)>.*/\1/')
9 | UDP_SRC_PORT=$(echo $SND_IP_PORT | sed -e 's/.*\.//')
10 | SENDER_IP=$(echo $SND_IP_PORT | sed 's![^.]*$!!' | sed 's/.$//')
11 |
12 | DATE=`date +%y-%m-%d_%H%M%S`
13 | echo "Video streaming IP address and UDP source port " $SND_IP " " $UDP_SRC_PORT
14 |
15 | export SND_IP
16 | export UDP_SRC_PORT
17 | ./rendermedia.sh $SENDER_IP $UDP_PORT_VIDEO $UDP_SRC_PORT $DATE
18 |
--------------------------------------------------------------------------------
/multicam/sender/LICENSE.dat:
--------------------------------------------------------------------------------
1 | Copyright (c) 2021 Ericsson AB
2 | All rights reserved.
3 | Redistribution and use in source and binary forms, with or without modification, are permitted (subject to the limitations in the disclaimer below) provided that the following conditions are met:
4 |
5 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
7 | * Neither the name of Ericsson AB nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
8 |
9 | NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
/multicam/sender/README.md:
--------------------------------------------------------------------------------
1 | # Sender side build instructions
2 |
3 | The NVIDIA is built with the Jetpack and install scripts provided by e-consystems.com upon purchase of the cameras. Make sure that the correct Jetpack version is used as e-consystems may lag behind the Jetpack updates slighly.
4 |
5 | The sender side platform contains interfacing with the gstreamer framework
6 | and the SCReAM congestion control. The SCReAM congestion control is currently
7 | run in a stand alone application outside the gstreamer pipeline as it is necessary
8 | to congestion control 2 streams
9 |
10 | ## codecctrl
11 | The gstreamer codec control is a plugin that serves as an interface between the SCReAM multi
12 | stream congestion control and the gstreamer video encoding entities
13 |
14 | **1. Install applicable gstreamer thingys**
15 | You need these
16 | https://developer.ridgerun.com/wiki/index.php?title=Setting_a_GStreamer_Alternative_Environment
17 | `sudo apt-get install pkg-config bison flex git libglib2.0-dev liborc-0.4-dev libtool autopoint autoconf gettext yasm`
18 |
19 | From https://gstreamer.freedesktop.org/documentation/installing/on-linux.html
20 | `$ apt-get install libgstreamer1.0-0 gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-doc gstreamer1.0-tools gstreamer1.0-x`
21 |
22 | In addition you need
23 |
24 | `$ sudo apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev`
25 |
26 | **2. Set path**
27 |
28 | `export GST_PLUGIN_PATH=/usr/local/lib/gstreamer-1.0/`
29 |
30 | **3. Make codecctrl plugin**
31 |
32 | `cd ./gst-codec-ctrl/gst-plugin`
33 |
34 | `chmod +x autogen.sh`
35 |
36 | `chmod +x config.status`
37 |
38 | `./autogen.sh`
39 |
40 | `sudo make install`
41 |
42 | **Issue.** File glibconfig.h is missing when gscream plugin is built.
43 |
44 | **Solution** copy file glibconfig.h from
45 | /usr/lib/aarch64-linux-gnu/glib-2.0/include/ (or where it may be)
46 | to
47 | /usr/include/glib-2.0
48 |
49 | **4. Install v4l2-ctl
50 | `sudo apt-get install -y v4l-utils`
51 |
52 | **5. Build SCReAM sender side
53 | The SCReAM sender side is built with the instructions
54 | `$ cd ./scream`
55 | `$ cmake .`
56 | `$ make`
57 |
58 | To enable SCReAM V2, change SET(CMAKE_CXX_FLAGS "-fPIC -fpermissive -pthread") to SET(CMAKE_CXX_FLAGS "-fPIC -fpermissive -pthread -DV2") in CMakeLists.txt
59 | Note also then that SCREAM_VERSION="V2" is needed in startsender.sh
60 |
61 |
62 | **5. Start streaming
63 | `$ ./startsender.sh`
64 |
65 | To ensure proper function it is recommended to start the sender side first, then the receiver side. Or more correctly, the remote end that is connected to a cellular modem should be started first. This can avoid issues with remapped ports.
66 |
--------------------------------------------------------------------------------
/multicam/sender/default.scream:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricssonResearch/scream/5d5e4ca2c41ad62875314e5e8d2571efd58aad6a/multicam/sender/default.scream
--------------------------------------------------------------------------------
/multicam/sender/gst-codec-ctrl/gst-plugin/AUTHORS:
--------------------------------------------------------------------------------
1 | Thomas Vander Stichele
2 |
--------------------------------------------------------------------------------
/multicam/sender/gst-codec-ctrl/gst-plugin/COPYING:
--------------------------------------------------------------------------------
1 | Put your license in here!
2 |
3 |
--------------------------------------------------------------------------------
/multicam/sender/gst-codec-ctrl/gst-plugin/ChangeLog:
--------------------------------------------------------------------------------
1 | 2008-11-04 Stefan Kost
2 |
3 | * src/Makefile.am:
4 | Don't install static libs for plugins. Fixes #550851 for the template.
5 |
6 | 2008-10-30 Stefan Kost
7 |
8 | * tools/make_element:
9 | Don't replace GstPlugin.
10 |
11 | 2008-08-11 Stefan Kost
12 |
13 | * README:
14 | * src/gstaudiofilter.c:
15 | * src/gstplugin.c:
16 | * src/gsttransform.c:
17 | * tools/make_element:
18 | Integrate new template and improve search'n'replace ops. Update
19 | templates to use current API.
20 |
21 | 2008-07-26 Stefan Kost
22 |
23 | * tools/make_element:
24 | Fix username detection. tries getent first and falls back to grep
25 | passwd. Spotted by Karoly Segesdi.
26 |
27 | 2008-06-09 Jan Schmidt
28 |
29 | * src/gstplugin.c:
30 | Fix some memory leaks, and make the setcaps function actually
31 | sets the caps on the other pad.
32 |
33 | 2008-05-08 Stefan Kost
34 |
35 | * README:
36 | Add simple usage explanation and make it look like the other READMEs.
37 |
38 | * src/gstplugin.c:
39 | * src/gstplugin.h:
40 | * src/gsttransform.c:
41 | * src/gsttransform.h:
42 | * tools/make_element:
43 | Add year, username and email fields. Update the templates here and
44 | there a bit. Add more comments.
45 |
46 | 2007-08-01 Tim-Philipp Müller
47 |
48 | * src/gsttransform.c:
49 | Include right header to avoid structure size mismatches etc.
50 |
51 | 2007-07-25 Tim-Philipp Müller
52 |
53 | Patch by: Steve Fink
54 |
55 | * src/gstplugin.c:
56 | Use GST_DEBUG_FUNCPTR() macros where it makes sense.
57 |
58 | 2007-07-19 Stefan Kost
59 |
60 | * configure.ac:
61 | Fix CVS-build detection.
62 |
63 | 2007-01-23 Tim-Philipp Müller
64 |
65 | * src/Makefile.am:
66 | Make clearer which Makefile variables need renaming if the plugin
67 | name is changes (#399746) (pretty it is not, but it's the content
68 | that counts, right?)
69 |
70 | 2007-01-22 Tim-Philipp Müller
71 |
72 | Patch by: Philip Jägenstedt
73 |
74 | * tools/make_element:
75 | Translate FOO_IS_MY_PLUGIN macro as well according to the template
76 | (#399323).
77 |
78 | 2006-07-04 Tim-Philipp Müller
79 |
80 | * autogen.sh:
81 | Run autoheader to create config.h.in and fix the build.`
82 |
83 | 2006-07-03 Tim-Philipp Müller
84 |
85 | * Makefile.am:
86 | * autogen.sh:
87 | * gst-autogen.sh:
88 | Throw an error if autotools versions are too old. We require
89 | automake 1.7 or newer (#346054). Add gst-autogen.sh to check
90 | for this.
91 |
92 | * COPYING:
93 | Add placeholder COPYING file so it doesn't get overwritten
94 | by a GPL one by automake.
95 |
96 | 2006-06-22 Tim-Philipp Müller
97 |
98 | Patch by: Philip Jägenstedt
99 |
100 | * src/gstplugin.c: (gst_plugin_template_base_init),
101 | (gst_plugin_template_class_init), (gst_plugin_template_init),
102 | (plugin_init):
103 | Use GST_BOILERPLATE, add debug category (#345601).
104 |
105 | 2006-04-20 Stefan Kost
106 |
107 | Patch by: Johan Rydberg
108 |
109 | * src/gstplugin.c: (gst_plugin_template_get_type),
110 | (gst_plugin_template_base_init), (gst_plugin_template_class_init),
111 | (gst_plugin_template_set_property),
112 | (gst_plugin_template_get_property):
113 | * src/gstplugin.h:
114 | * src/gsttransform.c: (gst_plugin_template_base_init),
115 | (gst_plugin_template_set_property),
116 | (gst_plugin_template_get_property):
117 | * tools/make_element:
118 | remove double gst_get_, fix '_' in names
119 |
120 |
121 | 2006-02-26 Tim-Philipp Müller
122 |
123 | * src/gstplugin.c: (gst_plugin_template_init),
124 | (gst_plugin_template_chain):
125 | Fix function declaration of _init() function.
126 | Remove unnecessary assertion clutter in chain function
127 | (that also failed to return a flow value, causing
128 | compiler warnings).
129 |
130 | 2006-02-07 Stefan Kost
131 |
132 | * src/gstplugin.c: (gst_plugin_template_set_caps),
133 | (gst_plugin_template_chain):
134 | * src/gsttransform.c: (gst_plugin_template_transform_ip):
135 | more code cleanups, more comments
136 |
137 | 2006-02-07 Stefan Kost
138 |
139 | * configure.ac:
140 | allow installing to $HOME
141 | * src/gstplugin.c: (gst_plugin_template_base_init),
142 | (gst_plugin_template_init):
143 | * src/gstplugin.h:
144 | * src/gsttransform.c: (gst_plugin_template_base_init),
145 | (gst_plugin_template_class_init), (gst_plugin_template_init),
146 | (gst_plugin_template_transform_ip),
147 | (gst_plugin_template_set_property),
148 | (gst_plugin_template_get_property), (plugin_init):
149 | * src/gsttransform.h:
150 | add another template
151 | * tools/make_element:
152 | fix generator, when template (arg2) is given
153 |
154 | 2006-01-23 Tim-Philipp Müller
155 |
156 | * src/gstplugin.h:
157 | FOO_BAR_CLASS(klass) should cast to FooBarClass*,
158 | not FooBar*.
159 |
160 | 2006-01-13 Thomas Vander Stichele
161 |
162 | * autogen.sh:
163 | * configure.ac:
164 | * src/Makefile.am:
165 | * src/gstplugin.c:
166 | bring into the 0.10 world
167 | Fix #315582
168 |
169 | 2005-12-16 Jan Schmidt
170 |
171 | * src/gstplugin.c: (gst_plugin_template_class_init):
172 | Need to have the set_property and get_property methods
173 | before installing properties
174 |
175 | 2005-12-14 Tim-Philipp Müller
176 |
177 | * src/gstplugin.h:
178 | Fix GST_IS_FOO_BAR_CLASS macro.
179 |
180 | 2005-06-30 Ronald S. Bultje
181 |
182 | * configure.ac:
183 | * src/gstplugin.c: (gst_plugin_template_set_caps),
184 | (gst_plugin_template_init), (gst_plugin_template_chain):
185 | Fix for GStreamer 0.9.
186 |
187 | 2004-04-22 Thomas Vander Stichele
188 |
189 | * Makefile.am:
190 | * autogen.sh:
191 | * configure.ac:
192 | * src/Makefile.am:
193 | use proper LDFLAGS for plugins
194 | run in maintainer mode by default
195 |
196 | 2004-04-22 Thomas Vander Stichele
197 |
198 | * configure.ac: ... and fix comments too
199 |
200 | 2004-04-03 Benjamin Otte
201 |
202 | * configure.ac:
203 | update for GStreamer 0.8
204 |
205 | 2004-01-25 Ronald Bultje
206 |
207 | * src/gstplugin.c: (gst_plugin_template_link),
208 | (gst_plugin_template_base_init), (gst_plugin_template_init):
209 | Fix for GStreamer 0.7.x.
210 |
211 | 2003-02-06 Thomas Vander Stichele
212 |
213 | * updated for GStreamer 0.6.0
214 |
215 | 2002-07-17 Thomas Vander Stichele
216 |
217 | * initial creation on a flight to New York
218 |
--------------------------------------------------------------------------------
/multicam/sender/gst-codec-ctrl/gst-plugin/Makefile.am:
--------------------------------------------------------------------------------
1 | SUBDIRS = src
2 |
3 | EXTRA_DIST = autogen.sh
4 |
--------------------------------------------------------------------------------
/multicam/sender/gst-codec-ctrl/gst-plugin/NEWS:
--------------------------------------------------------------------------------
1 | Nothing much yet.
2 |
--------------------------------------------------------------------------------
/multicam/sender/gst-codec-ctrl/gst-plugin/README:
--------------------------------------------------------------------------------
1 | WHAT IT IS
2 | ----------
3 |
4 | gst-plugin is a template for writing your own GStreamer plug-in.
5 |
6 | The code is deliberately kept simple so that you quickly understand the basics
7 | of how to set up autotools and your source tree.
8 |
9 | This template demonstrates :
10 | - what to do in autogen.sh
11 | - how to setup configure.ac (your package name and version, GStreamer flags)
12 | - how to setup your source dir
13 | - what to put in Makefile.am
14 |
15 | More features and templates might get added later on.
16 |
17 | HOW TO USE IT
18 | -------------
19 |
20 | To use it, either make a copy for yourself and rename the parts or use the
21 | make_element script in tools. To create sources for "myfilter" based on the
22 | "gsttransform" template run:
23 |
24 | cd src;
25 | ../tools/make_element myfilter gsttransform
26 |
27 | This will create gstmyfilter.c and gstmyfilter.h. Open them in an editor and
28 | start editing. There are several occurances of the string "template", update
29 | those with real values. The plugin will be called 'myfilter' and it will have
30 | one element called 'myfilter' too. Also look for "FIXME:" markers that point you
31 | to places where you need to edit the code.
32 |
33 | You still need to adjust the Makefile.am.
34 |
35 |
--------------------------------------------------------------------------------
/multicam/sender/gst-codec-ctrl/gst-plugin/autogen.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # you can either set the environment variables AUTOCONF, AUTOHEADER, AUTOMAKE,
3 | # ACLOCAL, AUTOPOINT and/or LIBTOOLIZE to the right versions, or leave them
4 | # unset and get the defaults
5 |
6 | autoreconf --verbose --force --install --make || {
7 | echo 'autogen.sh failed';
8 | exit 1;
9 | }
10 |
11 | ./configure || {
12 | echo 'configure failed';
13 | exit 1;
14 | }
15 |
16 | echo
17 | echo "Now type 'make' to compile this module."
18 | echo
19 |
--------------------------------------------------------------------------------
/multicam/sender/gst-codec-ctrl/gst-plugin/config.h:
--------------------------------------------------------------------------------
1 | /* config.h. Generated from config.h.in by configure. */
2 | /* config.h.in. Generated from configure.ac by autoheader. */
3 |
4 | /* Define to 1 if you have the header file. */
5 | #define HAVE_DLFCN_H 1
6 |
7 | /* Define to 1 if you have the header file. */
8 | #define HAVE_INTTYPES_H 1
9 |
10 | /* Define to 1 if you have the header file. */
11 | #define HAVE_MEMORY_H 1
12 |
13 | /* Define to 1 if you have the header file. */
14 | #define HAVE_STDINT_H 1
15 |
16 | /* Define to 1 if you have the header file. */
17 | #define HAVE_STDLIB_H 1
18 |
19 | /* Define to 1 if you have the header file. */
20 | #define HAVE_STRINGS_H 1
21 |
22 | /* Define to 1 if you have the header file. */
23 | #define HAVE_STRING_H 1
24 |
25 | /* Define to 1 if you have the header file. */
26 | #define HAVE_SYS_STAT_H 1
27 |
28 | /* Define to 1 if you have the header file. */
29 | #define HAVE_SYS_TYPES_H 1
30 |
31 | /* Define to 1 if you have the header file. */
32 | #define HAVE_UNISTD_H 1
33 |
34 | /* Define to the sub-directory where libtool stores uninstalled libraries. */
35 | #define LT_OBJDIR ".libs/"
36 |
37 | /* Name of package */
38 | #define PACKAGE "my-plugin-package"
39 |
40 | /* Define to the address where bug reports for this package should be sent. */
41 | #define PACKAGE_BUGREPORT ""
42 |
43 | /* Define to the full name of this package. */
44 | #define PACKAGE_NAME "my-plugin-package"
45 |
46 | /* Define to the full name and version of this package. */
47 | #define PACKAGE_STRING "my-plugin-package 1.0.0"
48 |
49 | /* Define to the one symbol short name of this package. */
50 | #define PACKAGE_TARNAME "my-plugin-package"
51 |
52 | /* Define to the home page for this package. */
53 | #define PACKAGE_URL ""
54 |
55 | /* Define to the version of this package. */
56 | #define PACKAGE_VERSION "1.0.0"
57 |
58 | /* Define to 1 if you have the ANSI C header files. */
59 | #define STDC_HEADERS 1
60 |
61 | /* Version number of package */
62 | #define VERSION "1.0.0"
63 |
--------------------------------------------------------------------------------
/multicam/sender/gst-codec-ctrl/gst-plugin/config.h.in:
--------------------------------------------------------------------------------
1 | /* config.h.in. Generated from configure.ac by autoheader. */
2 |
3 | /* Define to 1 if you have the header file. */
4 | #undef HAVE_DLFCN_H
5 |
6 | /* Define to 1 if you have the header file. */
7 | #undef HAVE_INTTYPES_H
8 |
9 | /* Define to 1 if you have the header file. */
10 | #undef HAVE_MEMORY_H
11 |
12 | /* Define to 1 if you have the header file. */
13 | #undef HAVE_STDINT_H
14 |
15 | /* Define to 1 if you have the header file. */
16 | #undef HAVE_STDLIB_H
17 |
18 | /* Define to 1 if you have the header file. */
19 | #undef HAVE_STRINGS_H
20 |
21 | /* Define to 1 if you have the header file. */
22 | #undef HAVE_STRING_H
23 |
24 | /* Define to 1 if you have the header file. */
25 | #undef HAVE_SYS_STAT_H
26 |
27 | /* Define to 1 if you have the header file. */
28 | #undef HAVE_SYS_TYPES_H
29 |
30 | /* Define to 1 if you have the header file. */
31 | #undef HAVE_UNISTD_H
32 |
33 | /* Define to the sub-directory where libtool stores uninstalled libraries. */
34 | #undef LT_OBJDIR
35 |
36 | /* Name of package */
37 | #undef PACKAGE
38 |
39 | /* Define to the address where bug reports for this package should be sent. */
40 | #undef PACKAGE_BUGREPORT
41 |
42 | /* Define to the full name of this package. */
43 | #undef PACKAGE_NAME
44 |
45 | /* Define to the full name and version of this package. */
46 | #undef PACKAGE_STRING
47 |
48 | /* Define to the one symbol short name of this package. */
49 | #undef PACKAGE_TARNAME
50 |
51 | /* Define to the home page for this package. */
52 | #undef PACKAGE_URL
53 |
54 | /* Define to the version of this package. */
55 | #undef PACKAGE_VERSION
56 |
57 | /* Define to 1 if you have the ANSI C header files. */
58 | #undef STDC_HEADERS
59 |
60 | /* Version number of package */
61 | #undef VERSION
62 |
--------------------------------------------------------------------------------
/multicam/sender/gst-codec-ctrl/gst-plugin/config.h.in~:
--------------------------------------------------------------------------------
1 | /* config.h.in. Generated from configure.ac by autoheader. */
2 |
3 | /* Define to 1 if you have the header file. */
4 | #undef HAVE_DLFCN_H
5 |
6 | /* Define to 1 if you have the header file. */
7 | #undef HAVE_INTTYPES_H
8 |
9 | /* Define to 1 if you have the header file. */
10 | #undef HAVE_MEMORY_H
11 |
12 | /* Define to 1 if you have the header file. */
13 | #undef HAVE_STDINT_H
14 |
15 | /* Define to 1 if you have the header file. */
16 | #undef HAVE_STDLIB_H
17 |
18 | /* Define to 1 if you have the header file. */
19 | #undef HAVE_STRINGS_H
20 |
21 | /* Define to 1 if you have the header file. */
22 | #undef HAVE_STRING_H
23 |
24 | /* Define to 1 if you have the header file. */
25 | #undef HAVE_SYS_STAT_H
26 |
27 | /* Define to 1 if you have the header file. */
28 | #undef HAVE_SYS_TYPES_H
29 |
30 | /* Define to 1 if you have the header file. */
31 | #undef HAVE_UNISTD_H
32 |
33 | /* Define to the sub-directory where libtool stores uninstalled libraries. */
34 | #undef LT_OBJDIR
35 |
36 | /* Name of package */
37 | #undef PACKAGE
38 |
39 | /* Define to the address where bug reports for this package should be sent. */
40 | #undef PACKAGE_BUGREPORT
41 |
42 | /* Define to the full name of this package. */
43 | #undef PACKAGE_NAME
44 |
45 | /* Define to the full name and version of this package. */
46 | #undef PACKAGE_STRING
47 |
48 | /* Define to the one symbol short name of this package. */
49 | #undef PACKAGE_TARNAME
50 |
51 | /* Define to the home page for this package. */
52 | #undef PACKAGE_URL
53 |
54 | /* Define to the version of this package. */
55 | #undef PACKAGE_VERSION
56 |
57 | /* Define to 1 if you have the ANSI C header files. */
58 | #undef STDC_HEADERS
59 |
60 | /* Version number of package */
61 | #undef VERSION
62 |
--------------------------------------------------------------------------------
/multicam/sender/gst-codec-ctrl/gst-plugin/configure.ac:
--------------------------------------------------------------------------------
1 | dnl required version of autoconf
2 | AC_PREREQ([2.53])
3 |
4 | dnl TODO: fill in your package name and package version here
5 | AC_INIT([my-plugin-package],[1.0.0])
6 |
7 | dnl required versions of gstreamer and plugins-base
8 | GST_REQUIRED=1.0.0
9 | GSTPB_REQUIRED=1.0.0
10 |
11 | AC_CONFIG_SRCDIR([src/gstplugin.cpp])
12 | AC_CONFIG_HEADERS([config.h])
13 |
14 | dnl required version of automake
15 | AM_INIT_AUTOMAKE([1.10])
16 |
17 | dnl enable mainainer mode by default
18 | AM_MAINTAINER_MODE([enable])
19 |
20 | dnl check for tools (compiler etc.)
21 | AC_PROG_CC
22 |
23 | AC_PROG_CXX
24 | dnl required version of libtool
25 | LT_PREREQ([2.2.6])
26 | LT_INIT
27 |
28 | dnl give error and exit if we don't have pkgconfig
29 | AC_CHECK_PROG(HAVE_PKGCONFIG, pkg-config, [ ], [
30 | AC_MSG_ERROR([You need to have pkg-config installed!])
31 | ])
32 |
33 | dnl Check for the required version of GStreamer core (and gst-plugins-base)
34 | dnl This will export GST_CFLAGS and GST_LIBS variables for use in Makefile.am
35 | dnl
36 | dnl If you need libraries from gst-plugins-base here, also add:
37 | dnl for libgstaudio-1.0: gstreamer-audio-1.0 >= $GST_REQUIRED
38 | dnl for libgstvideo-1.0: gstreamer-video-1.0 >= $GST_REQUIRED
39 | dnl for libgsttag-1.0: gstreamer-tag-1.0 >= $GST_REQUIRED
40 | dnl for libgstpbutils-1.0: gstreamer-pbutils-1.0 >= $GST_REQUIRED
41 | dnl for libgstfft-1.0: gstreamer-fft-1.0 >= $GST_REQUIRED
42 | dnl for libgstinterfaces-1.0: gstreamer-interfaces-1.0 >= $GST_REQUIRED
43 | dnl for libgstrtp-1.0: gstreamer-rtp-1.0 >= $GST_REQUIRED
44 | dnl for libgstrtsp-1.0: gstreamer-rtsp-1.0 >= $GST_REQUIRED
45 | dnl etc.
46 | PKG_CHECK_MODULES(GST, [
47 | gstreamer-1.0 >= $GST_REQUIRED
48 | gstreamer-base-1.0 >= $GST_REQUIRED
49 | gstreamer-controller-1.0 >= $GST_REQUIRED
50 | gstreamer-audio-1.0 >= $GST_REQUIRED
51 | gstreamer-rtp-1.0 >= $GST_REQUIRED
52 | ], [
53 | AC_SUBST(GST_CFLAGS)
54 | AC_SUBST(GST_LIBS)
55 | ], [
56 | AC_MSG_ERROR([
57 | You need to install or upgrade the GStreamer development
58 | packages on your system. On debian-based systems these are
59 | libgstreamer1.0-dev and libgstreamer-plugins-base1.0-dev.
60 | on RPM-based systems gstreamer1.0-devel, libgstreamer1.0-devel
61 | or similar. The minimum version required is $GST_REQUIRED.
62 | ])
63 | ])
64 |
65 | dnl check if compiler understands -Wall (if yes, add -Wall to GST_CFLAGS)
66 | AC_MSG_CHECKING([to see if compiler understands -Wall])
67 | save_CFLAGS="$CFLAGS"
68 | CFLAGS="$CFLAGS -Wall"
69 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ ], [ ])], [
70 | GST_CFLAGS="$GST_CFLAGS -Wall"
71 | AC_MSG_RESULT([yes])
72 | ], [
73 | AC_MSG_RESULT([no])
74 | ])
75 |
76 | dnl set the plugindir where plugins should be installed (for src/Makefile.am)
77 | if test "x${prefix}" = "x$HOME"; then
78 | plugindir="$HOME/.gstreamer-1.0/plugins"
79 | else
80 | plugindir="\$(libdir)/gstreamer-1.0"
81 | fi
82 | AC_SUBST(plugindir)
83 |
84 | dnl set proper LDFLAGS for plugins
85 | GST_PLUGIN_LDFLAGS='-module -avoid-version -export-symbols-regex [_]*\(gst_\|Gst\|GST_\).*'
86 | AC_SUBST(GST_PLUGIN_LDFLAGS)
87 |
88 | AC_CONFIG_FILES([Makefile src/Makefile])
89 | AC_OUTPUT
90 |
--------------------------------------------------------------------------------
/multicam/sender/gst-codec-ctrl/gst-plugin/missing:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 | # Common wrapper for a few potentially missing GNU programs.
3 |
4 | scriptversion=2013-10-28.13; # UTC
5 |
6 | # Copyright (C) 1996-2014 Free Software Foundation, Inc.
7 | # Originally written by Fran,cois Pinard , 1996.
8 |
9 | # This program is free software; you can redistribute it and/or modify
10 | # it under the terms of the GNU General Public License as published by
11 | # the Free Software Foundation; either version 2, or (at your option)
12 | # any later version.
13 |
14 | # This program is distributed in the hope that it will be useful,
15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | # GNU General Public License for more details.
18 |
19 | # You should have received a copy of the GNU General Public License
20 | # along with this program. If not, see .
21 |
22 | # As a special exception to the GNU General Public License, if you
23 | # distribute this file as part of a program that contains a
24 | # configuration script generated by Autoconf, you may include it under
25 | # the same distribution terms that you use for the rest of that program.
26 |
27 | if test $# -eq 0; then
28 | echo 1>&2 "Try '$0 --help' for more information"
29 | exit 1
30 | fi
31 |
32 | case $1 in
33 |
34 | --is-lightweight)
35 | # Used by our autoconf macros to check whether the available missing
36 | # script is modern enough.
37 | exit 0
38 | ;;
39 |
40 | --run)
41 | # Back-compat with the calling convention used by older automake.
42 | shift
43 | ;;
44 |
45 | -h|--h|--he|--hel|--help)
46 | echo "\
47 | $0 [OPTION]... PROGRAM [ARGUMENT]...
48 |
49 | Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
50 | to PROGRAM being missing or too old.
51 |
52 | Options:
53 | -h, --help display this help and exit
54 | -v, --version output version information and exit
55 |
56 | Supported PROGRAM values:
57 | aclocal autoconf autoheader autom4te automake makeinfo
58 | bison yacc flex lex help2man
59 |
60 | Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
61 | 'g' are ignored when checking the name.
62 |
63 | Send bug reports to ."
64 | exit $?
65 | ;;
66 |
67 | -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
68 | echo "missing $scriptversion (GNU Automake)"
69 | exit $?
70 | ;;
71 |
72 | -*)
73 | echo 1>&2 "$0: unknown '$1' option"
74 | echo 1>&2 "Try '$0 --help' for more information"
75 | exit 1
76 | ;;
77 |
78 | esac
79 |
80 | # Run the given program, remember its exit status.
81 | "$@"; st=$?
82 |
83 | # If it succeeded, we are done.
84 | test $st -eq 0 && exit 0
85 |
86 | # Also exit now if we it failed (or wasn't found), and '--version' was
87 | # passed; such an option is passed most likely to detect whether the
88 | # program is present and works.
89 | case $2 in --version|--help) exit $st;; esac
90 |
91 | # Exit code 63 means version mismatch. This often happens when the user
92 | # tries to use an ancient version of a tool on a file that requires a
93 | # minimum version.
94 | if test $st -eq 63; then
95 | msg="probably too old"
96 | elif test $st -eq 127; then
97 | # Program was missing.
98 | msg="missing on your system"
99 | else
100 | # Program was found and executed, but failed. Give up.
101 | exit $st
102 | fi
103 |
104 | perl_URL=http://www.perl.org/
105 | flex_URL=http://flex.sourceforge.net/
106 | gnu_software_URL=http://www.gnu.org/software
107 |
108 | program_details ()
109 | {
110 | case $1 in
111 | aclocal|automake)
112 | echo "The '$1' program is part of the GNU Automake package:"
113 | echo "<$gnu_software_URL/automake>"
114 | echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
115 | echo "<$gnu_software_URL/autoconf>"
116 | echo "<$gnu_software_URL/m4/>"
117 | echo "<$perl_URL>"
118 | ;;
119 | autoconf|autom4te|autoheader)
120 | echo "The '$1' program is part of the GNU Autoconf package:"
121 | echo "<$gnu_software_URL/autoconf/>"
122 | echo "It also requires GNU m4 and Perl in order to run:"
123 | echo "<$gnu_software_URL/m4/>"
124 | echo "<$perl_URL>"
125 | ;;
126 | esac
127 | }
128 |
129 | give_advice ()
130 | {
131 | # Normalize program name to check for.
132 | normalized_program=`echo "$1" | sed '
133 | s/^gnu-//; t
134 | s/^gnu//; t
135 | s/^g//; t'`
136 |
137 | printf '%s\n' "'$1' is $msg."
138 |
139 | configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
140 | case $normalized_program in
141 | autoconf*)
142 | echo "You should only need it if you modified 'configure.ac',"
143 | echo "or m4 files included by it."
144 | program_details 'autoconf'
145 | ;;
146 | autoheader*)
147 | echo "You should only need it if you modified 'acconfig.h' or"
148 | echo "$configure_deps."
149 | program_details 'autoheader'
150 | ;;
151 | automake*)
152 | echo "You should only need it if you modified 'Makefile.am' or"
153 | echo "$configure_deps."
154 | program_details 'automake'
155 | ;;
156 | aclocal*)
157 | echo "You should only need it if you modified 'acinclude.m4' or"
158 | echo "$configure_deps."
159 | program_details 'aclocal'
160 | ;;
161 | autom4te*)
162 | echo "You might have modified some maintainer files that require"
163 | echo "the 'autom4te' program to be rebuilt."
164 | program_details 'autom4te'
165 | ;;
166 | bison*|yacc*)
167 | echo "You should only need it if you modified a '.y' file."
168 | echo "You may want to install the GNU Bison package:"
169 | echo "<$gnu_software_URL/bison/>"
170 | ;;
171 | lex*|flex*)
172 | echo "You should only need it if you modified a '.l' file."
173 | echo "You may want to install the Fast Lexical Analyzer package:"
174 | echo "<$flex_URL>"
175 | ;;
176 | help2man*)
177 | echo "You should only need it if you modified a dependency" \
178 | "of a man page."
179 | echo "You may want to install the GNU Help2man package:"
180 | echo "<$gnu_software_URL/help2man/>"
181 | ;;
182 | makeinfo*)
183 | echo "You should only need it if you modified a '.texi' file, or"
184 | echo "any other file indirectly affecting the aspect of the manual."
185 | echo "You might want to install the Texinfo package:"
186 | echo "<$gnu_software_URL/texinfo/>"
187 | echo "The spurious makeinfo call might also be the consequence of"
188 | echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
189 | echo "want to install GNU make:"
190 | echo "<$gnu_software_URL/make/>"
191 | ;;
192 | *)
193 | echo "You might have modified some files without having the proper"
194 | echo "tools for further handling them. Check the 'README' file, it"
195 | echo "often tells you about the needed prerequisites for installing"
196 | echo "this package. You may also peek at any GNU archive site, in"
197 | echo "case some other package contains this missing '$1' program."
198 | ;;
199 | esac
200 | }
201 |
202 | give_advice "$1" | sed -e '1s/^/WARNING: /' \
203 | -e '2,$s/^/ /' >&2
204 |
205 | # Propagate the correct exit status (expected to be 127 for a program
206 | # not found, 63 for a program that failed due to version mismatch).
207 | exit $st
208 |
209 | # Local variables:
210 | # eval: (add-hook 'write-file-hooks 'time-stamp)
211 | # time-stamp-start: "scriptversion="
212 | # time-stamp-format: "%:y-%02m-%02d.%02H"
213 | # time-stamp-time-zone: "UTC"
214 | # time-stamp-end: "; # UTC"
215 | # End:
216 |
--------------------------------------------------------------------------------
/multicam/sender/gst-codec-ctrl/gst-plugin/src/.libs/libgstcodecctrl.exp:
--------------------------------------------------------------------------------
1 | gst_g_codecctrl_get_type
2 | gst_plugin_codecctrl_get_desc
3 | gst_plugin_codecctrl_register
4 |
--------------------------------------------------------------------------------
/multicam/sender/gst-codec-ctrl/gst-plugin/src/.libs/libgstcodecctrl.lai:
--------------------------------------------------------------------------------
1 | # libgstcodecctrl.la - a libtool library file
2 | # Generated by libtool (GNU libtool) 2.4.6 Debian-2.4.6-2
3 | #
4 | # Please DO NOT delete this file!
5 | # It is necessary for linking the library.
6 |
7 | # The name that we can dlopen(3).
8 | dlname='libgstcodecctrl.so'
9 |
10 | # Names of this library.
11 | library_names='libgstcodecctrl.so libgstcodecctrl.so libgstcodecctrl.so'
12 |
13 | # The name of the static archive.
14 | old_library=''
15 |
16 | # Linker flags that cannot go in dependency_libs.
17 | inherited_linker_flags=''
18 |
19 | # Libraries that this one depends upon.
20 | dependency_libs=' -lgstvideo-1.0 -lgstcontroller-1.0 -lgstaudio-1.0 -lgstrtp-1.0 -lgstbase-1.0 -lgstreamer-1.0 -lgobject-2.0 -lglib-2.0'
21 |
22 | # Names of additional weak libraries provided by this library
23 | weak_library_names=''
24 |
25 | # Version information for libgstcodecctrl.
26 | current=0
27 | age=0
28 | revision=0
29 |
30 | # Is this an already installed library?
31 | installed=yes
32 |
33 | # Should we warn about portability when linking against -modules?
34 | shouldnotlink=yes
35 |
36 | # Files to dlopen/dlpreopen
37 | dlopen=''
38 | dlpreopen=''
39 |
40 | # Directory that this library needs to be installed in:
41 | libdir='/usr/local/lib/gstreamer-1.0'
42 |
--------------------------------------------------------------------------------
/multicam/sender/gst-codec-ctrl/gst-plugin/src/.libs/libgstcodecctrl.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricssonResearch/scream/5d5e4ca2c41ad62875314e5e8d2571efd58aad6a/multicam/sender/gst-codec-ctrl/gst-plugin/src/.libs/libgstcodecctrl.so
--------------------------------------------------------------------------------
/multicam/sender/gst-codec-ctrl/gst-plugin/src/Makefile.am:
--------------------------------------------------------------------------------
1 | # Note: plugindir is set in configure
2 |
3 | ##############################################################################
4 | # TODO: change libgstplugin.la to something else, e.g. libmysomething.la #
5 | ##############################################################################
6 | plugin_LTLIBRARIES = libgstcodecctrl.la
7 |
8 | ##############################################################################
9 | # TODO: for the next set of variables, name the prefix if you named the .la, #
10 | # e.g. libmysomething.la => libmysomething_la_SOURCES #
11 | # libmysomething_la_CFLAGS #
12 | # libmysomething_la_LIBADD #
13 | # libmysomething_la_LDFLAGS #
14 | ##############################################################################
15 |
16 | ## Plugin 1
17 |
18 | # sources used to compile this plug-in
19 | libgstcodecctrl_la_SOURCES = gstcodecctrl.cpp
20 |
21 | # compiler and linker flags used to compile this plugin, set in configure.ac
22 | libgstcodecctrl_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
23 | libgstcodecctrl_la_CXXFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CXXFLAGS)
24 | libgstcodecctrl_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstvideo-1.0 $(GST_LIBS) $(OPENH264_LIBS)
25 | libgstcodecctrl_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
26 | libgstcodecctrl_la_LIBTOOLFLAGS = --tag=disable-static
27 | INCLUDES=-I/usr/include/gstreamer-1.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include/
28 |
29 | # headers we need but don't want installed
30 | noinst_HEADERS = gstcodecctrl.h
31 |
--------------------------------------------------------------------------------
/multicam/sender/gst-codec-ctrl/gst-plugin/src/gstcodecctrl.h:
--------------------------------------------------------------------------------
1 | /*
2 | * GStreamer
3 | * Copyright (C) 2005 Thomas Vander Stichele
4 | * Copyright (C) 2005 Ronald S. Bultje
5 | * Copyright (C) 2018 <>
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a
8 | * copy of this software and associated documentation files (the "Software"),
9 | * to deal in the Software without restriction, including without limitation
10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 | * and/or sell copies of the Software, and to permit persons to whom the
12 | * Software is furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 | * DEALINGS IN THE SOFTWARE.
24 | *
25 | * Alternatively, the contents of this file may be used under the
26 | * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
27 | * which case the following provisions apply instead of the ones
28 | * mentioned above:
29 | *
30 | * This library is free software; you can redistribute it and/or
31 | * modify it under the terms of the GNU Library General Public
32 | * License as published by the Free Software Foundation; either
33 | * version 2 of the License, or (at your option) any later version.
34 | *
35 | * This library is distributed in the hope that it will be useful,
36 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
38 | * Library General Public License for more details.
39 | *
40 | * You should have received a copy of the GNU Library General Public
41 | * License along with this library; if not, write to the
42 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
43 | * Boston, MA 02111-1307, USA.
44 | */
45 |
46 | #ifndef __GST_CODECCTRL_H__
47 | #define __GST_CODECCTRL_H__
48 |
49 | #include
50 | #include
51 |
52 |
53 | G_BEGIN_DECLS
54 |
55 | /* #defines don't like whitespacey bits */
56 | #define GST_TYPE_CODECCTRL \
57 | (gst_g_codecctrl_get_type())
58 | #define GST_CODECCTRL(obj) \
59 | (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CODECCTRL,GstCodecCtrl))
60 | #define GST_CODECCTRL_CLASS(klass) \
61 | (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CODECCTRL,GstCodecCtrlClass))
62 | #define GST_IS_CODECCTRL(obj) \
63 | (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CODECCTRL))
64 | #define GST_IS_CODECCTRL_CLASS(klass) \
65 | (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CODECCTRL))
66 |
67 | typedef struct _GstCodecCtrl GstCodecCtrl;
68 | typedef struct _GstCodecCtrlClass GstCodecCtrlClass;
69 |
70 | struct _GstCodecCtrl
71 | {
72 | GstElement element;
73 |
74 | GstPad *sinkpad, *srcpad;
75 |
76 | gboolean silent;
77 |
78 | GstElement *encoder;
79 | GstClockID clockId;
80 |
81 | guint media_src;
82 | guint ctrl_port;
83 | };
84 |
85 | struct _GstCodecCtrlClass
86 | {
87 | GstElementClass parent_class;
88 | };
89 |
90 | GType gst_g_codecctrl_get_type (void);
91 |
92 | static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
93 | GST_PAD_SINK,
94 | GST_PAD_ALWAYS,
95 | GST_STATIC_CAPS ("ANY")
96 | );
97 |
98 | static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
99 | GST_PAD_SRC,
100 | GST_PAD_ALWAYS,
101 | GST_STATIC_CAPS ("ANY")
102 | );
103 |
104 | static void task_print_loop();
105 |
106 |
107 | #define gst_g_codecctrl_parent_class parent_class
108 | G_DEFINE_TYPE (GstCodecCtrl, gst_g_codecctrl, GST_TYPE_ELEMENT);
109 |
110 | static void gst_g_codecctrl_set_property (GObject * object, guint prop_id,
111 | const GValue * value, GParamSpec * pspec);
112 | static void gst_g_codecctrl_get_property (GObject * object, guint prop_id,
113 | GValue * value, GParamSpec * pspec);
114 |
115 | static gboolean gst_g_codecctrl_sink_event (GstPad * pad, GstObject * parent, GstEvent * event);
116 | static GstFlowReturn gst_g_codecctrl_chain (GstPad * pad, GstObject * parent, GstBuffer * buf);
117 |
118 |
119 | G_END_DECLS
120 |
121 |
122 | #endif /* __GST_CODECCTRL_H__ */
123 |
--------------------------------------------------------------------------------
/multicam/sender/gst-codec-ctrl/gst-plugin/src/gstplugin.h:
--------------------------------------------------------------------------------
1 | /*
2 | * GStreamer
3 | * Copyright (C) 2005 Thomas Vander Stichele
4 | * Copyright (C) 2005 Ronald S. Bultje
5 | * Copyright (C) YEAR AUTHOR_NAME AUTHOR_EMAIL
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a
8 | * copy of this software and associated documentation files (the "Software"),
9 | * to deal in the Software without restriction, including without limitation
10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 | * and/or sell copies of the Software, and to permit persons to whom the
12 | * Software is furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 | * DEALINGS IN THE SOFTWARE.
24 | *
25 | * Alternatively, the contents of this file may be used under the
26 | * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
27 | * which case the following provisions apply instead of the ones
28 | * mentioned above:
29 | *
30 | * This library is free software; you can redistribute it and/or
31 | * modify it under the terms of the GNU Library General Public
32 | * License as published by the Free Software Foundation; either
33 | * version 2 of the License, or (at your option) any later version.
34 | *
35 | * This library is distributed in the hope that it will be useful,
36 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
38 | * Library General Public License for more details.
39 | *
40 | * You should have received a copy of the GNU Library General Public
41 | * License along with this library; if not, write to the
42 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
43 | * Boston, MA 02111-1307, USA.
44 | */
45 |
46 | #ifndef __GST_PLUGIN_TEMPLATE_H__
47 | #define __GST_PLUGIN_TEMPLATE_H__
48 |
49 | #include
50 |
51 | G_BEGIN_DECLS
52 |
53 | /* #defines don't like whitespacey bits */
54 | #define GST_TYPE_PLUGIN_TEMPLATE \
55 | (gst_plugin_template_get_type())
56 | #define GST_PLUGIN_TEMPLATE(obj) \
57 | (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PLUGIN_TEMPLATE,GstPluginTemplate))
58 | #define GST_PLUGIN_TEMPLATE_CLASS(klass) \
59 | (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PLUGIN_TEMPLATE,GstPluginTemplateClass))
60 | #define GST_IS_PLUGIN_TEMPLATE(obj) \
61 | (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PLUGIN_TEMPLATE))
62 | #define GST_IS_PLUGIN_TEMPLATE_CLASS(klass) \
63 | (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PLUGIN_TEMPLATE))
64 |
65 | typedef struct _GstPluginTemplate GstPluginTemplate;
66 | typedef struct _GstPluginTemplateClass GstPluginTemplateClass;
67 |
68 | struct _GstPluginTemplate
69 | {
70 | GstElement element;
71 |
72 | GstPad *sinkpad, *srcpad;
73 |
74 | gboolean silent;
75 | };
76 |
77 | struct _GstPluginTemplateClass
78 | {
79 | GstElementClass parent_class;
80 | };
81 |
82 | GType gst_plugin_template_get_type (void);
83 |
84 | G_END_DECLS
85 |
86 | #endif /* __GST_PLUGIN_TEMPLATE_H__ */
87 |
--------------------------------------------------------------------------------
/multicam/sender/gst-codec-ctrl/gst-plugin/src/gsttransform.c:
--------------------------------------------------------------------------------
1 | /*
2 | * GStreamer
3 | * Copyright (C) 2006 Stefan Kost
4 | * Copyright (C) YEAR AUTHOR_NAME AUTHOR_EMAIL
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | /**
23 | * SECTION:element-plugin
24 | *
25 | * FIXME:Describe plugin here.
26 | *
27 | *
28 | * Example launch line
29 | * |[
30 | * gst-launch -v -m fakesrc ! plugin ! fakesink silent=TRUE
31 | * ]|
32 | *
33 | */
34 |
35 | #ifdef HAVE_CONFIG_H
36 | #include "config.h"
37 | #endif
38 |
39 | #include
40 | #include
41 | #include
42 |
43 | #include "gsttransform.h"
44 |
45 | GST_DEBUG_CATEGORY_STATIC (gst_plugin_template_debug);
46 | #define GST_CAT_DEFAULT gst_plugin_template_debug
47 |
48 | /* Filter signals and args */
49 | enum
50 | {
51 | /* FILL ME */
52 | LAST_SIGNAL
53 | };
54 |
55 | enum
56 | {
57 | PROP_0,
58 | PROP_SILENT,
59 | };
60 |
61 | /* the capabilities of the inputs and outputs.
62 | *
63 | * FIXME:describe the real formats here.
64 | */
65 | static GstStaticPadTemplate sink_template =
66 | GST_STATIC_PAD_TEMPLATE (
67 | "sink",
68 | GST_PAD_SINK,
69 | GST_PAD_ALWAYS,
70 | GST_STATIC_CAPS ("ANY")
71 | );
72 |
73 | static GstStaticPadTemplate src_template =
74 | GST_STATIC_PAD_TEMPLATE (
75 | "src",
76 | GST_PAD_SRC,
77 | GST_PAD_ALWAYS,
78 | GST_STATIC_CAPS ("ANY")
79 | );
80 |
81 | #define gst_plugin_template_parent_class parent_class
82 | G_DEFINE_TYPE (GstPluginTemplate, gst_plugin_template, GST_TYPE_BASE_TRANSFORM);
83 |
84 | static void gst_plugin_template_set_property (GObject * object, guint prop_id,
85 | const GValue * value, GParamSpec * pspec);
86 | static void gst_plugin_template_get_property (GObject * object, guint prop_id,
87 | GValue * value, GParamSpec * pspec);
88 |
89 | static GstFlowReturn gst_plugin_template_transform_ip (GstBaseTransform * base,
90 | GstBuffer * outbuf);
91 |
92 | /* GObject vmethod implementations */
93 |
94 | /* initialize the plugin's class */
95 | static void
96 | gst_plugin_template_class_init (GstPluginTemplateClass * klass)
97 | {
98 | GObjectClass *gobject_class;
99 | GstElementClass *gstelement_class;
100 |
101 | gobject_class = (GObjectClass *) klass;
102 | gstelement_class = (GstElementClass *) klass;
103 |
104 | gobject_class->set_property = gst_plugin_template_set_property;
105 | gobject_class->get_property = gst_plugin_template_get_property;
106 |
107 | g_object_class_install_property (gobject_class, PROP_SILENT,
108 | g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?",
109 | FALSE, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
110 |
111 | gst_element_class_set_details_simple (gstelement_class,
112 | "Plugin",
113 | "Generic/Filter",
114 | "FIXME:Generic Template Filter",
115 | "AUTHOR_NAME AUTHOR_EMAIL");
116 |
117 | gst_element_class_add_pad_template (gstelement_class,
118 | gst_static_pad_template_get (&src_template));
119 | gst_element_class_add_pad_template (gstelement_class,
120 | gst_static_pad_template_get (&sink_template));
121 |
122 | GST_BASE_TRANSFORM_CLASS (klass)->transform_ip =
123 | GST_DEBUG_FUNCPTR (gst_plugin_template_transform_ip);
124 |
125 | /* debug category for fltering log messages
126 | *
127 | * FIXME:exchange the string 'Template plugin' with your description
128 | */
129 | GST_DEBUG_CATEGORY_INIT (gst_plugin_template_debug, "plugin", 0, "Template plugin");
130 | }
131 |
132 | /* initialize the new element
133 | * initialize instance structure
134 | */
135 | static void
136 | gst_plugin_template_init (GstPluginTemplate *filter)
137 | {
138 | filter->silent = FALSE;
139 | }
140 |
141 | static void
142 | gst_plugin_template_set_property (GObject * object, guint prop_id,
143 | const GValue * value, GParamSpec * pspec)
144 | {
145 | GstPluginTemplate *filter = GST_PLUGIN_TEMPLATE (object);
146 |
147 | switch (prop_id) {
148 | case PROP_SILENT:
149 | filter->silent = g_value_get_boolean (value);
150 | break;
151 | default:
152 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
153 | break;
154 | }
155 | }
156 |
157 | static void
158 | gst_plugin_template_get_property (GObject * object, guint prop_id,
159 | GValue * value, GParamSpec * pspec)
160 | {
161 | GstPluginTemplate *filter = GST_PLUGIN_TEMPLATE (object);
162 |
163 | switch (prop_id) {
164 | case PROP_SILENT:
165 | g_value_set_boolean (value, filter->silent);
166 | break;
167 | default:
168 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
169 | break;
170 | }
171 | }
172 |
173 | /* GstBaseTransform vmethod implementations */
174 |
175 | /* this function does the actual processing
176 | */
177 | static GstFlowReturn
178 | gst_plugin_template_transform_ip (GstBaseTransform * base, GstBuffer * outbuf)
179 | {
180 | GstPluginTemplate *filter = GST_PLUGIN_TEMPLATE (base);
181 |
182 | if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (outbuf)))
183 | gst_object_sync_values (GST_OBJECT (filter), GST_BUFFER_TIMESTAMP (outbuf));
184 |
185 | if (filter->silent == FALSE)
186 | g_print ("I'm plugged, therefore I'm in.\n");
187 |
188 | /* FIXME: do something interesting here. This simply copies the source
189 | * to the destination. */
190 |
191 | return GST_FLOW_OK;
192 | }
193 |
194 |
195 | /* entry point to initialize the plug-in
196 | * initialize the plug-in itself
197 | * register the element factories and other features
198 | */
199 | static gboolean
200 | plugin_init (GstPlugin * plugin)
201 | {
202 | return gst_element_register (plugin, "plugin", GST_RANK_NONE,
203 | GST_TYPE_PLUGIN_TEMPLATE);
204 | }
205 |
206 | /* gstreamer looks for this structure to register plugins
207 | *
208 | * FIXME:exchange the string 'Template plugin' with you plugin description
209 | */
210 | GST_PLUGIN_DEFINE (
211 | GST_VERSION_MAJOR,
212 | GST_VERSION_MINOR,
213 | plugin,
214 | "Template plugin",
215 | plugin_init,
216 | VERSION,
217 | "LGPL",
218 | "GStreamer",
219 | "http://gstreamer.net/"
220 | )
221 |
--------------------------------------------------------------------------------
/multicam/sender/gst-codec-ctrl/gst-plugin/src/gsttransform.h:
--------------------------------------------------------------------------------
1 | /*
2 | * GStreamer
3 | * Copyright (C) 2006 Stefan Kost
4 | * Copyright (C) YEAR AUTHOR_NAME AUTHOR_EMAIL
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef __GST_PLUGIN_TEMPLATE_H__
23 | #define __GST_PLUGIN_TEMPLATE_H__
24 |
25 | #include
26 | #include
27 |
28 | G_BEGIN_DECLS
29 |
30 | #define GST_TYPE_PLUGIN_TEMPLATE \
31 | (gst_plugin_template_get_type())
32 | #define GST_PLUGIN_TEMPLATE(obj) \
33 | (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PLUGIN_TEMPLATE,GstPluginTemplate))
34 | #define GST_PLUGIN_TEMPLATE_CLASS(klass) \
35 | (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PLUGIN_TEMPLATE,GstPluginTemplateClass))
36 | #define GST_IS_PLUGIN_TEMPLATE(obj) \
37 | (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PLUGIN_TEMPLATE))
38 | #define GST_IS_PLUGIN_TEMPLATE_CLASS(klass) \
39 | (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PLUGIN_TEMPLATE))
40 |
41 | typedef struct _GstPluginTemplate GstPluginTemplate;
42 | typedef struct _GstPluginTemplateClass GstPluginTemplateClass;
43 |
44 | struct _GstPluginTemplate {
45 | GstBaseTransform element;
46 |
47 | gboolean silent;
48 | };
49 |
50 | struct _GstPluginTemplateClass {
51 | GstBaseTransformClass parent_class;
52 | };
53 |
54 | GType gst_plugin_template_get_type (void);
55 |
56 | G_END_DECLS
57 |
58 | #endif /* __GST_PLUGIN_TEMPLATE_H__ */
59 |
--------------------------------------------------------------------------------
/multicam/sender/gst-codec-ctrl/gst-plugin/src/targetver.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | // Including SDKDDKVer.h defines the highest available Windows platform.
4 |
5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
7 |
8 | #include
9 |
--------------------------------------------------------------------------------
/multicam/sender/gst-codec-ctrl/gst-plugin/stamp-h1:
--------------------------------------------------------------------------------
1 | timestamp for config.h
2 |
--------------------------------------------------------------------------------
/multicam/sender/killitall.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 | killall -9 gst-launch-1.0 scream_sender
3 |
4 |
--------------------------------------------------------------------------------
/multicam/sender/scream/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.6)
2 |
3 | PROJECT( scream )
4 |
5 | message("Source Dir:" ${scream_SOURCE_DIR})
6 |
7 | SET(EXECUTABLE_OUTPUT_PATH ${scream_SOURCE_DIR}/bin)
8 | SET(LIBRARY_OUTPUT_PATH ${scream_SOURCE_DIR}/lib)
9 | SET(RUNTIME_OUTPUT_DIRECTORY ${scream_SOURCE_DIR}/bin)
10 |
11 | SET(scream_BIN ${scream_SOURCE_DIR}/bin)
12 |
13 | message("scream_SOURCE_DIR directories:" ${scream_SOURCE_DIR})
14 |
15 | IF(UNIX)
16 | add_definitions(-std=c++0x)
17 | ENDIF(UNIX)
18 |
19 | IF(WIN32)
20 | IF(MSVC12)
21 | message("Detected MSVC12 compiler")
22 | set(MSVC_VER VC12)
23 | ELSEIF(MSVC11)
24 | message("Detected MSVC11 compiler")
25 | set(MSVC_VER VC11)
26 | ELSEIF(MSVC10)
27 | message("Detected MSVC10 compiler")
28 | set(MSVC_VER VC10)
29 | ELSEIF(MSVC14)
30 | message("Detected MSVC14 compiler")
31 | set(MSVC_VER VC14)
32 | ELSE(MSVC12)
33 | message("WARNING: Unknown/unsupported MSVC version")
34 | ENDIF(MSVC12)
35 | ENDIF(WIN32)
36 |
37 | if( CMAKE_SIZEOF_VOID_P EQUAL 8 )
38 | # 64bit
39 | message("Detected 64-bit build - compiling with -fPIC")
40 | SET(CMAKE_CXX_FLAGS "-fPIC -fpermissive -pthread -DV2")
41 | else( CMAKE_SIZEOF_VOID_P EQUAL 8 )
42 | # 32 bit
43 | message("Detected 32-bit build")
44 | SET(CMAKE_CXX_FLAGS "-fpermissive -pthread -DV2")
45 | endif( CMAKE_SIZEOF_VOID_P EQUAL 8 )
46 |
47 | #SET(LDFLAGS "-lrt -pthread -lpthread")
48 |
49 | SET(screamIncludes
50 | ${scream_SOURCE_DIR}
51 | ${scream_SOURCE_DIR}/code
52 | )
53 |
54 | message("screamIncludes directories:" ${screamIncludes})
55 |
56 | # lib directories
57 | IF(WIN32)
58 | SET(screamLink
59 | ${scream_SOURCE_DIR}/../lib
60 | )
61 | ELSEIF(UNIX)
62 | SET(screamLink
63 | ${scream_SOURCE_DIR}/../lib
64 | /usr/local/lib
65 | /usr/lib
66 | )
67 | ENDIF(WIN32)
68 |
69 | SET(LibDir
70 | ${scream_SOURCE_DIR}/../lib
71 | )
72 |
73 |
74 | set(LIBS ${LIBS} -lrt -pthread)
75 |
76 | message("LibDir directories:" ${LibDir})
77 |
78 | # Include directories
79 | INCLUDE_DIRECTORIES(
80 | ${scream_SOURCE_DIR}/../include
81 | )
82 |
83 | ADD_SUBDIRECTORY( code)
84 |
--------------------------------------------------------------------------------
/multicam/sender/scream/code/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # source files
2 | SET(SRCS
3 | ../../../../code/RtpQueue.cpp
4 | ../../../../code/ScreamTx.cpp
5 | ../../../../code/ScreamV2Tx.cpp
6 | ../../../../code/ScreamV2TxStream.cpp
7 | scream_sender.cpp
8 | )
9 |
10 | SET(HEADERS
11 | ../../../../code/RtpQueue.h
12 | ../../../../code/ScreamTx.h
13 | )
14 |
15 | SET(SRC_1
16 | ${SRCS}
17 | scream_sender.cpp
18 | )
19 |
20 | INCLUDE_DIRECTORIES(
21 | ${screamIncludes}
22 | ../../../../code/
23 | )
24 |
25 | LINK_DIRECTORIES(
26 | ${screamLink}
27 | )
28 |
29 | ADD_EXECUTABLE(scream_sender ${SRC_1} ${HEADERS})
30 |
31 |
32 | TARGET_LINK_LIBRARIES (
33 | scream_sender
34 | ${screamLibs}
35 | )
36 |
--------------------------------------------------------------------------------
/multicam/sender/startsender.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # The semder side processing is illustrated below
4 | # Each gstreamer pipeline encodes media and sends it on local
5 | # ports 30000 and 30002 to the SCReAM sender
6 | # The SCReAM sender implements the congestion control
7 | # and prioritization between media
8 | # and sends the multiplexed RTP media over port UDP_PORT_VIDEO to the destination,
9 | # RTCP feedback from the destinaton is also received on port UDP_PORT_VIDEO
10 | #
11 | # +-----------------+ Lo:30001 +---------------------+
12 | # | +<----------+ |
13 | # | /dev/video0 | | |
14 | # | capture/encode +---------->+ |
15 | # +-----------------+ Lo:30000 | +------------------->
16 | # | SCReAM sender | DST_IP:51000
17 | # +-----------------+ Lo:30003 | +<-------------------
18 | # | +<----------+ |
19 | # | /dev/video1 | | |
20 | # | capture/encode +---------->+ |
21 | # +-----------------+ Lo:30002 +---------------------+
22 |
23 |
24 | # Set path to codecctrl plugin
25 | export GST_PLUGIN_PATH=/usr/local/lib/gstreamer-1.0/
26 |
27 | # Settings for video encoding and streaming
28 | RECEIVER_IP=192.168.1.20 #Change to applicable receiver address
29 | UDP_PORT_VIDEO=51000
30 | NETWORK_QUEUE_DELAY_TARGET=0.06
31 | MAX_TOTAL_RATE=60000
32 |
33 | # Select type of camera here
34 | #SOURCE="e-CAM50_CUNX"
35 | SOURCE="Raspberry-Pi-HQ_Camera_12MP"
36 | #SOURCE="Movie"
37 | #SCREAM_VERSION="V1"
38 | SCREAM_VERSION="V2"
39 |
40 |
41 | if [ "$SOURCE" == "e-CAM50_CUNX" ]; then
42 | echo "Starting e-CAM50_CUNX camera(s)"
43 |
44 | # Settings for exposure compensation and sharpness
45 | # for low light condition this can be set to 8000 and 0 to
46 | # maintain full framerate
47 | EXPOSURE_COMPENSATION=140000 #default 140000
48 | SHARPNESS=16 #default 16
49 |
50 | --set-ctrl=low_latency_mode=1 --set-ctrl=exposure_compensation=$EXPOSURE_COMPENSATION --set-ctrl=sharpness=$SHARPNESS
51 | v4l2-ctl -d /dev/video1 --set-ctrl=low_latency_mode=1 --set-ctrl=exposure_compensation=$EXPOSURE_COMPENSATION --set-ctrl=sharpness=$SHARPNESS
52 |
53 | echo "Start gstreamer pipelines"
54 |
55 | ## /dev/video0
56 | # encode at 1920*1080, run application ecam_tk1_guvcview for other alternatives
57 | gst-launch-1.0 rtpbin name=rtpbin nvv4l2camerasrc device=/dev/video0 ! "video/x-raw(memory:NVMM), format=(string)UYVY, width=(int)1920, height=(int)1080" ! nvvidconv ! "video/x-raw(memory:NVMM),format=(string)I420" ! nvv4l2h264enc name=video iframeinterval=500 control-rate=1 bitrate=1000000 insert-sps-pps=true preset-level=1 profile=2 maxperf-enable=true EnableTwopassCBR=true vbv-size=500000 poc-type=2 ! queue max-size-buffers=2 ! rtph264pay mtu=1300 ! codecctrl media-src=4 port=30001 ! udpsink host=127.0.0.1 port=30000 &
58 |
59 | sleep 1
60 | ## /dev/video1
61 | gst-launch-1.0 rtpbin name=rtpbin nvv4l2camerasrc device=/dev/video1 ! "video/x-raw(memory:NVMM), format=(string)UYVY, width=(int)1920, height=(int)1080" ! nvvidconv ! nvv4l2h264enc name=video iframeinterval=500 control-rate=1 bitrate=1000000 insert-sps-pps=true preset-level=1 profile=2 maxperf-enable=true EnableTwopassCBR=true vbv-size=500000 poc-type=2 ! queue max-size-buffers=2 ! rtph264pay mtu=1300 ! codecctrl media-src=4 port=30003 ! udpsink host=127.0.0.1 port=30002 &
62 | fi
63 |
64 | if [ "$SOURCE" == "Raspberry-Pi-HQ_Camera_12MP" ]; then
65 | echo "Raspberry Pi HQ Camera 12MP camera(s)"
66 |
67 | gst-launch-1.0 rtpbin name=rtpbin nvarguscamerasrc sensor-id=0 saturation=0.5 tnr_mode=2 ee-mode=0 tnr_strength=0.1 wbmode=4 exposurecompensation=0.6 ! "video/x-raw(memory:NVMM),width=1920,height=1080,framerate=60/1" ! nvvidconv ! "video/x-raw(memory:NVMM),format=(string)I420" ! nvv4l2h264enc name=video iframeinterval=500 control-rate=1 bitrate=1000000 insert-sps-pps=true preset-level=1 profile=2 maxperf-enable=true EnableTwopassCBR=true vbv-size=500000 poc-type=2 ! queue max-size-buffers=2 ! rtph264pay mtu=1300 ! codecctrl media-src=4 port=30001 ! udpsink host=127.0.0.1 port=30000 &
68 |
69 | gst-launch-1.0 rtpbin name=rtpbin nvarguscamerasrc sensor-id=1 saturation=0.6 tnr_mode=2 ee-mode=0 tnr_strength=0.1 ! "video/x-raw(memory:NVMM),width=1920,height=1080,framerate=60/1" ! nvvidconv ! "video/x-raw(memory:NVMM),format=(string)I420" ! nvv4l2h264enc name=video iframeinterval=500 control-rate=1 bitrate=1000000 insert-sps-pps=true preset-level=1 profile=2 maxperf-enable=true EnableTwopassCBR=true vbv-size=500000 poc-type=2 ! queue max-size-buffers=2 ! rtph264pay mtu=1300 ! codecctrl media-src=4 port=30003 ! udpsink host=127.0.0.1 port=30002 &
70 | fi
71 |
72 | if [ "$SOURCE" == "Movie" ]; then
73 | # Download the big buck bunny 1080p60fps movie
74 | # from http://ftp.vim.org/ftp/ftp/pub/graphics/blender/demo/movies/BBB/
75 | MEDIA=~/bbb_sunflower_1080p_60fps_normal.mp4
76 | gst-launch-1.0 rtpbin name=rtpbin multifilesrc location=$MEDIA location=$MEDIA loop=true stop-index=-1 ! qtdemux name=demux ! queue ! h264parse ! omxh264dec ! queue ! nvv4l2h264enc name=video iframeinterval=500 control-rate=1 bitrate=1000000 insert-sps-pps=true preset-level=1 profile=2 maxperf-enable=true EnableTwopassCBR=true vbv-size=500000 poc-type=2 ! queue max-size-buffers=2 ! rtph264pay mtu=1300 ! codecctrl media-src=4 port=30001 ! udpsink host=127.0.0.1 port=30000 &
77 | fi
78 |
79 | sleep 1
80 | ##Start SCReAM sender side.
81 | # The rate control is configured so that /dev/video0 gets a higher prority (1.0)
82 | # while /dev/video1 gets a lower priority (0.5), see -priority parameter
83 | # Min, max and init rate for /dev/video{0,1} can also be configured
84 | # ratescale compensates for offset that may occur between target and actual bitrates for the video coder
85 | # For L4S capability, change to
86 | # ./screamTx/bin/scream_sender -ect 1
87 |
88 | echo "Video streaming started"
89 | if [ "$SCREAM_VERSION" == "V1" ]; then
90 | ./scream/bin/scream_sender -ect 1 -delaytarget $NETWORK_QUEUE_DELAY_TARGET -priority 1.0:0.5 -ratemax 25000:25000 -ratemin 2000:2000 -rateinit 5000:5000 -ratescale 1.0:1.0 -cwvmem 60 -maxtotalrate $MAX_TOTAL_RATE -pacingheadroom 1.2 2 $RECEIVER_IP $UDP_PORT_VIDEO &
91 | fi
92 | if [ "$SCREAM_VERSION" == "V2" ]; then
93 | ./scream/bin/scream_sender -ect 1 -delaytarget $NETWORK_QUEUE_DELAY_TARGET -priority 1.0:0.5 -ratemax 25000:25000 -ratemin 2000:2000 -rateinit 5000:5000 -ratescale 1.0:1.0 -maxtotalrate $MAX_TOTAL_RATE -pacingheadroom 1.5 2 $RECEIVER_IP $UDP_PORT_VIDEO &
94 | fi
95 |
--------------------------------------------------------------------------------
/multicam/sender/startsender_2.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # The semder side processing is illustrated below
4 | # Each gstreamer pipeline encodes media and sends it on local
5 | # ports 30000 and 30002 to the SCReAM sender
6 | # The SCReAM sender implements the congestion control
7 | # and prioritization between media
8 | # and sends the multiplexed RTP media over port UDP_PORT_VIDEO to the destination,
9 | # RTCP feedback from the destinaton is also received on port UDP_PORT_VIDEO
10 | #
11 | # +-----------------+ Lo:30001 +---------------------+
12 | # | +<----------+ |
13 | # | /dev/video0 | | |
14 | # | capture/encode +---------->+ |
15 | # +-----------------+ Lo:30000 | +------------------->
16 | # | SCReAM sender | DST_IP:51000
17 | # +-----------------+ Lo:30003 | +<-------------------
18 | # | +<----------+ |
19 | # | /dev/video1 | | |
20 | # | capture/encode +---------->+ |
21 | # +-----------------+ Lo:30002 +---------------------+
22 |
23 |
24 | # Set path to codecctrl plugin
25 | export GST_PLUGIN_PATH=/usr/local/lib/gstreamer-1.0/
26 |
27 | # Settings for video encoding and streaming
28 | RECEIVER_IP=192.168.1.20 #Change to applicable receiver address
29 | UDP_PORT_VIDEO=51000
30 | NETWORK_QUEUE_DELAY_TARGET=0.06
31 | MAX_TOTAL_RATE=60000
32 |
33 | # Select type of camera here
34 | #SOURCE="e-CAM50_CUNX"
35 | SOURCE="Raspberry-Pi-HQ_Camera_12MP"
36 | SOURCE="Movie"
37 | #SCREAM_VERSION="V1"
38 | SCREAM_VERSION="V2"
39 |
40 |
41 | if [ "$SOURCE" == "e-CAM50_CUNX" ]; then
42 | echo "Starting e-CAM50_CUNX camera(s)"
43 |
44 | # Settings for exposure compensation and sharpness
45 | # for low light condition this can be set to 8000 and 0 to
46 | # maintain full framerate
47 | EXPOSURE_COMPENSATION=140000 #default 140000
48 | SHARPNESS=16 #default 16
49 |
50 | --set-ctrl=low_latency_mode=1 --set-ctrl=exposure_compensation=$EXPOSURE_COMPENSATION --set-ctrl=sharpness=$SHARPNESS
51 | v4l2-ctl -d /dev/video1 --set-ctrl=low_latency_mode=1 --set-ctrl=exposure_compensation=$EXPOSURE_COMPENSATION --set-ctrl=sharpness=$SHARPNESS
52 |
53 | echo "Start gstreamer pipelines"
54 |
55 | ## /dev/video0
56 | # encode at 1920*1080, run application ecam_tk1_guvcview for other alternatives
57 | gst-launch-1.0 rtpbin name=rtpbin nvv4l2camerasrc device=/dev/video0 ! "video/x-raw(memory:NVMM), format=(string)UYVY, width=(int)1920, height=(int)1080" ! nvvidconv ! "video/x-raw(memory:NVMM),format=(string)I420" ! nvv4l2h264enc name=video iframeinterval=500 control-rate=1 bitrate=1000000 insert-sps-pps=true preset-level=1 profile=2 maxperf-enable=true EnableTwopassCBR=true vbv-size=500000 poc-type=2 ! queue max-size-buffers=2 ! rtph264pay mtu=1300 ! codecctrl media-src=4 port=30001 ! udpsink host=127.0.0.1 port=30000 &
58 |
59 | sleep 1
60 | ## /dev/video1
61 | gst-launch-1.0 rtpbin name=rtpbin nvv4l2camerasrc device=/dev/video1 ! "video/x-raw(memory:NVMM), format=(string)UYVY, width=(int)1920, height=(int)1080" ! nvvidconv ! nvv4l2h264enc name=video iframeinterval=500 control-rate=1 bitrate=1000000 insert-sps-pps=true preset-level=1 profile=2 maxperf-enable=true EnableTwopassCBR=true vbv-size=500000 poc-type=2 ! queue max-size-buffers=2 ! rtph264pay mtu=1300 ! codecctrl media-src=4 port=30003 ! udpsink host=127.0.0.1 port=30002 &
62 | fi
63 |
64 | if [ "$SOURCE" == "Raspberry-Pi-HQ_Camera_12MP" ]; then
65 | echo "Raspberry Pi HQ Camera 12MP camera(s)"
66 |
67 | gst-launch-1.0 rtpbin name=rtpbin nvarguscamerasrc sensor-id=0 saturation=0.5 tnr_mode=2 ee-mode=0 tnr_strength=0.1 wbmode=4 exposurecompensation=0.7 ! "video/x-raw(memory:NVMM),width=1920,height=1080,framerate=50/1" ! nvvidconv ! "video/x-raw(memory:NVMM),format=(string)I420" ! nvv4l2h264enc name=video iframeinterval=500 control-rate=1 bitrate=1000000 insert-sps-pps=true preset-level=1 profile=2 maxperf-enable=true EnableTwopassCBR=true vbv-size=500000 poc-type=2 ! queue max-size-buffers=2 ! rtph264pay mtu=1300 ! codecctrl media-src=4 port=30001 ! udpsink host=127.0.0.1 port=30000 &
68 |
69 | gst-launch-1.0 rtpbin name=rtpbin nvarguscamerasrc sensor-id=1 saturation=0.6 tnr_mode=2 ee-mode=0 tnr_strength=0.1 ! "video/x-raw(memory:NVMM),width=1920,height=1080,framerate=60/1" ! nvvidconv ! "video/x-raw(memory:NVMM),format=(string)I420" ! nvv4l2h264enc name=video iframeinterval=500 control-rate=1 bitrate=1000000 insert-sps-pps=true preset-level=1 profile=2 maxperf-enable=true EnableTwopassCBR=true vbv-size=500000 poc-type=2 ! queue max-size-buffers=2 ! rtph264pay mtu=1300 ! codecctrl media-src=4 port=30003 ! udpsink host=127.0.0.1 port=30002 &
70 | fi
71 |
72 | if [ "$SOURCE" == "Movie" ]; then
73 | # Download the big buck bunny 1080p60fps movie
74 | # from http://ftp.vim.org/ftp/ftp/pub/graphics/blender/demo/movies/BBB/
75 | MEDIA=~/bbb_sunflower_1080p_60fps_normal.mp4
76 | gst-launch-1.0 rtpbin name=rtpbin multifilesrc location=$MEDIA location=$MEDIA loop=true stop-index=-1 ! qtdemux name=demux ! queue ! h264parse ! omxh264dec ! queue ! nvv4l2h264enc name=video iframeinterval=500 control-rate=1 bitrate=1000000 insert-sps-pps=true preset-level=1 profile=2 maxperf-enable=true EnableTwopassCBR=true vbv-size=500000 poc-type=2 ! queue max-size-buffers=2 ! rtph264pay mtu=1300 ! codecctrl media-src=4 port=30001 ! udpsink host=127.0.0.1 port=30000 &
77 | fi
78 |
79 | sleep 1
80 | ##Start SCReAM sender side.
81 | # The rate control is configured so that /dev/video0 gets a higher prority (1.0)
82 | # while /dev/video1 gets a lower priority (0.5), see -priority parameter
83 | # Min, max and init rate for /dev/video{0,1} can also be configured
84 | # ratescale compensates for offset that may occur between target and actual bitrates for the video coder
85 | # For L4S capability, change to
86 | # ./screamTx/bin/scream_sender -ect 1
87 |
88 | echo "Video streaming started"
89 | if [ "$SCREAM_VERSION" == "V1" ]; then
90 | ./scream/bin/scream_sender -ect 1 -delaytarget $NETWORK_QUEUE_DELAY_TARGET -priority 1.0:0.5 -ratemax 25000:25000 -ratemin 2000:2000 -rateinit 5000:5000 -ratescale 1.0:1.0 -cwvmem 60 -maxtotalrate $MAX_TOTAL_RATE -pacingheadroom 1.2 2 $RECEIVER_IP $UDP_PORT_VIDEO &
91 | fi
92 | if [ "$SCREAM_VERSION" == "V2" ]; then
93 | ./scream/bin/scream_sender -ect 1 -delaytarget $NETWORK_QUEUE_DELAY_TARGET -priority 1.0:0.5 -ratemax 25000:25000 -ratemin 2000:2000 -rateinit 5000:5000 -ratescale 1.0:1.0 -maxtotalrate $MAX_TOTAL_RATE -pacingheadroom 1.5 2 $RECEIVER_IP $UDP_PORT_VIDEO &
94 | fi
95 |
--------------------------------------------------------------------------------
/plot_1_stream.m:
--------------------------------------------------------------------------------
1 | function plot_1_stream(a,Tlim,maxR,maxD,maxRT, U)
2 | % Plot stdout for 1-streaming
3 | % script is adapted to 1 stream
4 | % Tlim [min max] time e.g [0 1000]
5 | % maxR max rate [Mbps]
6 | % maxD max delay [s]
7 | % example:
8 | % >a = load('logfile.txt');
9 | % >plot_vay_4(a,[0 1000],15,0.1);
10 |
11 | T=a(:,1);T=T-T(1);
12 |
13 | B = ones(1,U)/U;
14 | K=6;L=1;
15 | subplot(K,1,L);L=L+1;
16 | %plot(T,a(:,4)/1e3,T,a(:,5)/1e3,':',T,a(:,7)*max(a(:,4))/1e3*0.05,':k');
17 | plot(T,a(:,4)/1200,T,a(:,5)/1200,':');
18 | set(gca,'FontSize',12);grid on;
19 | %title('CWND and bytes in flight [kbyte]')
20 | title('CWND and bytes in flight [MSS]')
21 | set(gca,'XTickLabel',[]);
22 | xlim(Tlim);
23 |
24 | subplot(K,1,L);L=L+1;
25 | plot(T,a(:,2),T,a(:,3));
26 | set(gca,'FontSize',12);grid on;
27 | set(gca,'XTickLabel',[]);
28 | title('Est. queue delay and RTT [s]')
29 | ylim([0 maxD]);
30 | xlim(Tlim);
31 |
32 | subplot(K,1,L);L=L+1;
33 | plot(T,a(:,8)+a(:,2));
34 | set(gca,'FontSize',12);grid on;
35 | set(gca,'XTickLabel',[]);
36 | title('RTP queue+network delay[s]')
37 | ylim([0 maxD]);
38 | xlim(Tlim);
39 |
40 | subplot(K,1,L);L=L+1;
41 | ce = a(:,13);
42 | loss = a(:,12);
43 | plot(T,ce/1e3,T,loss/1e3,T,filter(B,1,a(:,6))/1e3,'k');
44 | set(gca,'FontSize',12);grid on;
45 | set(gca,'XTickLabel',[]);
46 | title('Tx rate [Mbps]')
47 | legend('ce','loss','Total')
48 | ylim([0 maxRT]);
49 | xlim(Tlim);
50 |
51 | subplot(K,1,L);L=L+1;
52 | plot(T,a(:,9)/1e3);
53 | set(gca,'FontSize',12);grid on;
54 | set(gca,'XTickLabel',[]);
55 | xlim(Tlim);
56 | ylim([0 maxR]);
57 | title('Target rate [Mbps]')
58 |
59 | subplot(K,1,L);L=L+1;
60 | plot(T,filter(B,1,a(:,10))/1e3);
61 | set(gca,'FontSize',12);grid on;
62 | title('Encoder rate [Mbps]')
63 | xlim(Tlim);
64 | ylim([0 maxR]);
65 | xlabel('T [s]')
66 |
67 | end
--------------------------------------------------------------------------------
/plot_1_stream_s.m:
--------------------------------------------------------------------------------
1 | function plot_1_streams(a,Tlim,maxR,maxD,maxRT, U)
2 | % Plot stdout for 1-streaming
3 | % script is adapted to 1 stream
4 | % Tlim [min max] time e.g [0 1000]
5 | % maxR max rate [Mbps]
6 | % maxD max delay [s]
7 | % example:
8 | % >a = load('logfile.txt');
9 | % >plot_vay_4(a,[0 1000],15,0.1);
10 |
11 | T=a(:,1);T=T-T(1);
12 |
13 | B = ones(1,U)/U;
14 | K=4;L=1;
15 | subplot(K,1,L);L=L+1;
16 | %plot(T,a(:,4)/1e3,T,a(:,5)/1e3,':',T,a(:,7)*max(a(:,4))/1e3*0.05,':k');
17 | plot(T,a(:,4)/1200,T,a(:,5)/1200,':');
18 | set(gca,'FontSize',12);grid on;
19 | %title('CWND and bytes in flight [kbyte]')
20 | title('CWND and bytes in flight [MSS]')
21 | set(gca,'XTickLabel',[]);
22 | xlim(Tlim);
23 |
24 | subplot(K,1,L);L=L+1;
25 | plot(T,a(:,2),T,a(:,3));
26 | set(gca,'FontSize',12);grid on;
27 | set(gca,'XTickLabel',[]);
28 | title('Est. queue delay and RTT [s]')
29 | ylim([0 maxD]);
30 | xlim(Tlim);
31 |
32 | subplot(K,1,L);L=L+1;
33 | plot(T,a(:,8));
34 | set(gca,'FontSize',12);grid on;
35 | set(gca,'XTickLabel',[]);
36 | title('RTP queue delay[s]')
37 | ylim([0 maxD]);
38 | xlim(Tlim);
39 |
40 | subplot(K,1,L);L=L+1;
41 | ce = a(:,13);
42 | loss = a(:,12);
43 | plot(T,filter(B,1,a(:,6))/1e3,'k');
44 | set(gca,'FontSize',12);grid on;
45 | title('Tx rate [Mbps]')
46 | ylim([0 maxRT]);
47 | xlim(Tlim);
48 |
49 | xlabel('T [s]')
50 |
51 | end
--------------------------------------------------------------------------------
/plot_4_stream.m:
--------------------------------------------------------------------------------
1 | function plot_4_stream(a,Tlim,maxR,maxD,maxRT, U)
2 | % Plot stdout for 4-streaming
3 | % script is adapted to 4 streams
4 | % Tlim [min max] time e.g [0 1000]
5 | % maxR max rate [Mbps]
6 | % maxD max delay [s]
7 | % example:
8 | % >a = load('logfile.txt');
9 | % >plot_vay_4(a,[0 1000],15,0.1);
10 |
11 | T=a(:,1);T=T-T(1);
12 |
13 | B = ones(1,U)/U;
14 | K=7;L=1;
15 | subplot(K,1,L);L=L+1;
16 | plot(T,a(:,4)/1e3,T,a(:,5)/1e3,':',T,a(:,7)*max(a(:,4))/1e3*0.05,':k');
17 | set(gca,'FontSize',12);grid on;
18 | title('CWND and bytes in flight [kbyte]')
19 | set(gca,'XTickLabel',[]);
20 | xlim(Tlim);
21 |
22 | subplot(K,1,L);L=L+1;
23 | plot(T,a(:,2),T,a(:,3));
24 | set(gca,'FontSize',12);grid on;
25 | set(gca,'XTickLabel',[]);
26 | title('Est. queue delay and RTT [s]')
27 | ylim([0 maxD]);
28 | xlim(Tlim);
29 |
30 | subplot(K,1,L);L=L+1;
31 | plot(T,a(:,8),T,a(:,8+6),T,a(:,8+12),T,a(:,8+18));
32 | set(gca,'FontSize',12);grid on;
33 | set(gca,'XTickLabel',[]);
34 | legend('0','1','2','3')
35 | title('RTP queue delay[s]')
36 | ylim([0 maxD]);
37 | xlim(Tlim);
38 |
39 | subplot(K,1,L);L=L+1;
40 | ce = a(:,13)+a(:,13+6)+a(:,13+12)+a(:,13+18);
41 | loss = a(:,12)+a(:,12+6)+a(:,12+12)+a(:,12+18);
42 | plot(T,ce/1e2,T,loss/1e2,T,filter(B,1,a(:,6))/1e3,'k');
43 | set(gca,'FontSize',12);grid on;
44 | set(gca,'XTickLabel',[]);
45 | title('Tx rate [Mbps]')
46 | legend('ce*10','loss*10','Total')
47 | ylim([0 maxRT]);
48 | xlim(Tlim);
49 |
50 | subplot(K,1,L);L=L+1;
51 | plot(T,filter(B,1,a(:,11))/1e3,T,filter(B,1,a(:,11+6))/1e3,T,filter(B,1,a(:,11+12))/1e3,T,filter(B,1,a(:,11+18))/1e3);
52 | set(gca,'FontSize',12);grid on;
53 | set(gca,'XTickLabel',[]);
54 | title('Tx rate streams [Mbps]')
55 | legend('0','1','2','3')
56 | ylim([0 maxR]);
57 | xlim(Tlim);
58 |
59 | subplot(K,1,L);L=L+1;
60 | plot(T,a(:,9)/1e3,'-',T,a(:,9+6)/1e3,'-',T,a(:,9+12)/1e3,'-',T,a(:,9+18)/1e3,'-');
61 | set(gca,'FontSize',12);grid on;
62 | set(gca,'XTickLabel',[]);
63 | legend('0','1','2','3')
64 | xlim(Tlim);
65 | ylim([0 maxR]);
66 | title('Target rate [Mbps]')
67 |
68 | subplot(K,1,L);L=L+1;
69 | plot(T,filter(B,1,a(:,10))/1e3,T,filter(B,1,a(:,10+6))/1e3,T,filter(B,1,a(:,10+12))/1e3,T,filter(B,1,a(:,10+18))/1e3);
70 | set(gca,'FontSize',12);grid on;
71 | legend('0','1','2','3')
72 | title('Encoder rate [Mbps]')
73 | xlim(Tlim);
74 | ylim([0 maxR]);
75 | xlabel('T [s]')
76 |
77 | end
--------------------------------------------------------------------------------
/plot_cdf.m:
--------------------------------------------------------------------------------
1 | function plot_cdf(a,Tlim,Tmax)
2 | % This function plots the CDF of the RTT and
3 | % queue delay from the logs given by the
4 | % SCReAM BW test tool.
5 | % Parameters :
6 | % a : log file from SCReAM BW test tool
7 | % imported with the command
8 | % a = load();
9 | % where is the name of the log file
10 | % Tlim : xmin and xmax limits [s], e.g. [0 100]
11 | % Tmax : Max displayed value for RTT/delay
12 | %
13 | % The script can be used with matlab or octave
14 | % Octave can sometimes be painfully slow. The following commands
15 | % can make it faster
16 | % >a = a = load();
17 | % >a = a(1:50:end,:); % subsample the log file
18 | % >figure(1);
19 | % >plot_cdf(....
20 | %
21 |
22 | T = a(:,1);
23 | ix = intersect(find(T > Tlim(1)),find(T <= Tlim(2)));
24 |
25 | qd = sort(a(ix,2));
26 | rtt = sort(a(ix,3));
27 | N = length(qd); N = (0:N-1)/(N-1);
28 |
29 | subplot(111);
30 | plot(qd,N,rtt,N);
31 | set(gca,'FontSize',14);grid on;
32 | title('CDF Network queue delay and RTT [s]');
33 | legend('Queue delay','RTT');
34 | xlim([0 Tmax]);
35 |
36 | xlabel('[s]');
37 | end
38 |
39 |
--------------------------------------------------------------------------------
/plot_thp_delay.m:
--------------------------------------------------------------------------------
1 | function plot_thp_delay(a,id,Tlim,maxThp,maxDelay)
2 | % This function plots the thorughput
3 | % RTT and estimated queue delay
4 | % Parameters:
5 | % a : log file from SCReAM BW test tool
6 | % imported with the command
7 | % a = load();
8 | % where is the name of the log file
9 | % id : stream id
10 | % Tlim : xmin and xmax limits [s], e.g. [0 100]
11 | % maxThp : Max thorughput [Mbps]
12 | % maxDelay : Max delay [s]
13 | %
14 | % The script can be used with matlab or octave
15 | %
16 | ix = find(a(:,8)==id);
17 |
18 | T = a(ix,1);
19 | T = T-T(1);
20 |
21 | subplot(4,1,1);
22 | plot(T,filter(1,1,a(ix,13))/1e6,T,a(ix,12)/1e6,T,a(ix,14)/1e6,T,a(ix,18)/1e6,T,min(maxThp/10,a(ix,15)/1e3-1),'.k');
23 | set(gca,'FontSize',12);grid on;
24 | set(gca,'XTickLabel',[]);grid on;
25 | title('Throughput [Mbps]');
26 | legend('Transmitted','RTP','ACKed','Target','Loss')
27 | xlim(Tlim);
28 | ylim([0 maxThp]);
29 |
30 | subplot(4,1,2);
31 | plot(T,a(ix,5)/1e3,'-r',T,a(ix,4)/1e3,'.-b');
32 | set(gca,'FontSize',12);grid on;
33 | set(gca,'XTickLabel',[]);grid on;
34 | title('CWND(B) and bytes in flight(R) [kByte]');
35 | xlim(Tlim);
36 |
37 | subplot(4,1,3);
38 | x = a(ix,11)./a(ix,10)*100;
39 | plot(T,x);
40 | mean(x)
41 | set(gca,'FontSize',12);grid on;
42 | set(gca,'XTickLabel',[]);grid on;
43 | title('Congestion mark [%]');
44 | xlim(Tlim);
45 | ylim([0 110]);
46 |
47 | subplot(4,1,4);
48 | plot(T,a(ix,2),'.-',T,a(ix,3),'.-','linewidth',1);ylim([0 maxDelay]);
49 | set(gca,'FontSize',12);grid on;
50 | title('Network queue(B) and RTT(R) [s]');
51 | xlim(Tlim);
52 |
53 | xlabel('T [s]');
54 | xlim(Tlim);
55 | end
56 |
57 |
--------------------------------------------------------------------------------
/plot_thp_delay_new.m:
--------------------------------------------------------------------------------
1 | function plot_thp_delay_new(a,id,Tlim,maxThp,maxDelay)
2 | % This function plots the thorughput
3 | % RTT and estimated queue delay
4 | % Parameters:
5 | % a : log file from SCReAM BW test tool
6 | % imported with the command
7 | % a = load();
8 | % where is the name of the log file
9 | % id * stream id
10 | % Tlim : xmin and xmax limits [s], e.g. [0 100]
11 | % maxThp : Max thorughput [Mbps]
12 | % maxDelay : Max delay [s]
13 | %
14 | % The script can be used with matlab or octave
15 | %
16 | ix = find(a(:,8)==id);
17 |
18 | T = a(ix,1);
19 | T = T-T(1);
20 | K = 10;
21 | B = ones(1,K)/K;
22 | A = [1 -0.95];
23 |
24 |
25 | subplot(4,1,1);
26 | %plot(T,filter(1,1,a(ix,13))/1e6,T,filter(B,1,a(ix,12))/1e6,T,filter(B,1,a(ix,14))/1e6)
27 | plot(T,filter(1,1,a(ix,13))/1e6,T,filter(0.05,A,a(ix,12))/1e6,T,filter(0.05,A,a(ix,14))/1e6,T,a(ix,18)/1e6);
28 | set(gca,'FontSize',12);grid on;
29 | set(gca,'XTickLabel',[]);grid on;
30 | title('Throughput [Mbps]');
31 | legend('Transmitted','RTP','ACKed','Target')
32 | xlim(Tlim);
33 | ylim([0 maxThp]);
34 |
35 | subplot(4,1,2);
36 | plot(T,a(ix,5)/1e3,'-R',T,a(ix,4)/1e3,'.-B');
37 | set(gca,'FontSize',12);grid on;
38 | set(gca,'XTickLabel',[]);grid on;
39 | title('CWND(B) and bytes in flight(R) [kByte]');
40 | xlim(Tlim);
41 |
42 |
43 | subplot(4,1,3);
44 | K = 1;
45 | B = ones(1,K)/K;
46 | x = a(ix,11)./a(ix,10)*100;
47 | plot(T,filter(B,1,x));
48 | mean(x)
49 | set(gca,'FontSize',12);grid on;
50 | set(gca,'XTickLabel',[]);grid on;
51 | title('Congestion mark [%]');
52 | xlim(Tlim);
53 | ylim([0 110]);
54 |
55 |
56 | K = 10;
57 | B = ones(1,K)/K;
58 |
59 | subplot(4,1,4);
60 | plot(T,a(ix,2),'.-',T,filter(B,1,a(ix,19)),'.-','linewidth',1);ylim([0 maxDelay]);
61 | %plot(T,a(ix,2)+a(ix,19),'R.',T,a(ix,2),'B.-','linewidth',1);ylim([0 maxDelay]);
62 | set(gca,'FontSize',12);grid on;
63 | title('Network queue(B) and RTP Q (R) [s]');
64 | xlim(Tlim);
65 |
66 |
67 | xlabel('T [s]');
68 | xlim(Tlim);
69 | end
70 |
71 |
--------------------------------------------------------------------------------
/plot_txrx.m:
--------------------------------------------------------------------------------
1 | function plot_txrx(a,Tlim,maxDelay)
2 |
3 |
4 | T = a(:,1);
5 | T = T-T(1);
6 | rxtx = a(:,5);
7 | ix = find(a(:,5)>0);
8 | rxtxmin= min(rxtx(ix));
9 | rxtx(ix) = rxtx(ix)-rxtxmin;
10 | ix = find(rxtx < 0);
11 | if length(ix) > 0
12 | plot(T,rxtx,T(ix),maxDelay/10,'ro');
13 | else
14 | plot(T,rxtx);
15 | end
16 | grid;
17 | xlim(Tlim); ylim([0 maxDelay]);
18 | set(gca,'FontSize',12);
19 | xlabel('T[s]');
20 | legend('RX-TX delay','Loss')
21 | title('RX-TX delay [s]');
22 |
23 | end
--------------------------------------------------------------------------------
/scream.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.3.32811.315
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scream_01", "code\scream_01.vcxproj", "{995F8DF3-7BE9-4B48-89EA-4F64046D68C2}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Win32 = Debug|Win32
11 | Release|Win32 = Release|Win32
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {995F8DF3-7BE9-4B48-89EA-4F64046D68C2}.Debug|Win32.ActiveCfg = Debug|Win32
15 | {995F8DF3-7BE9-4B48-89EA-4F64046D68C2}.Debug|Win32.Build.0 = Debug|Win32
16 | {995F8DF3-7BE9-4B48-89EA-4F64046D68C2}.Release|Win32.ActiveCfg = Release|Win32
17 | {995F8DF3-7BE9-4B48-89EA-4F64046D68C2}.Release|Win32.Build.0 = Release|Win32
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {B20F2EED-C0EB-444F-BCAE-BE6E58364120}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/scream_ecn_keyframe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricssonResearch/scream/5d5e4ca2c41ad62875314e5e8d2571efd58aad6a/scream_ecn_keyframe.png
--------------------------------------------------------------------------------
/scream_noecn_keyframe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EricssonResearch/scream/5d5e4ca2c41ad62875314e5e8d2571efd58aad6a/scream_noecn_keyframe.png
--------------------------------------------------------------------------------
/test-record.md:
--------------------------------------------------------------------------------
1 | # Test activities with SCReAM
2 | Test activities ordered, most recent first
3 |
4 | ## Test activity 2024-10-31
5 | SCReAM test with 100Mbps bottleneck with DualPi2 AQM
6 | SCReAM commit 76a298add1ebd3714f86ae6f4a31194ca04a168f (2024-10-31)
7 |
8 | ### Hardware and qdisc configuration
9 | Same as 2024-10-28
10 |
11 | ### Test 2, different RTTs
12 | The test is run with 5 different values of RTT and up to 4 additional TCP loads
13 |
14 | -microburstinterval 0.5
15 | -mtu 1360 (1400 byte in IP level)
16 | -rand 0 (fixed frame sizes)
17 |
18 | | RTT [ms] | 0 TCP | 1 TCP | 2 TCP | 3 TCP | 4 TCP |
19 | | :- |:-:|:-:|:-:|:-:|:-:|
20 | | 5 | 79 | 52 | 40 | 29 | 20 |
21 | | 10 | 78 | 58 | 40 | 28 | 22 |
22 | | 25 | 78 | 60 | 48 | 38 | 29 |
23 | | 50 | 76 | 60 | 43 | 35 | 30 |
24 | | 100 | 71 | 54 | 32 | 25 | 18 |
25 |
26 | 
27 | First 20s only SCreAM then 1 TCP Prague added every 20s
28 |
29 | 
30 | First 20s only SCreAM then 4 TCP Prague for 20s
31 |
32 |
33 | ### Test3, different RTTs, and varying video frame sizes
34 | Like test # 2 but varying video frame sizes
35 |
36 | -microburstinterval 0.5
37 | -mtu 1360 : 1400 byte on IP level
38 | -rand 50 : frame sizes vary +/-1 50% from the nominal (uniform distribution)
39 |
40 | | RTT [ms] | 0 TCP | 1 TCP | 2 TCP | 3 TCP | 4 TCP |
41 | | :- |:-:|:-:|:-:|:-:|:-:|
42 | | 5 | 70 | 48 | 30 | 25 | 18 |
43 | | 10 | 68 | 50 | 36 | 28 | 18 |
44 | | 25 | 68 | 50 | 44 | 32 | 25 |
45 | | 50 | 66 | 46 | 38 | 30 | 23 |
46 | | 100 | 64 | 48 | 38 | 26 | 21 |
47 |
48 | 
49 | First 20s only SCreAM then 1 TCP Prague added every 20s
50 |
51 |
52 | ### Summary
53 | The results do no differ greatly from the test 2024-10-28, this means that the introduced cubic emulation with L4S gives more stable bitrate and less delay spikes and still manages to compete with TCP Prague in the given test range.
54 | SCReAM gets a larger share of the link capacity than is fair. Possibly the algorithm can be tuned a bit more conservative to trade bitrate against a even more stable behavior.
55 |
56 |
57 | ## Test activity 2024-10-28
58 | SCReAM test with 100Mbps bottleneck with DualPi2 AQM
59 | SCReAM commit 994f9a40d4b4a78b8052551e3480b30269d75a3a (2024-10-28)
60 |
61 | ### Hardware and qdisc configuration
62 | The test laptops are two Lenovo ThinkPad E470 with Ubuntu 20.04. The PCs are interconnected with an ethernet cable
63 | Linux release 5.15 with TCP Prague and DualPi2 from
64 | https://github.com/L4STeam/linux is used. Iperf is used as additional load generator, confugured to use L4S and Prague
65 |
66 | The bottleneck is configured on the receiving (client side) with the below script
67 |
68 | ~~~
69 | # Script that runs on the receiving side to model an
70 | # L4S-capable link with 100Mbps throughput and 25ms RTT
71 | # $INTERFACE is the network interface
72 |
73 | sudo modprobe ifb numifbs=1
74 | sudo ip link set dev ifb0 up
75 |
76 | # Delete old stuff
77 | sudo tc qdisc del dev $INTERFACE root
78 | sudo tc qdisc del dev ifb0 root
79 | sudo tc qdisc del dev $INTERFACE handle ffff: ingress
80 |
81 | sudo tc qdisc add dev $INTERFACE handle ffff: ingress
82 | sudo tc filter add dev $INTERFACE parent ffff: protocol ip u32 match u32 0 0 action mirred egress redirect dev ifb0
83 |
84 | # Add 25ms RTT to egress interface
85 | sudo tc qdisc add dev $INTERFACE root netem delay 25ms
86 |
87 | # Ingress, limit and add L4S marking
88 | sudo tc qdisc add dev ifb0 root handle 1: htb default 10
89 | sudo tc class add dev ifb0 parent 1: classid 1:1 htb rate 100mbit ceil 100mbit
90 | sudo tc class add dev ifb0 parent 1:1 classid 1:10 htb rate 100mbit ceil 100mbit
91 | sudo tc qdisc add dev ifb0 parent 1:10 dualpi2
92 | ~~~
93 |
94 |
95 | The expected SCReAM bitrate [Mbps] given the number of additional TCP loads is
96 |
97 | | 0 TCP | 1 TCP | 2 TCP | 3 TCP | 4 TCP |
98 | |:-:|:-:|:-:|:-:|:-:|
99 | | 100 | 50 | 33 | 25 | 20 |
100 |
101 | All tests are run with only one iteration so one can expect a roughlt +/- 5% deviation from the figures below.
102 |
103 | ### Test 1, impact of microburst interval
104 | The test examines the impact of the microburst interval in the SCReAM performance without additional load and with
105 | -microburstinterval X
106 | -mtu 1360 (1400 byte in IP level)
107 | -rand 0
108 |
109 | | X [ms] | 0 TCP | 1 TCP | 2 TCP | 3 TCP | 4 TCP |
110 | | :- |:-:|:-:|:-:|:-:|:-:|
111 | | 0.25 | 71 | 56 | 46 | 39 | 28 |
112 | | 0.5 | 75 | 60 | 48 | 40 | 30 |
113 | | 1.0 | 68 | 56 | 44 | 38 | 30 |
114 | | 2.0 | 41 | 31 | 29 | 29 | 26 |
115 |
116 | The results indicate that a 2ms microburst interval causes SCReAM to over mark in the DualPi2 AQM. It is therefore recommended to use a smaller microburst interval such as 0.5ms.
117 | The results in general indicated that SCReAM underutilizes the link capacity when is does not need to share the capacity with other flows. This is an expected behavior because of the 50% pacing headroom in SCReAM. Furthermore, SCReAM gets more than its fair share when additional load is applied.
118 |
119 | ### Test 2, different RTTs
120 | The test is run with 4 different values of RTT and up to 4 additional TCP loads
121 |
122 | -microburstinterval 0.5
123 | -mtu 1360 (1400 byte in IP level)
124 | -rand 0 (fixed frame sizes)
125 |
126 | | RTT [ms] | 0 TCP | 1 TCP | 2 TCP | 3 TCP | 4 TCP |
127 | | :- |:-:|:-:|:-:|:-:|:-:|
128 | | 5 | 80 | 55 | 35 | 25 | 22 |
129 | | 10 | 75 | 55 | 44 | 30 | 23 |
130 | | 25 | 75 | 60 | 48 | 40 | 30 |
131 | | 50 | 72 | 50 | 32 | 27 | 22 |
132 |
133 | The results give that SCReAM gives rougly the same results regardless of RTT, within the 5ms - 50ms range. SCReAM also gets more than its fair share when additional load is applied.
134 |
135 | ### Test3, different RTTs, and varying video frame sizes
136 | Like test # 2 but varying video frame sizes
137 |
138 | -microburstinterval 0.5
139 | -mtu 1360 : 1400 byte on IP level
140 | -rand 50 : frame sizes vary +/-1 50% from the nominal (uniform distribution)
141 |
142 | | RTT [ms] | 0 TCP | 1 TCP | 2 TCP | 3 TCP | 4 TCP |
143 | | :- |:-:|:-:|:-:|:-:|:-:|
144 | | 5 | 69 | 45 | 35 | 26 | 18 |
145 | | 10 | 66 | 46 | 40 | 28 | 21 |
146 | | 25 | 64 | 53 | 40 | 32 | 22 |
147 | | 50 | 63 | 52 | 39 | 25 | 18 |
148 |
149 | SCReAM gives a lower bitrate when video frame sizes vary. This is an expected result, given that SCReAM adjusts itself to avoid queue build-up because of larger video frames than expected. SCReAM is also (roughly) more fair against other flows
150 |
151 | | 0 TCP | 1 TCP | 2 TCP | 3 TCP | 4 TCP |
152 | |:-:|:-:|:-:|:-:|:-:|
153 | | 100 | 50 | 33 | 25 | 20 |
154 |
155 | ### Summary
156 | In the given test setup with a 100Mbps DualPi2 AQM it can be concluded that:
157 |
158 | + SCReAM is quite robust under competition from up to 4 competing TCP flows within a 5 to 50ms RTT range.
159 | + SCReAM underutilizes the link capacity when no other competing traffic. This is an expected outcome because of the 50% pacing headroom.
160 | + SCReAM gets more than its fair share of the capacity when frame size is fixed. The unfairness is smaller when frame sizes vary in size.
161 | + Microburst interval = 0.5ms is recommended.
162 |
163 |
--------------------------------------------------------------------------------
/test_v_a.m:
--------------------------------------------------------------------------------
1 | function test_v_a(a,Tlim,I,Bmax,Cmax,Dmax)
2 | T = a(:,1);
3 | K = 12;
4 | %Tmax = 100.0;
5 |
6 |
7 | figure(1);
8 | subplot(3,1,1);
9 | ce = a(:,13);
10 | if (I>1)
11 | k = 6;
12 | for n=2:I
13 | ce = ce+a(:,13+k);k=k+6;
14 | end
15 | end
16 | plot(T,a(:,6)/1e3,T,ce/1e3);
17 | set(gca,'FontSize',12);grid on;
18 | set(gca,'XTickLabel',[]);
19 | axis([Tlim(1) Tlim(2) 0 Bmax(1)*1.5]);grid on;
20 | title('Throughput and CE rate [Mbps]');
21 |
22 | subplot(3,1,2);
23 | plot(T,a(:,2),T,a(:,3));
24 | %,T,a(:,4));
25 | set(gca,'FontSize',12);grid on;
26 | set(gca,'XTickLabel',[]);
27 | axis([Tlim(1) Tlim(2) 0 Dmax]);grid on;
28 | title('qdel[s]');
29 |
30 | subplot(3,1,3);
31 | plot(T,a(:,4),T,a(:,5),T,a(:,7)*20000,'k');
32 | set(gca,'FontSize',12);grid on;
33 | axis([Tlim(1) Tlim(2) 0 Cmax]);grid on;
34 | title('CWND & in flight [byte]');
35 | xlabel('T [s]');
36 |
37 | if I>0
38 | figure(2);
39 | subplot(2,1,1);
40 | plot(T,a(:,8));
41 | set(gca,'FontSize',12);grid on;
42 | axis([Tlim(1) Tlim(2) 0 0.05]);grid on;
43 | set(gca,'XTickLabel',[]);
44 | title('RTP queue delay [s]');
45 | subplot(2,1,2);
46 | plot(T,a(:,9)/1000,T,a(:,11)/1000,T,a(:,10)/1000);
47 | set(gca,'FontSize',12);grid on;
48 | axis([Tlim(1) Tlim(2) 0 Bmax(1)]);grid on;
49 | title('Bitrate [Mbps]');
50 | legend('Target','Transmitted', 'RTP', 'X');
51 | xlabel('T [s]');
52 | end
53 |
54 | if I>1
55 | K = 6;
56 | figure(3);
57 | subplot(2,1,1);
58 | plot(T,a(:,8+K));
59 | set(gca,'FontSize',12);grid on;
60 | axis([Tlim(1) Tlim(2) 0 0.05]);grid on;
61 | set(gca,'XTickLabel',[]);
62 | title('RTP queue delay');
63 | subplot(2,1,2);
64 | plot(T,a(:,9+K)/1000,T,a(:,11+K)/1000,T,a(:,10+K)/1000);
65 | set(gca,'FontSize',12);grid on;
66 | axis([Tlim(1) Tlim(2) 0 Bmax(2)]);grid on;
67 | title('Bitrate [kbps]');
68 | legend('Target','Transmitted', 'RTP');
69 | xlabel('T [s]');
70 | end
71 |
72 | if I>2
73 | K = 12;
74 | figure(4);
75 | subplot(2,1,1);
76 | plot(T,a(:,8+K));
77 | set(gca,'FontSize',12);grid on;
78 | axis([Tlim(1) Tlim(2) 0 0.05]);grid on;
79 | set(gca,'XTickLabel',[]);
80 | title('RTP queue delay');
81 | subplot(2,1,2);
82 | plot(T,a(:,9+K)/1000,T,a(:,11+K)/1000,T,a(:,10+K)/1000);
83 | set(gca,'FontSize',12);grid on;
84 | axis([Tlim(1) Tlim(2) 0 Bmax(3)]);grid on;
85 | title('Bitrate [kbps]');
86 | legend('Target','Transmitted', 'RTP');
87 | xlabel('T [s]');
88 | end
89 |
90 | if I>3
91 | K = 18;
92 | figure(5);
93 | subplot(2,1,1);
94 | plot(T,a(:,8+K));
95 | set(gca,'FontSize',12);grid on;
96 | axis([Tlim(1) Tlim(2) 0 0.05]);grid on;
97 | set(gca,'XTickLabel',[]);
98 | title('RTP queue delay');
99 | subplot(2,1,2);
100 | plot(T,a(:,9+K)/1000,T,a(:,11+K)/1000,T,a(:,10+K)/1000);
101 | set(gca,'FontSize',12);grid on;
102 | axis([Tlim(1) Tlim(2) 0 Bmax(3)]);grid on;
103 | title('Bitrate [kbps]');
104 | legend('Target','Transmitted', 'RTP');
105 | xlabel('T [s]');
106 | end
107 |
--------------------------------------------------------------------------------
/traces/trace_flat.txt:
--------------------------------------------------------------------------------
1 | 20000
2 | 20000
3 | 20000
4 | 20000
5 | 20000
6 | 20000
7 | 20000
8 | 20000
9 | 20000
10 | 20000
11 | 20000
12 | 20000
13 | 20000
14 | 20000
15 | 20000
16 | 20000
17 | 20000
18 | 20000
19 | 20000
20 | 20000
21 | 20000
22 | 20000
23 | 20000
24 | 20000
25 | 20000
26 | 20000
27 | 20000
28 | 20000
29 | 20000
30 | 20000
31 | 20000
32 | 20000
33 | 20000
34 | 20000
35 | 20000
36 | 20000
37 | 20000
38 | 20000
39 | 20000
40 | 20000
41 | 20000
42 | 20000
43 | 20000
44 | 20000
45 | 20000
46 | 20000
47 | 20000
48 | 20000
49 | 20000
50 | 20000
51 | 20000
52 | 20000
53 | 20000
54 | 20000
55 | 20000
56 | 20000
57 | 20000
58 | 20000
59 | 20000
60 | 20000
61 | 20000
62 | 20000
63 | 20000
64 | 20000
65 | 20000
66 | 20000
67 | 20000
68 | 20000
69 | 20000
70 | 20000
71 | 20000
72 | 20000
73 | 20000
74 | 20000
75 | 20000
76 | 20000
77 | 20000
78 | 20000
79 | 20000
80 | 20000
81 | 20000
82 | 20000
83 | 20000
84 | 20000
85 | 20000
86 | 20000
87 | 20000
88 | 20000
89 | 20000
90 | 20000
91 | 20000
92 | 20000
93 | 20000
94 | 20000
95 | 20000
96 | 20000
97 | 20000
98 | 20000
99 | 20000
100 | 20000
101 | 20000
102 | 20000
103 | 20000
104 | 20000
105 | 20000
106 | 20000
107 | 20000
108 | 20000
109 | 20000
110 | 20000
111 | 20000
112 | 20000
113 | 20000
114 | 20000
115 | 20000
116 | 20000
117 | 20000
118 | 20000
119 | 20000
120 | 20000
121 | 20000
122 | 20000
123 | 20000
124 | 20000
125 | 20000
126 | 20000
127 | 20000
128 | 20000
129 | 20000
130 | 20000
131 | 20000
132 | 20000
133 | 20000
134 | 20000
135 | 20000
136 | 20000
137 | 20000
138 | 20000
139 | 20000
140 | 20000
141 | 20000
142 | 20000
143 | 20000
144 | 20000
145 | 20000
146 | 20000
147 | 20000
148 | 20000
149 | 20000
150 | 20000
151 | 20000
152 | 20000
153 | 20000
154 | 20000
155 | 20000
156 | 20000
157 | 20000
158 | 20000
159 | 20000
160 | 20000
161 | 20000
162 | 20000
163 | 20000
164 | 20000
165 | 20000
166 | 20000
167 | 20000
168 | 20000
169 | 20000
170 | 20000
171 | 20000
172 | 20000
173 | 20000
174 | 20000
175 | 20000
176 | 20000
177 | 20000
178 | 20000
179 | 20000
180 | 20000
181 | 20000
182 | 20000
183 | 20000
184 | 20000
185 | 20000
186 | 20000
187 | 20000
188 | 20000
189 | 20000
190 | 20000
191 | 20000
192 | 20000
193 | 20000
194 | 20000
195 | 20000
196 | 20000
197 | 20000
198 | 20000
199 | 20000
200 | 20000
201 | 20000
202 | 20000
203 | 20000
204 | 20000
205 | 20000
206 | 20000
207 | 20000
208 | 20000
209 | 20000
210 | 20000
211 | 20000
212 | 20000
213 | 20000
214 | 20000
215 | 20000
216 | 20000
217 | 20000
218 | 20000
219 | 20000
220 | 20000
221 | 20000
222 | 20000
223 | 20000
224 | 20000
225 | 20000
226 | 20000
227 | 20000
228 |
--------------------------------------------------------------------------------
/version-history.md:
--------------------------------------------------------------------------------
1 | # Older version history
2 | - 2024-10-03 :
3 | - Features that more cautiously increases CWND are removed/refined as these deviated too much from the principle of two marked packets per RTT at steady state.
4 | - 2024-09-27 :
5 | - Limit growth on very small CWND added (optional), to make algorithm more stable at very low bitrates when CWND is just a few MSS
6 | - 2024-07-05 :
7 | - Robustness to large packet reordering improved. Feature is currently only enabled for the BW test application. To enable featire in multicam, add #define EXT_OOO_FB in multicam scream_receiver.cpp. Updated code also fixed an issue where even little reordering triggered packet loss reaction.
8 | - -periodicdropinterval option removed. Periodic rate reduction is instead implemented in ScreamV2Tx.cpp.
9 | - ScreamV1Tx.cpp removed.
10 | - BW test tool, summary output displays %-age of packets marked Not-ECT, ECT(0), ECT(1) and CE.
11 | - 2024-05-31 :
12 | - Congestion window validation modified
13 | - 2024-05-20 :
14 | - -emulatecubic option decoupled for very large CWND.
15 | - -emulatecubic option also made available for gstreamer plugin wrapper
16 | - 2024-05-11 :
17 | - -emulatecubic option modified to be adaptive so that SCReAM will have a reasonable chance to compete against competing Prague flows. -emulatecubic is made optional but is recommended as it stabilizes SCReAM target bitrate and can also reduce delay jitter.
18 | - 2024-05-03 :
19 | - isslowencoder option renamed to -emulatecubic as it behaves similar to TCP Cubic with a more moderate CWND growth close to the last known max value. The -emulatecubic option reduces bitrate variations at steady state but comes with the drawback that SCReAM can have problems to compete with Prague CC
20 | - 2024-04-25 :
21 | - Improved stability at very low bitrates
22 | - Added isslowencoder option for the case that rate increase should be more moderate. This comes with the risk that SCReAM is starved by e.g TCP Prague.
23 | - 2024-04-19 :
24 | - Log item RTP queue delay modified to make it possible to add network queue delay and RTP queue delay to see the actual extra delay for transmitted RTP packets.
25 | - SCReAM BW test tool (SCReAMv2 only): Added openWindow option
26 | - 2024-04-17 :
27 | - ScreamV2Tx : openWindow option did not function properly, fixed. Reaction to sudden drop in throughput improved.
28 | - RtpQueue : code after return statement fixed.
29 | - 2024-04-03 :
30 | - Multicam scream_sender.cpp : multiplicativeIncreaseFactor was erroneously set to 1.0, replaced with a much more correct value 0.05.
31 | - ScreamV2Tx : targetBitrate and RTP queue delay added to extra detailed log (-log option).
32 | - 2024-03-27 :
33 | - Stability issue at very low RTTs fixed.
34 | - 2024-03-22 :
35 | - Added method setIsSlowEncoder to increase robustness when video encoders react slowly to updated target bitrates.
36 | - 2024-03-11 :
37 | - Added support for IPv6 in SCReAM BW test application.
38 | - Added counter for Not-ECT, ECT(0), ECT(1) and CE in summary printout.
39 | - 2024-02-21 :
40 | - Added averaging to transmit and rtp rate logs.
41 | - 2024-01-24 :
42 | - Robustness to sudden jumps in sender or receiver clocks improved.
43 | - 2024-01-19 :
44 | - Stream prioritization refined.
45 | - SCReAM RFC8298 update. First draft available [RFC8298-bis](https://github.com/IngJohEricsson/draft-johansson-ccwg-scream-bis "RFC8298-bin")
46 | - SCReAM V2 is made default for gstreamer application.
47 | - 2024-01-10 :
48 | - SCReAM V2 is made default for BW test and multicam application.
49 | - 2023-12-07 :
50 | - General : Added CE marking percentage to statistics, added function to get statistics items. RTCP format error fixed.
51 | - SCReAM V2 : Delay based CC modified for more stable bitrate. Frame size histogram added to handle large frame size variation better
52 | - 2023-11-12 : SCReAM V2 update. Conditional packet pacing is changed to always pacing when packet pacing is enabled. This removes an odd on/off effect in the packet pacing. Packet pacing implementation is updated to allow for micro burst intervals down to 0.2ms
53 | - 2023-11-03 : SCReAM V2 update. The delay based part of SCReAM V2 is modified such that a virtual L4S alpha is computed when L4S is either disabled or inactive. The virtal L4S alpha is calculated based on the estimated queue delay. The resulting algorithm now abandoned most the LEDBAT style approach that was outlined in RFC8298. Some additional previous voodoo magic is removed in the process.
54 | - 2023-09-20 : SCReAM V2. Version 2 is a major rewrite of the complete algorithm with the goal to make the algorithm more stable, especially when used with L4S. Support for V2 is in the BW test algorithm application and the multicam code. SCReAM V2 is enabled by adding -DV2 in the CMAKE_CXX_FLAGS in CMakeLists.txt
The main changes are:
55 | - The congestion window serves mainly as a hand brake to avoid that excessive amounts of data is injected to the network when link thorughput drops dramatically. The congestion window is otherwise seldom a limiting factor in more normal working conditions
56 | - The packet pacing headroom is made large, as a default, the pacing rate is 50% larger than the nominal target rate. The congestion down-scale is adapted to this to still achieve high link ultilization
57 | - The rate control algorith is greatly simplified, with a minimal amount of voodoo magic that is difficult to explain
58 | - The fast increase mode is replaced with a multiplicative increase that sets in fully a configurable time after congestion
59 | - The final algorithm closely follows the 2 CE marks per RTT rule when used with L4S.
60 |
--------------------------------------------------------------------------------