Skip to content

Commit

Permalink
Bug in using the pre-compiled janus path
Browse files Browse the repository at this point in the history
  • Loading branch information
kennethjiang committed May 14, 2024
1 parent ecafeed commit 7a904fd
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 58 deletions.
61 changes: 27 additions & 34 deletions moonraker_obico/janus_config_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,61 +5,54 @@
import distro
import subprocess
import re
import shutil


from .utils import os_bit, pi_version
from .utils import os_bit, pi_version, board_id

JANUS_ROOT_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'bin', 'janus')
RUNTIME_JANUS_ETC_DIR = os.path.join(JANUS_ROOT_DIR, 'runtime', 'etc', 'janus')
TPL_JANUS_ETC_DIR = os.path.join(JANUS_ROOT_DIR, 'templates', 'etc', 'janus')

distro_id = distro.id()
if distro_id == 'debian' and pi_version(): # On some Raspbian/RPi OS versions, distro.id() returns 'debian' instead of 'raspbian'.
distro_id = 'raspbian'
if distro_id == 'raspbian' and pi_version(): # On some Raspbian/RPi OS versions, distro.id() returns 'debian'. On others, it returns 'raspbian'.
distro_id = 'debian'

PRECOMPILED_DIR = '{root_dir}/precomplied/{os_id}.{os_version}.{os_bit}'.format(root_dir=JANUS_ROOT_DIR, os_id=distro_id, os_version=distro.major_version(), os_bit=os_bit())
PRECOMPILED_DIR = '{root_dir}/precomplied/{board_id}.{os_id}.{os_version}.{os_bit}'.format(root_dir=JANUS_ROOT_DIR, board_id=board_id(), os_id=distro_id, os_version=distro.major_version(), os_bit=os_bit())

_logger = logging.getLogger('obico.janus_config_builder')

def precompiled_janus_jcfg_folders_section(lib_dir):
def janus_jcfg_folders_section(lib_dir):
return """
plugins_folder = "{lib_dir}/janus/plugins" # Plugins folder
transports_folder = "{lib_dir}/janus/transports" # Transports folder
events_folder = "{lib_dir}/janus/events" # Event handlers folder
loggers_folder = "{lib_dir}/janus/loggers"
""".format(lib_dir=lib_dir)

def system_janus_jcfg_folders_section(janus_jcfg_path):
pattern = r'^\s*(plugins_folder|transports_folder|events_folder|loggers_folder)\s*='
filtered_lines = []

with open(janus_jcfg_path, 'r') as f:
for line in f:
if re.search(pattern, line):
filtered_lines.append(line)

return ''.join(filtered_lines)


def find_system_janus_jcfg_path():
janus_path = shutil.which('janus')
janus_jcfg_path = None

if not janus_path:
return (None, None)
def find_system_janus_paths():
janus_path = None
janus_lib_path = None

try:
output = subprocess.check_output(['dpkg', '-L', 'janus'], universal_newlines=True)
paths = output.split('\n')
for path in paths:
path = path.strip()
if path.endswith('/janus.jcfg'):
janus_jcfg_path = path

# janus binary path if only 1 line ends with /bin/janus
janus_paths = [path.strip() for path in paths if path.strip().endswith('/bin/janus')]
if len(janus_paths) == 1:
janus_path = janus_paths[0]

# janus lib path if line contains plugins/libjanus_streaming.so
janus_lib_paths = [path.strip() for path in paths if '/janus/plugins/libjanus_streaming.so' in path]
if janus_lib_paths:
janus_lib_path = os.path.dirname(janus_lib_paths[0])
janus_lib_path = os.path.normpath(janus_lib_path)
if janus_lib_path.endswith('/janus/plugins'):
janus_lib_path = janus_lib_path[:-14] # remove "/plugins" from the end

except (subprocess.CalledProcessError, FileNotFoundError):
pass

return (janus_path, janus_jcfg_path)
return (janus_path, janus_lib_path)


def build_janus_jcfg(auth_token):
Expand All @@ -69,14 +62,14 @@ def build_janus_jcfg(auth_token):
janus_bin_path = None
folder_section = None

(janus_bin_path, system_janus_jcfg_path) = find_system_janus_jcfg_path()
if janus_bin_path and system_janus_jcfg_path:
folder_section = system_janus_jcfg_folders_section(system_janus_jcfg_path)
(janus_bin_path, system_janus_lib_path) = find_system_janus_paths()
if janus_bin_path and system_janus_lib_path:
folder_section = janus_jcfg_folders_section(system_janus_lib_path)
else:
janus_bin_path = os.path.join(PRECOMPILED_DIR, 'bin', 'janus')
ld_lib_path = os.path.join(PRECOMPILED_DIR, 'lib')
if os.path.exists(janus_bin_path) and os.path.exists(ld_lib_path) and os.path.isdir(ld_lib_path):
folder_section = precompiled_janus_jcfg_folders_section(ld_lib_path)
folder_section = janus_jcfg_folders_section(ld_lib_path)

if not janus_bin_path or not folder_section:
return (None, None)
Expand Down
14 changes: 14 additions & 0 deletions moonraker_obico/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,9 +322,23 @@ def pi_version():
except:
return None


def os_bit():
return platform.architecture()[0].replace("bit", "-bit")


def board_id():
model_file = "/sys/firmware/devicetree/base/model"
if os.path.isfile(model_file):
with open(model_file, 'r') as file:
data = file.read()
if "raspberry" in data.lower():
return "rpi"
elif "makerbase" in data.lower() or "roc-rk3328-cc" in data:
return "mks"
return "NA"


def parse_integer_or_none(s):
try:
return int(s)
Expand Down
58 changes: 34 additions & 24 deletions moonraker_obico/webcam_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,35 +102,45 @@ def start(self, webcam_configs):
self.assign_janus_params()
try:
(janus_bin_path, ld_lib_path) = build_janus_config(self.webcams, self.app_config.server.auth_token, JANUS_WS_PORT, JANUS_ADMIN_WS_PORT, self.sentry)
if not janus_bin_path:
_logger.error('Janus not found or not configured correctly. Quiting webcam streaming.')
self.server_conn.post_printer_event_to_server(
'moonraker-obico: Webcam Streaming Failed',
'The webcam streaming failed to start. Obico is now streaming at 0.1 FPS.',
event_class='WARNING',
info_url='https://www.obico.io/docs/user-guides/webcam-stream-stuck-at-1-10-fps/',
)
self.shutdown()
return

self.janus = JanusConn(JANUS_WS_PORT, self.app_config, self.server_conn, self.is_pro, self.sentry)
self.janus.start(janus_bin_path, ld_lib_path)

if not self.wait_for_janus():
for webcam in self.webcams:
webcam.setdefault('error', 'Janus failed to start')

for webcam in self.webcams:
if webcam.streaming_params['mode'] == 'h264_rtsp':
continue # No extra process is needed when the mode is 'h264_rtsp'
elif webcam.streaming_params['mode'] == 'h264_copy':
self.h264_copy(webcam)
elif webcam.streaming_params['mode'] == 'h264_transcode':
self.h264_transcode(webcam)
elif webcam.streaming_params['mode'] == 'mjpeg_webrtc':
self.mjpeg_webrtc(webcam)

normalized_webcams = [self.normalized_webcam_dict(webcam) for webcam in self.webcams]
self.printer_state.set_webcams(normalized_webcams)
self.server_conn.post_status_update_to_server(with_settings=True)

return (normalized_webcams, None) # return value expected for a passthru target
except Exception:
self.sentry.captureException()
_logger.error('Error in configuring janus. Quiting webcam streaming.')
_logger.error('Error. Quitting webcam streaming.', exc_info=True)
self.shutdown()
return

self.janus = JanusConn(JANUS_WS_PORT, self.app_config, self.server_conn, self.is_pro, self.sentry)
self.janus.start(janus_bin_path, ld_lib_path)

if not self.wait_for_janus():
for webcam in self.webcams:
webcam.setdefault('error', 'Janus failed to start')

for webcam in self.webcams:
if webcam.streaming_params['mode'] == 'h264_rtsp':
continue # No extra process is needed when the mode is 'h264_rtsp'
elif webcam.streaming_params['mode'] == 'h264_copy':
self.h264_copy(webcam)
elif webcam.streaming_params['mode'] == 'h264_transcode':
self.h264_transcode(webcam)
elif webcam.streaming_params['mode'] == 'mjpeg_webrtc':
self.mjpeg_webrtc(webcam)

normalized_webcams = [self.normalized_webcam_dict(webcam) for webcam in self.webcams]
self.printer_state.set_webcams(normalized_webcams)
self.server_conn.post_status_update_to_server(with_settings=True)

return (normalized_webcams, None) # return value expected for a passthru target

def shutdown(self):
self.shutting_down = True
self.shutdown_subprocesses()
Expand Down

0 comments on commit 7a904fd

Please sign in to comment.