Skip to content

Commit 97c66e2

Browse files
committed
Attempt ar reducing latency on the PI
1 parent 552f53b commit 97c66e2

7 files changed

+182
-158
lines changed

gs/src/Comms.cpp

+52-23
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ struct Comms::PCap
9292
int rx_pcap_selectable_fd = 0;
9393

9494
size_t _80211_header_length = 0;
95+
size_t index = 0;
9596
};
9697

9798
struct Comms::TX
@@ -136,13 +137,14 @@ struct Comms::TX
136137

137138
struct Comms::RX
138139
{
139-
std::thread thread;
140+
std::vector<std::thread> threads;
140141

141142
fec_t* fec = nullptr;
142143
std::array<uint8_t const*, 16> fec_src_packet_ptrs;
143144
std::array<uint8_t*, 32> fec_dst_packet_ptrs;
144145

145146
std::vector<PCap*> pcaps;
147+
std::vector<uint32_t> pcal_last_block_index;
146148

147149
size_t transport_packet_size = 0;
148150
size_t streaming_packet_size = 0;
@@ -248,8 +250,9 @@ Comms::~Comms()
248250

249251
m_impl->tx.packet_queue_cv.notify_all();
250252

251-
if (m_impl->rx.thread.joinable())
252-
m_impl->rx.thread.join();
253+
for (auto& thread: m_impl->rx.threads)
254+
if (thread.joinable())
255+
thread.join();
253256

254257
if (m_impl->tx.thread.joinable())
255258
m_impl->tx.thread.join();
@@ -490,6 +493,10 @@ bool Comms::process_rx_packet(PCap& pcap)
490493

491494
std::lock_guard<std::mutex> lg(rx.block_queue_mutex);
492495

496+
//keep track of what interface returned what index.
497+
//this should allow us to skip stale blocks sooner
498+
rx.pcal_last_block_index[pcap.index] = block_index;
499+
493500
if (block_index < rx.next_block_index)
494501
{
495502
//LOGW("Old packet: {} < {}", block_index, rx.next_block_index);
@@ -783,21 +790,24 @@ bool Comms::init(RX_Descriptor const& rx_descriptor, TX_Descriptor const& tx_des
783790
interfaces.insert(i);
784791
interfaces.insert(m_tx_descriptor.interface);
785792

793+
m_impl->rx.pcal_last_block_index.resize(interfaces.size());
786794
m_impl->rx.pcaps.resize(interfaces.size());
787795
m_impl->pcaps.resize(interfaces.size());
788796
size_t index = 0;
789-
for (auto& i: interfaces)
797+
for (auto& interf: interfaces)
790798
{
791799
m_impl->pcaps[index] = std::make_unique<PCap>();
792-
if (!prepare_pcap(i, *m_impl->pcaps[index]))
800+
if (!prepare_pcap(interf, *m_impl->pcaps[index]))
793801
return false;
794802

795-
if (m_tx_descriptor.interface == i)
803+
m_impl->pcaps[index]->index = index;
804+
805+
if (m_tx_descriptor.interface == interf)
796806
m_impl->tx.pcap = m_impl->pcaps[index].get();
797807

798808
for (size_t j = 0; j < m_rx_descriptor.interfaces.size(); j++)
799809
{
800-
if (m_rx_descriptor.interfaces[j] == i)
810+
if (m_rx_descriptor.interfaces[j] == interf)
801811
{
802812
m_impl->rx.pcaps[j] = m_impl->pcaps[index].get();
803813
break;
@@ -807,7 +817,8 @@ bool Comms::init(RX_Descriptor const& rx_descriptor, TX_Descriptor const& tx_des
807817
}
808818

809819
m_impl->tx.thread = std::thread([this]() { tx_thread_proc(); });
810-
m_impl->rx.thread = std::thread([this]() { rx_thread_proc(); });
820+
for (size_t i = 0; i < m_rx_descriptor.interfaces.size(); i++)
821+
m_impl->rx.threads.push_back(std::thread([this, i]() { rx_thread_proc(i); }));
811822

812823
#if defined RASPBERRY_PI_XXX
813824
{
@@ -829,9 +840,10 @@ bool Comms::init(RX_Descriptor const& rx_descriptor, TX_Descriptor const& tx_des
829840

830841
////////////////////////////////////////////////////////////////////////////////////////////
831842

832-
void Comms::rx_thread_proc()
843+
void Comms::rx_thread_proc(size_t index)
833844
{
834845
RX& rx = m_impl->rx;
846+
PCap& pcap = *rx.pcaps[index];
835847

836848
while (!m_exit)
837849
{
@@ -842,18 +854,11 @@ void Comms::rx_thread_proc()
842854
to.tv_usec = 30000;
843855

844856
FD_ZERO(&readset);
845-
for (size_t i = 0; i < m_rx_descriptor.interfaces.size(); i++)
846-
FD_SET(rx.pcaps[i]->rx_pcap_selectable_fd, &readset);
857+
FD_SET(pcap.rx_pcap_selectable_fd, &readset);
847858

848859
int n = select(30, &readset, nullptr, nullptr, &to);
849-
if (n != 0)
850-
{
851-
for (size_t i = 0; i < m_rx_descriptor.interfaces.size(); i++)
852-
{
853-
if (FD_ISSET(rx.pcaps[i]->rx_pcap_selectable_fd, &readset))
854-
process_rx_packet(*rx.pcaps[i]);
855-
}
856-
}
860+
if (n != 0 && FD_ISSET(pcap.rx_pcap_selectable_fd, &readset))
861+
process_rx_packet(pcap);
857862
}
858863
}
859864

@@ -1093,7 +1098,7 @@ void Comms::process_rx_packets()
10931098
uint32_t coding_k = m_rx_descriptor.coding_k;
10941099
uint32_t coding_n = m_rx_descriptor.coding_n;
10951100

1096-
std::lock_guard<std::mutex> lg(rx.block_queue_mutex);
1101+
std::unique_lock<std::mutex> lg(rx.block_queue_mutex);
10971102

10981103
if (Clock::now() - rx.last_packet_tp > m_rx_descriptor.reset_duration)
10991104
rx.next_block_index = 0;
@@ -1127,6 +1132,14 @@ void Comms::process_rx_packets()
11271132
//entire block received
11281133
if (block->packets.size() >= coding_k)
11291134
{
1135+
//sanity check - this should not happen
1136+
for (size_t i = 0; i < block->packets.size(); i++)
1137+
{
1138+
RX::Packet_ptr const& d = block->packets[i];
1139+
if (!d->is_processed)
1140+
LOGI("Skipping {}!!!", block->index * coding_k + d->index);
1141+
}
1142+
11301143
rx.last_block_tp = Clock::now();
11311144
rx.next_block_index = block->index + 1;
11321145
rx.block_queue.pop_front();
@@ -1170,7 +1183,9 @@ void Comms::process_rx_packets()
11701183
}
11711184
}
11721185

1186+
lg.unlock(); //not need to hold the mutex locked - give the rx_proc a chance to get its data in
11731187
fec_decode(rx.fec, rx.fec_src_packet_ptrs.data(), rx.fec_dst_packet_ptrs.data(), indices.data(), rx.payload_size);
1188+
lg.lock(); //relock the mutex
11741189

11751190
//now dispatch them
11761191
for (size_t i = 0; i < block->packets.size(); i++)
@@ -1197,9 +1212,21 @@ void Comms::process_rx_packets()
11971212
continue; //next packet
11981213
}
11991214

1215+
//calculate what is the earliest block index received
1216+
uint32_t earliest_block_index = std::numeric_limits<uint32_t>::max();
1217+
for (uint32_t index: rx.pcal_last_block_index)
1218+
earliest_block_index = std::min(earliest_block_index, index);
1219+
12001220
//skip if too much buffering
1201-
if (rx.block_queue.size() > 3)
1221+
bool skipped_blocks = false;
1222+
while ((rx.block_queue.size() > 0 && rx.block_queue.front()->index < earliest_block_index) || //if all interfaces received blocks bigger that the first in the queue
1223+
rx.block_queue.size() > 3) //or if queueing too much
12021224
{
1225+
// if (rx.block_queue.front()->index < earliest_block_index)ˇ
1226+
// LOGI("Skipping stale packet: fast");
1227+
// else
1228+
// LOGI("Skipping stale packet: slow");
1229+
12031230
for (size_t i = 0; i < block->packets.size(); i++)
12041231
{
12051232
RX::Packet_ptr const& d = block->packets[i];
@@ -1208,10 +1235,12 @@ void Comms::process_rx_packets()
12081235
}
12091236
rx.next_block_index = block->index + 1;
12101237
rx.block_queue.pop_front();
1238+
skipped_blocks = true;
12111239
}
12121240

1213-
//crt packet is not complete, stop until we get more packets
1214-
break;
1241+
//nothing else to do - we cannot complete nor skip blocks - so wait for more data
1242+
if (!skipped_blocks)
1243+
break;
12151244
}
12161245
}
12171246

gs/src/Comms.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class Comms
6060
void process_rx_packets();
6161

6262
void tx_thread_proc();
63-
void rx_thread_proc();
63+
void rx_thread_proc(size_t index);
6464

6565
TX_Descriptor m_tx_descriptor;
6666
RX_Descriptor m_rx_descriptor;

gs/src/PI_HAL.cpp

+39-9
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,26 @@ extern "C"
4444

4545
extern uint8_t s_font_droid_sans[];
4646

47+
/* To install & compile SDL2 with DRM:
48+
49+
--- Install dependencies
50+
51+
sudo apt build-dep libsdl2
52+
sudo apt install libdrm-dev libgbm-dev
53+
54+
--- Build SDL2:
55+
git clone SDL2
56+
cd SDL
57+
mkdir build
58+
cd build
59+
../configure --disable-video-rpi --enable-video-kmsdrm --enable-video-x11 --disable-video-opengl
60+
make -j5
61+
sudo make install
62+
63+
--- Run:
64+
sudo -E LD_LIBRARY_PATH=/usr/local/lib DISPLAY=:0 ./gs
65+
*/
66+
4767
///////////////////////////////////////////////////////////////////////////////////////////////////
4868

4969
struct PI_HAL::Impl
@@ -245,20 +265,28 @@ bool PI_HAL::init_display_sdl()
245265
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
246266
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
247267
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
248-
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0);
249-
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
268+
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0);
269+
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
250270

251271
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
252272
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
253273
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
254274
SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
255275

276+
int driver_count = SDL_GetNumVideoDrivers();
277+
LOGI("Drivers: {}", driver_count);
278+
for (int i = 0; i < driver_count; i++)
279+
{
280+
LOGI("Driver {}: {}", i, SDL_GetVideoDriver(i));
281+
}
282+
256283
SDL_DisplayMode mode;
257284
int res = SDL_GetCurrentDisplayMode(0, &mode);
258285
assert(res == 0);
259286

260287
m_impl->width = mode.w;
261288
m_impl->height = mode.h;
289+
LOGI("Mode {}: {}x{}", res, mode.w, mode.h);
262290

263291
// Create an application window with the following settings:
264292
m_impl->window = SDL_CreateWindow(
@@ -267,19 +295,24 @@ bool PI_HAL::init_display_sdl()
267295
SDL_WINDOWPOS_UNDEFINED, // initial y position
268296
m_impl->width, // width, in pixels
269297
m_impl->height, // height, in pixels
270-
SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN
298+
SDL_WINDOW_FULLSCREEN |
299+
SDL_WINDOW_OPENGL |
300+
SDL_WINDOW_SHOWN |
301+
SDL_WINDOW_BORDERLESS
271302
);
272303

273304
// Check that the window was successfully created
274305
if (m_impl->window == nullptr)
275306
{
276307
// In the case that the window could not be made...
277-
LOGW("Cannot create window: {}", SDL_GetError());
308+
LOGE("Cannot create window: {}", SDL_GetError());
278309
return false;
279310
}
280311

281312
m_impl->context = SDL_GL_CreateContext(m_impl->window);
282-
SDL_GL_MakeCurrent(m_impl->window, m_impl->context);
313+
int err = SDL_GL_MakeCurrent(m_impl->window, m_impl->context);
314+
if (err != 0)
315+
LOGE("Failed to create context: {}", err);
283316

284317
ImGui::CreateContext();
285318
ImGui_ImplSDL2_InitForOpenGL(m_impl->window, m_impl->context);
@@ -396,11 +429,8 @@ bool PI_HAL::update_display()
396429
}
397430
}
398431

399-
#ifdef USE_BOUBLE_BUFFER
400432
SDL_GL_SwapWindow(m_impl->window);
401-
#else
402-
glFlush();
403-
#endif
433+
//glFlush();
404434

405435
ImGui_ImplSDL2_NewFrame(m_impl->window);
406436
#else

0 commit comments

Comments
 (0)