-
-
Notifications
You must be signed in to change notification settings - Fork 54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix pause buffers #82
Conversation
For me it is ingiardabile both in substream and in mainstream. |
Still not sure what's up with your camera. You had the error in steam message which usually means the cameras internal buffer filled up (not neolink but the camera itself). Could you provide some specs on your model. What's the resolution fps, os, docker/native etc. if I get others with the same issue I'll see if I can find some common ground. |
Reolink Argus 3 Pro |
P.s. if you set |
neolink=debug ./neolink rtsp --config=neolink.toml > log.txt 2>&1 |
Many possible reasons. Official client dosent need to worry about internal buffers or queues or timestamps or anything needed for rtsp expected by clients it just displays last frame which can reduce artifacts. Additionally they seem to have a slightly non standard h264 stream (perhaps some approximations in their hardware encoder) that causes some issues like invalid NAL units. Since Reolink writes both decoder and encoder they can accommodate for this. Where as neolink does nothing but pass it on and let the client deal with it. I also don't know what all of the parameters in the packets do. For example there's an integer value in the acknowledgment packet that seems to update randomly ever 1s. It could be some sort of latency that is used to negotiate dropping frames. This is a reverse engineering project everything has to be learned by testing live there's no nice docs or standard reference to look up. If you think you can do better please make your own contribution. I cannot test and tinker with cameras I don't own. |
Like this: RUST_LOG=neolink=debug ./neolink rtsp --config=neolink.toml > log.txt 2>&1 |
I really appreciate your work, I'm not here to criticize in any way. |
Here is a short log, if you need longer I'll do it again. |
I just think there's an internal buffer that's filling and that's why we get that error. Evidence:
This behaviour is akin to a fixed size ring buffer.
|
Why it fills I haven't quite figured out yet. The camera (and neolink) have to maintain a buffer of packets for UDP reassembly. What this means is camera sends a packet of id 100 then 101 etc when I get the packet I acknowledge it by saying yes I got 100. After which the camera should delete it from its buffer. We both need to maintain this buffer because UDP is lossy. I might get packet 105 before packets 103 and 104. So in this case I tell the camera that I have packets 100,102 and 105 and request a resend of 103 and 104. Perhaps for example the camera is not accepting my acknowledge packets in the way it expects and it's over filling it's buffer because of this. I really can't tell since I don't observer this error often enough. I do know that I get this error more often when there's a congested network for example when the family is streaming a lot of video. |
If I can help you understand better with other tests I am available... Currently I am alone in the house and I am using the internet only to answer you, no active streaming and no other use of the network. |
One thing we could try is a wireshark dump of the packets. Then I could check if the camera is sending the right packets after an acknowledgement or sending old packets or even tell if neolink has sent the wrong acknowledgments. |
Buts it's kinda a different issue and not related to this PR |
If you explain to me how to do it I will do it ... |
Something like this would work I think though might need tinkering as I havent done this in awhile: sudo apt-get install tcpdump
sudo tcpdump host CAM_IP_ADDRESS -w capture.pcap Should capture all packets to and from the camera ip and write them into the capture.pcap file. Set your camea password to a dummy one first or change it afterwards because reolinks password encryption is not too strong and it can likely be cracked from these packets. Press Cntl-C when done to stop the dump |
I launch this command with neolink working right? |
Launch in another terminal before neolink starts, start neolink, let neolink run for a while, stop neolink, stop tcpdump |
I‘m getting the following error since the lastest Build: (Argus 3 pro) neolink::rtsp::gst::sender] Buffer exhausted. Not enough data from Camera. is this error related to this? |
Possibly I am tracking a few issue with the latest release some I am going to mark them as pre-release until I get them sorted |
Definitely much better but it still freezes. Here's the log. |
Thanks. I'm going to get some sleep now and check it out in the morning. Hopefully I can make sense of it. |
Here's the log. |
So from your logs, substream works fine but mainStream does not |
Just did some math on your logs and in 60s of real time only 50s of video frame is recieved. It's not comming in fast enough to be live |
Unfortunately at the moment I can't tell you if I see a jerky or fluid stream because I'm away from home... for now only the logs... |
Could you try perhaps putting your cameras bitrate down to 1536 (using the offical app) |
The log suggests that it works like that with the lower bitrate |
Is this a fixable problem on neolink? |
Have you considered this is a limitation of the network. Unlike the official client where they have a direct connection here we act as a relay we both download and re-upload the data increasing the load on the network. |
Yes, I thought about it, that's why I asked if it can be solved with neolink ... at the same time, however, I think, I have a ubiquiti u6-lr 2 meters from the camera connected in 5ghz ... it is plausible that the network can't do it ? |
Things you could try is putting the neolink on Ethernet to the switch. Not sure how easy that would be for you to test. If I can find the time I'll try and look at the timestamps in the tcp dump you sent. See how many packet replays and losses there are etc. |
The server where Neolink runs is connected via ethernet, only the cameras are wifi. |
I see then not much else I can recommend to test this |
Ok I checked your tcpdump and in 2m of real time only 1m53s of video has arrived. This is what arrives on the socket even before neolink attempts ANY processing or even just recieving it. It suggests that the nework can't quite handle the load. It's not the sort of thing I can do to address. I might be able to setup some sort of dynamic bitrate to adjsut the bitrate down if the load gets too high but that would be in another PR |
Ok so one last thing I have tried is to increase the MTU, it should give us about 300 extra bytes per packet but not sure if it will be enough, |
The MTU of a network is usually 1500. Some of this data is used for the IP header so you get about 1450 of usable data. After that we have about 100 bytes for the BCUdp data and the BC header leaving about 1350 bytes to pack the video into. This is the value reolink uses. Before I was using a more conservative estimate of 1050 bytes, so by changing this we get an extra 300bytes per packet |
I did some testing with the official app and my network cannot stream 2048kbps at 1080p(15fps) without pauses and buffering. Seems to be fine for maybe 15s then it buffers for 20s then plays for another 15 etc with time jumps in stamps. This was tested lower that your 1440p 15fps, bitrate 3072kbps |
Further tests with 1536kbps also have occasional pauses and time jumps (but not as much as 2048kbps) (official reolink client) |
I saw that if I only do the mainstream by removing the stream I can get to 2048kbps without problems. |
Well if you use client pause then you can stream them one at a time. It's the reason I wanted to add that feature. Currently though client and motion pause turn on both sub and main so My next project will probably be getting it to know when your streaming sub and main stream then only stream the right one. |
Some fixes to the buffer after a pause to keep it filled so we can play smoothly