-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Started implementation from scratch, working player and networking br…
…oadcast
- Loading branch information
0 parents
commit 1d91f08
Showing
22 changed files
with
560 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
# Byte-compiled / optimized / DLL files | ||
__pycache__/ | ||
*.py[cod] | ||
*$py.class | ||
|
||
.idea | ||
|
||
# C extensions | ||
*.so | ||
|
||
# Distribution / packaging | ||
.Python | ||
build/ | ||
develop-eggs/ | ||
dist/ | ||
downloads/ | ||
eggs/ | ||
.eggs/ | ||
lib/ | ||
lib64/ | ||
parts/ | ||
sdist/ | ||
var/ | ||
wheels/ | ||
*.egg-info/ | ||
.installed.cfg | ||
*.egg | ||
MANIFEST | ||
|
||
# PyInstaller | ||
# Usually these files are written by a python script from a template | ||
# before PyInstaller builds the exe, so as to inject date/other infos into it. | ||
*.manifest | ||
*.spec | ||
|
||
# Installer logs | ||
pip-log.txt | ||
pip-delete-this-directory.txt | ||
|
||
# Unit test / coverage reports | ||
htmlcov/ | ||
.tox/ | ||
.coverage | ||
.coverage.* | ||
.cache | ||
nosetests.xml | ||
coverage.xml | ||
*.cover | ||
.hypothesis/ | ||
.pytest_cache/ | ||
|
||
# Translations | ||
*.mo | ||
*.pot | ||
|
||
# Django stuff: | ||
*.log | ||
local_settings.py | ||
db.sqlite3 | ||
|
||
# Flask stuff: | ||
instance/ | ||
.webassets-cache | ||
|
||
# Scrapy stuff: | ||
.scrapy | ||
|
||
# Sphinx documentation | ||
docs/_build/ | ||
|
||
# PyBuilder | ||
target/ | ||
|
||
# Jupyter Notebook | ||
.ipynb_checkpoints | ||
|
||
# pyenv | ||
.python-version | ||
|
||
# celery beat schedule file | ||
celerybeat-schedule | ||
|
||
# SageMath parsed files | ||
*.sage.py | ||
|
||
# Environments | ||
.env | ||
.venv | ||
env/ | ||
venv/ | ||
ENV/ | ||
env.bak/ | ||
venv.bak/ | ||
|
||
# Spyder project settings | ||
.spyderproject | ||
.spyproject | ||
|
||
# Rope project settings | ||
.ropeproject | ||
|
||
# mkdocs documentation | ||
/site | ||
|
||
# mypy | ||
.mypy_cache/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
# Videowall (WIP) | ||
|
||
Video wall with multiple tiles that enables synchronized video playback, mirrored or tiled. | ||
|
||
## Installation | ||
|
||
### Raspberry PI installation | ||
|
||
#### Installation prerequisites | ||
|
||
- Raspbian Jessie | ||
- Raspberry Pi 3 / Raspberry Pi Zero (other Pi's not tested) | ||
- Videowall repository is your current working directory | ||
|
||
#### Installation dependencies | ||
|
||
Install the `x-window-system` and `gstreamer`: | ||
|
||
``` | ||
sudo apt-get -y install x-window-system \ | ||
gstreamer1.0-tools \ | ||
gstreamer1.0-plugins-good \ | ||
gstreamer1.0-plugins-bad \ | ||
gstreamer1.0-plugins-ugly \ | ||
gstreamer1.0-omx \ | ||
gir1.2-gst-plugins-base-1.0 \ | ||
python-gst-1.0 \ | ||
pulseaudio \ | ||
python-enum \ | ||
python-colorlog | ||
``` | ||
|
||
Make sure `gstreamer is working properly` by downloading and playing an x264 encoded sample video: | ||
|
||
``` | ||
wget https://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_30mb.mp4 -O ~/big_buck_bunny_720p_30mb.mp4 | ||
``` | ||
|
||
#### Set-up videowall | ||
|
||
Enable the x-server on startup: | ||
|
||
``` | ||
sudo cp systemd/startx/override.conf /etc/systemd/system/[email protected]/ | ||
sudo systemctl daemon-reload | ||
sudo systemctl restart [email protected] | ||
``` | ||
|
||
If everything went well, the x server should now be running and you should see a black screen with a small green font: `pi@raspberrypi`. | ||
|
||
Add the following to `/etc/X11/xinit/xinitrc` after the first line to disable screen blanking: | ||
``` | ||
xset s off # don't activate screensaver | ||
xset -dpms # disable DPMS (Energy Star) features. | ||
xset s noblank # don't blank the video device | ||
``` | ||
|
||
Set boot config RPI so we can use more GPU memory (not sure whether this has any effect): | ||
``` | ||
echo "gpu_mem = 386MB" | sudo tee -a /boot/config.txt | ||
``` | ||
|
||
## Quick start | ||
|
||
### Server | ||
|
||
scripts/server | ||
|
||
### Client | ||
|
||
scripts/client | ||
|
||
## References | ||
|
||
- [Gstreamer mmal for smooth video playback on RPI](https://gstreamer.freedesktop.org/data/events/gstreamer-conference/2016/John%20Sadler%20-%20Smooth%20video%20on%20Raspberry%20Pi%20with%20gst-mmal%20(Lightning%20Talk).pdf) | ||
- [Gstreamer sync server for synchronized playback on multiple client with a gstreamer client server set-up](https://github.com/ford-prefect/gst-sync-server) | ||
- [Multicast Video-Streaming on Embedded Linux Environment, Daichi Fukui, Toshiba Corporation, Japan Technical Jamboree 63, Dec 1st, 2017](https://elinux.org/images/3/33/Multicast_jamboree63_fukui.pdf) | ||
- [omxplayer-sync](https://github.com/turingmachine/omxplayer-sync) | ||
- [pwomxplayer](https://github.com/JeffCost/pwomxplayer) | ||
- [dbus vlc](https://wiki.videolan.org/DBus-spec/) | ||
- [dbus tutorial phython for MPRIS](http://amhndu.github.io/Blog/python-dbus-mpris.html) | ||
- [dbus omxplayer](https://github.com/popcornmix/omxplayer) | ||
- [GPU memory 90 degrees omxplayer](https://github.com/popcornmix/omxplayer/issues/467) | ||
- [Remote dbus control](https://stackoverflow.com/questions/10158684/connecting-to-dbus-over-tcp/13275973#13275973) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
#!/usr/bin/env python | ||
|
||
|
||
import sys | ||
from players import MasterPlayer | ||
from gi.repository import GObject | ||
import json | ||
|
||
import time | ||
import threading | ||
import select | ||
import socket | ||
|
||
|
||
class MasterThread(threading.Thread): | ||
def __init__(self, uri, broadcast_port, player_ip, player_port): | ||
super(MasterThread, self).__init__() | ||
self.master_player = MasterPlayer(uri, player_ip, player_port) | ||
self.broadcast_port = broadcast_port | ||
|
||
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) | ||
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) | ||
|
||
def send_update(self): | ||
pdu = { | ||
'base-time': self.master_player.base_time, | ||
'uri': self.master_player.uri, | ||
'player-ip': self.master_player.ip, | ||
'player-port': self.master_player.port, | ||
} | ||
self.socket.sendto(json.dumps(pdu), ('<broadcast>', self.broadcast_port)) | ||
|
||
def run(self): | ||
self.master_player.play() | ||
while True: | ||
self.send_update() | ||
time.sleep(1) | ||
|
||
|
||
from argparse import ArgumentParser | ||
|
||
if __name__ == "__main__": | ||
parser = ArgumentParser() | ||
parser.add_argument('uri') | ||
parser.add_argument('--broadcast_port', type=int, default=37020) | ||
parser.add_argument('--player_ip', default='localhost') | ||
parser.add_argument('--player_port', type=int, default=11111) | ||
|
||
args = parser.parse_args() | ||
|
||
GObject.threads_init() | ||
loop = GObject.MainLoop() | ||
|
||
master = MasterThread(args.uri, args.broadcast_port, args.player_ip, args.player_port) | ||
master.start() | ||
|
||
loop.run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import gi | ||
import logging.config | ||
|
||
from client import Client | ||
from server import Server | ||
|
||
gi.require_version('Gst', '1.0') | ||
gi.require_version('GstNet', '1.0') | ||
|
||
logging.config.dictConfig({ | ||
'version': 1, | ||
'disable_existing_loggers': False, | ||
'formatters': { | ||
'colored': { | ||
'()': 'colorlog.ColoredFormatter', | ||
'format': "%(log_color)s[%(levelname)s] %(name)s: %(message)s", | ||
} | ||
}, | ||
'handlers': { | ||
'stream': { | ||
'class': 'logging.StreamHandler', | ||
'formatter': 'colored', | ||
}, | ||
}, | ||
'root': { | ||
'handlers': ['stream'], | ||
'level': 'INFO', | ||
}, | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
class Client(object): | ||
def __init__(self): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from networking_client import NetworkingClient | ||
from networking_server import NetworkingServer |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from collections import namedtuple | ||
|
||
BroadcastMessage = namedtuple("BroadcastMessage", ("filename", "base_time", "player_ip", "player_port")) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import json | ||
import logging | ||
import socket | ||
|
||
from message_definition import BroadcastMessage | ||
from networking_exceptions import NetworkingException | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class NetworkingClient(object): | ||
def __init__(self, broadcast_port, buffer_size=1024): | ||
self._socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP | ||
self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) | ||
self._socket.bind(("", broadcast_port)) # Bind to all | ||
self._buffer_size = buffer_size | ||
|
||
def receive_broadcast(self): | ||
data, _ = self._socket.recvfrom(self._buffer_size) | ||
|
||
try: | ||
msg = BroadcastMessage(**json.loads(data)) | ||
except Exception as e: | ||
raise NetworkingException(e) | ||
else: | ||
logger.debug("Received %s", msg) | ||
return msg |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
class NetworkingException(Exception): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import json | ||
import socket | ||
import logging | ||
|
||
from .message_definition import BroadcastMessage | ||
from .networking_exceptions import NetworkingException | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class NetworkingServer(object): | ||
def __init__(self, broadcast_port): | ||
self._socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) | ||
self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) | ||
self._broadcast_port = broadcast_port | ||
|
||
def send_broadcast(self, msg): | ||
if not isinstance(msg, BroadcastMessage): | ||
raise NetworkingException("msg ({}) is not of type NetworkingException".format(msg)) | ||
|
||
logger.debug("Sending %s", msg) | ||
self._socket.sendto(json.dumps(msg._asdict()), ('<broadcast>', self._broadcast_port)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from player_client import PlayerClient | ||
from player_server import PlayerServer | ||
from player_platforms import PlayerPlatform |
Oops, something went wrong.