jdillenkofer / camera_proxy

MIT License
46 stars 17 forks source link

P2P Protocol Implementation & Enhancements #10

Closed vherrlein closed 3 years ago

vherrlein commented 3 years ago

The following changes rely only on Camera within the same network. The streaming through a Reolink relay is not implemented yet.

Changes

jdillenkofer commented 3 years ago

Hi, i tried your changes and had a problem with the p2p host discovery:

PS E:\dev\python\camera_proxy> python .\src\main.py
Traceback (most recent call last):
  File "E:\dev\python\camera_proxy\src\main.py", line 12, in <module>
    from camera_stream_manager import CameraStreamManager
  File "E:\dev\python\camera_proxy\src\camera_stream_manager.py", line 3, in <module>
    from camera import Camera
  File "E:\dev\python\camera_proxy\src\camera.py", line 6, in <module>
    import baichuan_udp_layer
  File "E:\dev\python\camera_proxy\src\baichuan_udp_layer.py", line 30, in <module>
    socket.gethostbyname("p2p14.reolink.com"),
socket.gaierror: [Errno 11001] getaddrinfo failed

I removed the domains 14 and 15 and now it works. Maybe we can initialize them in the constructor and only add them if the dns lookup actually works.

I also don't quite understand the gettid method:

    def gettid():
        """Get TID as displayed by htop."""
        libc = 'libc.so.6'
        for cmd in (186, 224, 178):
            tid = ctypes.CDLL(libc).syscall(cmd)
            if tid != -1:
                return tid

Why do you use the syscalls 224 (timer_gettime) and 178 (query_module)? I could only find 186 which is "gettid".

Maybe we can also add a requirements.txt file for the pip dependencies and use that instead of pip installing everything in the Dockerfile. And the Docker EXPOSE 8000 Command doesn't match the port used in the dockerfile (9090) anymore.

Thank you for the pull request. Great changes. Will be happy to merge this, once the last remaining questions are figured out.

vherrlein commented 3 years ago

Hi, Regarding to domains they are coming from a UDP dump based on the Reolink Windows App and the camera itself. Reolink DNS entries from Windows app Reolink DNS entries from Windows app Reolink DNS entries from the camera Reolink DNS entries from the camera

Indeed, we could refactor that piece of code in order to resolve p2p hosts at discovery time with a better approach. Unfortunately, I didn't have enough time to do it.

For syscall id's, long story short, they rely to the target architecture: 186 => x86_64 (64bit) 224 => x86_64 (32bit) 178 => Generic

As references:

For next enhancements, your proposal is really interesting. We could also think about:

I'm currently also working on a way to manage the decoder queue based on a reduction factor calculated according to the processing speed. The main objective, having a correct dropping video frame routine if the machine cannot handle the pressure (CPU heavy loads). Currently, it works but dropping frames without knowing if we are dropping Intra-coded or Predicted frames, it results to wired video, such as a TV Sat HD channel with a bad reception. Available within my feature branch : feature/ENHC-Optimizing_Process

Another potential solution for streaming video, it could be to provide a RTMP service acting as pass-through gateway from frames received without any decoding process (Reolink Cams provides already video in H264 format :)). But that's just in theory...

For your information below my environments. Camera: Reolink Argus Eco

Sample used after the image building

version: "3.3"
services:
  camera_proxy:
    image: camera_proxy:dev-amd64
    configs:
      - source: camera_proxy_config
        target: app/settings.json
    networks:
      - outside
    restart: always
    deploy:
      resources:
        limits:
          memory: 2G

configs:
  camera_proxy_config:
    external: true

networks:
  outside:
    external:
      name: "host"

Hope that would answer your enquiries. Regards

vherrlein commented 3 years ago

For your last question on docker EXPOSE. You’re right, that’s a mistake. A complete review of the docker file would be performed. As the baichuan protocol involves broadcast requests on the same network, for now it’s “mandatory” to connect the container with the Host network.

So, the EXPOSE is just describing, it doesn’t impact the usage of the container within Host network.

As soon as the P2P protocol is implemented end to end, including streaming over a relay, we can expose correct listening ports:

jdillenkofer commented 3 years ago

Do you want to merge your changes already or should I wait for the remaining parts of the p2p protocol?

Regarding the PyAv dependency: What do you think about removing PyAv and use libav with hardware acceleration directly? I run this software on a raspberry pi 4. I don't know how good the OpenCL support of that device is.

We can add rtp support as well. The only reason why I reencode the video stream is because i want to display the images on an fritz!fon (https://avm.de/produkte/fritzfon/) and that device only supports basic jpeg images. Maybe we can add support for webm or something else that is actually well supported across different browsers.

I also thought about switching the language from python to go or rust. But i think the slowest thing right now is the video decoding and we use native libraries for that anyway. Initially this was just a testbed for me to validate my understanding of the camera protocol, but i guess now it has become a small program some people actually use.

vherrlein commented 3 years ago

You can go ahead by merging that PR, it still relevant for a Dev branch. All things we discussed above will be implemented soon with a new PR ;)

surfzoid commented 3 years ago

Hi, very nice news,a way to add battery Cam to zoneminder. An best should be ffmpeg since zm use it,also h264,to use the "pass through" option of zm and sound and why not,see mic control in zm

vherrlein commented 3 years ago

Switching languages right now it’s a bit late 🤣 Allot of people started to use yours. I admit I come from .Net world and C++, I was happy to see your app as foundation which look close to C. So, it was fast to learn Python at the end.

However, one of the next important step would be refactor the overall in order to put in place a better code architecture, design pattern and documentations.

for your info, I’m using Gitflow as DevOps process on my branch.

vherrlein commented 3 years ago

Hi, very nice news,a way to add battery Cam to zoneminder. An best should be ffmpeg since zm use it,also h264,to use the "pass through" option of zm and sound and why not,see mic control in zm

@surfzoid, It was also in our minds for next improvements :)

vherrlein commented 3 years ago

Regarding the PyAv dependency: What do you think about removing PyAv and use libav with hardware acceleration directly? I run this software on a raspberry pi 4. I don't know how good the OpenCL support of that device is.

@jdillenkofer, for now I don't know yet

We can add rtp support as well. The only reason why I reencode the video stream is because i want to display the images on an fritz!fon (https://avm.de/produkte/fritzfon/) and that device only supports basic jpeg images. Maybe we can add support for webm or something else that is actually well supported across different browsers.

Of course, as developers, the only limits is our imagination :)