Closed BigNerd95 closed 3 years ago
One possibility at the top of my head would be to recognize whether a client has downloaded the last frame it was sent yet, and if not, put the next fully available frame into the stream. This could be a pointer to a chunked frame.
On Fri, Nov 13, 2020 at 03:04:13AM -0800, Jeremy Kescher wrote:
One possibility at the top of my head would be to recognize whether a client has downloaded the last frame yet, and if not, put the next fully available frame into the stream.
I need to test this, but skipping frames should happen if client send is blocking:
func (pubSub *PubSub) doPublish(data []byte) {
subs := pubSub.subscribers
for s := range subs {
select {
case s.ChunkChannel <- data: // try to send
default: // or skip this frame
}
}
}
-- Valentin
You can reproduce this by changing "Online" to "Slow 3G" in Chrome Developer Tools > Network. Then add a print in these places: https://github.com/vvidic/mjpeg-proxy/blob/master/mjpeg-proxy.go#L412 https://github.com/vvidic/mjpeg-proxy/blob/master/mjpeg-proxy.go#L419
The server block during part.Write (which is correct)
But how you can see by this log, it block after a lot of frame were sent.
chunker[/source3]: started
Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send
# here stop a few seconds (on part.Write)
Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send
# here stop a few seconds
Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send
# here stop a few seconds
Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send
# here stop a few seconds
Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send
# here stop a few seconds
Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send
# here stop a few seconds
Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send
# here stop a few seconds
Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send Send
# ...
Each Send is about 36452 bytes
Note: the first group of Send is much longer than the following ones
So it seems to be filling up an underlying buffer of 8 MB and then block until a 1 MB is free
I just tried with another computer instead of localhost. Now it sends only 6 frame and then block. So maybe there is a buffer only when using localhost?
Anyway, I set 1kb/s on the receiving host, but it would be better if it only sends 1 or max 2 frame.
On Fri, Nov 13, 2020 at 06:36:37AM -0800, Lorenzo Santina wrote:
I just tried with another computer instead of localhost. Now it sends only 6 frame and then block. So maybe there is a buffer only when using localhost?
Anyway, I set 1kb/s on the receiving host, but it would be better if it only sends 1 or max 2 frame.
I did some testing and it seems to behave relatively well already. TCP buffer on a real (not simulated) slow connection should be small and not too many frames should be sent at once.
-- Valentin
Hi! Congrats for this small but very useful project.
It was exactly what I was looking for: pub/sub mjpeg proxy. I made a similar solution some years ago in python for raspberry picamera https://github.com/BigNerd95/picamera/commit/f723b0832f154404c186017a13bf7a14dd48d36b#diff-9dc379f8ac02d2f947ab8b7e67be6877ae0ca646f31a475b0169867e105f91edR112
Anyway my question is:
If a client has a very slow connection, this method sends less frame than the original FPS (which is what I want), but due to tcp buffer (I think) the stream is not real time, because even if you use unbuffered channel, the thread sending frame to a client is not blocking during the tcp send, so it will keep reading frame from the publisher channel until the tcp buffer is full. Only then it will start to drop frame.
I think a possible solution is to reduce the tcp buffer size to a size similar of a single frame, so it will start dropping frame as soon as possible if the viewer connection is too slow to handle the original FPS. Do you have other ideas?