Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[flake8]
max-line-length = 100
ignore = E203, E402, E266, E501, W503
# max-complexity = 18
# select = B,C,E,F,W,T4,B9
36 changes: 36 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
repos:
- repo: https://github.com/Lucas-C/pre-commit-hooks-safety
rev: v1.2.4
hooks:
- id: python-safety-dependencies-check

- repo: 'https://github.com/asottile/reorder_python_imports'
rev: v3.0.1
hooks:
- id: reorder-python-imports
name: 'Reorder Python imports'

- repo: https://github.com/ambv/black
rev: 22.3.0
hooks:
- id: black
language_version: python3.9

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.2.0
hooks:
- id: end-of-file-fixer
- id: trailing-whitespace
- id: check-merge-conflict
- id: requirements-txt-fixer

- repo: https://github.com/sondrelg/pep585-upgrade
rev: 'v1' # Use the sha / tag you want to point at
hooks:
- id: upgrade-type-hints
args: [ '--futures=true' ]

- repo: https://gitlab.com/pycqa/flake8
rev: 3.9.2
hooks:
- id: flake8
4 changes: 4 additions & 0 deletions constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
FRAMEGEN_FFMPEG = "FFMPEG"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use class Framegen(str, Enum): here

FRAMEGEN_XWD = "XWD"
FRAMEGEN_SIMPLE = "FRAMEGEN_SIMPLE"
FRAMEGEN_DOUBLE = "FRAMEGEN_DOUBLE"
116 changes: 116 additions & 0 deletions frame_generator/ffmpeg_double_fg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import os
import subprocess
from logging import getLogger
from threading import Thread

from drop_queue import DropQueue

log = getLogger(__name__)


class FfmpegDoubleFrameGenerator(Thread):
end = False
framebuf: DropQueue

width = 1366
height = 768

framerate = 30
optirun = False
vsync = 2

buffer_size = 1024 * 10

def __init__(self, settings: dict, buf: DropQueue):
super().__init__()
self.framebuf = buf
self.settings = settings

@property
def size(self):
return f"{self.width}x{self.height}"

@property
def size2width(self):
return f"{self.width*2}x{self.height}"

@staticmethod
def api(optirun=False, params=None, **kwargs) -> str:
cmd = "ffmpeg"
if optirun:
cmd = "optirun " + cmd
for i in params:
cmd += f" -{i[0]} {i[1]}"
cmd += " -"
return cmd

def _get_frame(self, data, start, end):
frame = data[start:end]
return frame

def _get_display(self):
# Or try :0.0
# return ":0.0"
return os.getenv("DISPLAY", ":0.0") + "+0,0"

def run(self):
"""
Run ffmpeg stream video in pipe , should run some like:
ffmpeg -f lavfi -i color=white:s=2732x768\
-f x11grab -video_size 1366x768 -framerate 30 -i :0.0 \
-f x11grab -video_size 1366x768 -framerate 30 -i :0.0 \
-filter_complex "overlay,overlay=1366:0" \
-vcodec libx264 test.mkv
Ordering of command parametrs IMPOTANT
"""

self.end = False
params = [
("f", "lavfi"),
("i", f"color=white:s={self.size2width}"),
("f", "x11grab"),
("video_size", self.size),
("framerate", self.framerate),
("i", self._get_display()),
("f", "x11grab"),
("video_size", self.size),
("framerate", self.framerate),
("i", self._get_display()),
("filter_complex", f'"overlay,overlay={self.width}:0"'),
("loglevel", "error"),
("nostdin", ""),
("s", self.size),
("framerate", self.framerate),
("f", "mjpeg"),
# ("vsync", self.vsync),
]
ffmpeg_cmd = self.api(self.optirun, params)
log.info(f"ffmpeg cmd: {ffmpeg_cmd}")
p = subprocess.Popen(
ffmpeg_cmd.split(),
shell=False,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=subprocess.PIPE,
)

data = bytearray()
start = -1
cnt = 0
while not self.end:
data += p.stdout.read(self.buffer_size)

if start == -1:
start = data.find(b"\xFF\xD8\xFF")
continue
else:
end = data.find(b"\xFF\xD9")

if end != -1 and start != -1:
frame = data[start : end + 1]
self.framebuf.put(frame)
log.info(f"frame: {cnt}")
cnt = cnt + 1
data = data[end + 2 :]
start = -1
log.info("DoubleFrameGenerator end")
4 changes: 2 additions & 2 deletions frame_generator/ffmpeg_fg.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ class FfmpegFrameGenerator(Thread):
end = False
framebuf: DropQueue

width = 800 * 2
height = 600
width = 1366
height = 768

framerate = 30
optirun = False
Expand Down
19 changes: 16 additions & 3 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
#!/bin/python3

import logging
from time import sleep

from callback.open_vr import OpenVR
from constants import FRAMEGEN_DOUBLE
from constants import FRAMEGEN_FFMPEG
from constants import FRAMEGEN_SIMPLE
from constants import FRAMEGEN_XWD
from discover import discover
from frame_generator.ffmpeg_double_fg import FfmpegDoubleFrameGenerator
from frame_generator.ffmpeg_fg import FfmpegFrameGenerator
from frame_generator.xwd_fg import XwdFrameGenerator
from sender import Sender
from sensor_client import SensorClient
Expand All @@ -17,11 +22,19 @@ def main():
server_ip = discover()
server_port = 5555
client_port = 7777

framegen_type = FRAMEGEN_FFMPEG
framegen_video_type = FRAMEGEN_DOUBLE
sender = Sender(server_ip, server_port=server_port, client_port=client_port)

# Run frame generator for sender
framegen = XwdFrameGenerator(sender.settings, sender.framebuf)
framegen = None
if framegen_type == FRAMEGEN_FFMPEG:
if framegen_video_type == FRAMEGEN_DOUBLE:
framegen = FfmpegDoubleFrameGenerator(sender.settings, sender.framebuf)
if framegen_video_type == FRAMEGEN_SIMPLE:
framegen = FfmpegFrameGenerator(sender.settings, sender.framebuf)
if framegen_type == FRAMEGEN_XWD:
framegen = XwdFrameGenerator(sender.settings, sender.framebuf)
framegen.start()

# Start sending frames to client
Expand Down