There is a trick for achieving low latency video with TCP: set SO_SNDBUF to the lowest possible value and do your own buffering. If your buffer grows too large, lower the bitrate and/or drop frames.
298 karma · joined April 18, 2015
There is a trick for achieving low latency video with TCP: set SO_SNDBUF to the lowest possible value and do your own buffering. If your buffer grows too large, lower the bitrate and/or drop frames.
I feel that the VNC protocol gets a bad reputation because of bad implementations. There's really nothing in the protocol itself that keeps it back.
What I like about VNC is that you can actually read the RFC and get fairly a good understanding of it in less than a day. I'm not sure if the same can be said for RDP.
Microsoft has this page where you can access a bunch of PDF documents that describe RDP in some sense, but I've no idea where I would even start and/or what's even relevant for any given problem that you might want to solve.
I have written recursive descent parsers in the past, and if I remember correctly, the way I set things up, I had to handle leading list elements specially. It's possible that this was unnecessary and I was simply blinded to a simpler way of doing things because I was following the EBNF too strictly.
Edit: I noticed that we're not actually accounting for an empty list here. That makes things slightly more complex:
comma-separated = [ element, *(",", element) ];
Your code would need to test if there is an element or a list terminator before processing the element.If the marker is "-", EBNF might look like this:
leading-marker-list = *("-", element)
Comma separated would look like this: comma-separated = [ element, *(",", element) ]
This is not meant as an argument for or against; just an observation.Edit: Amended comma separated EBNF to account for an empty list.
An example of a truly inefficient encoding method is ZRLE. It is a tiled zlib and run-length encoded format that can't be split up into multiple jobs because future computation depends on past computation.
They got things right with the tight encoding method of which there are two variants: zlib (lossless) and jpeg. With zlib, you can have up to 4 separate zlib streams, which means that you can utilise 4 CPU cores for encoding in parallel. The jpeg method has no such limitations.
RDP also supports plain framebuffers and that's what we use.
Anyhow, with the advent of specialised hardware for video encoding, passing framebuffers isn't necessarily such a bad option. You just have to make sure that the CPU doesn't touch the framebuffer before encoding and after decoding.
Perhaps you can tell us what's wrong with his "ridiculous breadboard thing" rather than just stating that it's ridiculous?
About damage tracking and hardware encoding: The encoder must always diff the whole frame. There is no magic involved here. It probably does it intelligently, e.g. by hashing blocks and comparing the hashes rather than the memory regions. However, comparing the whole frame still means that you must read the entire frame from memory.
He is correct in saying that an encoder that is aware of damage regions would be more efficient. This is because it would require a lot less memory bandwidth.
He is also correct about 60 fps compositor updates. You probably just misinterpreted his meaning. What he's saying is that when there is nothing happening on screen, you shouldn't tell the compositor to keep updating the content because that just wastes energy on compositing something that hasn't changed.
However, this is tricky when you have a constant bandwidth h264 stream because you will have incremental updates for the same frame. A trick I've used to get past this is to stop encoding when the size of the encoded packages goes below a certain threshold, at which point the image isn't going to improve much.
I've been experimenting with ONVIF to create an IP camera that can be integrated with windows without the user having to install any additional software. I almost never touch windows and I must say that the experience has been very frustrating because things do not behave according to spec and I can't look at the source code to see what's actually happening.
Access to source code makes a world of difference. Otherwise, you're left guessing and the quality of your product will suffer because you end up doing "whatever works" under your circumstances. Under different circumstances that can break.
About VNC, yes, it is slow and laggy... on a raspberry pi 3. ;)
It depends on the encoding and implementation, really. For example, I see that Mr. Wolf is using raw encoding for the RTP stream, so bandwidth is hardly a problem. Thus, I would be surprised if VNC with raw encoding would be any slower than that. In fact, it should be even faster because WayVNC will only send the parts of the image that actually changed, whereas wf-recorder will send the whole image every time. Of course, it also depends on the client. I recommend tigervnc.
I would also like to mention that VNC has, recently, gained support for H264 encoding and WayVNC can do zero-copy h264 encoding on the GPU/VPU using VAAPI. Clients that support h264 so far are: tigervnc and wlvncc. However, only wlvncc does it using hardware decoding and hardware rendering. It really falls short, when it needs to touch the CPU. When that happens, you're better off with Tight encoding.
Edit: I should mention that h264 does not work on Raspberry Pi yet. It needs hardware specific encoder and decoder.
Edit 2: Actually, I misremembered about RTP. My troubles were with multicast RTSP.
Perhaps people like me, who just make things work, are a part of the problem? I mean, if they don't get any negative feedback, I guess they'll just assume that people are happy with their products.
Then again, does anyone actually want loud beeps and bright lights on home appliances? Who are those people?
I'm sorry, I don't see how your analogy with computer architecture applies. Like with all things, knolling can be taken to an extreme, but as I understand it, the idea is to keep shared work stations clean and ready for the next person or yourself and to keep things organised while you're working, in such a way that you don't have to go looking for tools that you need.
The distinction helps me being honest with myself about what my role really is, and this means that I am less likely to be overly clever where it is not needed, which would lead to technical debt.
To be clear: a craft is not a "lesser job" than engineering and very often requires just as much ingenuity. My main goal with writing the article is to keep myself honest about what my work is about most of the time and not to think too highly of myself.
Are you absolutely sure that most of your time is spent analyzing and designing and not implementing or doing routine maintenance?
A mutex may try to spin more than a "couple of times" before it calls futex. Example: https://git.musl-libc.org/cgit/musl/tree/src/thread/pthread_...
Installing those dependencies on a regular PC is easy, but not so on an embedded system. I tried cross-compiling the dependencies once, but got stuck at some point. It would've been hard to justify the time spent if I'd continued, so I dropped it. I'm really happy that someone has invested time into this issue.