Created
November 9, 2021 04:48
-
-
Save dasl-/d5bed823af668a4b677410c707343996 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
diff --git a/docs/configuring_omxplayer.adoc b/docs/configuring_omxplayer.adoc | |
index 5369839..942002d 100644 | |
--- a/docs/configuring_omxplayer.adoc | |
+++ b/docs/configuring_omxplayer.adoc | |
@@ -8,12 +8,6 @@ At time of writing, https://github.com/dasl-/piwall2/blob/5625b8887f528f671b7944 | |
omxplayer --crop {0} --adev {1} --display {2} --vol {3} --aspect-mode stretch --no-keys --timeout 30 --threshold 0.2 --video_fifo 35 --genlog pipe:0 | |
.... | |
-Of particular note are the `threshold` and `video_fifo` options: | |
-.... | |
- --threshold n Amount of buffered data required to finish buffering [s] | |
- --video_fifo n Size of video output fifo in MB | |
-.... | |
- | |
Here is some https://github.com/popcornmix/omxplayer/issues/256[more info about some of the more interesting omxplayer parameters]. | |
## omxplayer configuration | |
@@ -34,10 +28,17 @@ In the omxplayer log, we will see https://gist.github.com/dasl-/0caa95c6c438685b | |
Raising the timeout should make these types of errors less likely. See also https://github.com/dasl-/piwall2/blob/main/docs/issues_weve_seen_before.adoc#receivers-sometimes-fail-to-play-video | |
### threshold | |
-Raising the `threshold` was necessary to prevent random occasional video drop outs. See: https://github.com/dasl-/piwall2/blob/main/docs/profiling_and_debugging_multicast_video_playback.adoc . Hopefully setting it to 5 seconds is enough to accomodate playing of all videos without pauses / drop outs. | |
+.... | |
+ --threshold n Amount of buffered data required to finish buffering [s] | |
+.... | |
+ | |
+Although we set it explicitly to 0.2s, this is the same as the https://github.com/popcornmix/omxplayer/blob/1f1d0ccd65d3a1caa86dc79d2863a8f067c8e3f8/omxplayer.cpp#L1177[default threshold value]. | |
### video_fifo | |
-Increasing the `video_fifo` option was necessary to accomodate the increased threshold. Without increasing the video_fifo, we'd see videos with a threshold of 5 seconds take about 90 seconds to start playing. In other words, they were taking about 85 seconds longer than expected to start playing. What were they doing all this time? Let's look at a https://gist.github.com/dasl-/0e52feccff6caacecf0955011f925aeb[log from such a run]. From the logs, it looks like we started receiving video signal at around 02:46:07, yet it took until 02:47:39 (about 90 seconds) for the video to actually unpause: | |
+.... | |
+ --video_fifo n Size of video output fifo in MB | |
+.... | |
+If using a `--threshold` value that is much higher than the default, it may be necessary to increase the `video_fifo` size. Without increasing the `video_fifo`, we'd see videos with a `threshold` of 5 seconds take about 90 seconds to start playing. In other words, they were taking about 85 seconds longer than expected to start playing. What were they doing all this time? Let's look at a https://gist.github.com/dasl-/0e52feccff6caacecf0955011f925aeb[log from such a run]. From the logs, it looks like we started receiving video signal at around 02:46:07, yet it took until 02:47:39 (about 90 seconds) for the video to actually unpause: | |
.... | |
02:47:39 T:2123221681 DEBUG: OMXClock::OMXSetSpeed(1.00) pause_resume:1 | |
.... | |
@@ -49,6 +50,8 @@ If we https://gist.github.com/dasl-/1b0070adf0dbcaca22986d2f33afe88e[filter for | |
Increasing the `video_fifo` size appears to solve the problem, indicating that omxplayer likely didn't have enough memory allocated to buffer the requested 5 seconds of video. Presumably it gave up after about 90 seconds and started playing anyway. By increasing the buffer, we only have to wait about 5 seconds for the video to start playing. | |
+The default `video_fifo` size is https://github.com/popcornmix/omxplayer/blob/1f1d0ccd65d3a1caa86dc79d2863a8f067c8e3f8/OMXVideo.h#L83[`4.6875`]. | |
+ | |
### audio_fifo | |
If we ever need to increase the `threshold` more, we may need to raise `video_fifo` again. Note that according to the logs, the audio buffers didn't go very far past 6.33 seconds. If we ever need to raise the `threshold` beyond that, we may need to increase audio buffer sizes also. Using the `audio_fifo` option to omxplayer didn't seem to have any effect, however. Reading the omxplayer source, it actually seemed like the `audio_fifo` option might not get used for anything, i.e. it's a no-op? Worth reconfirming sometime. | |
diff --git a/piwall2/broadcaster/videobroadcaster.py b/piwall2/broadcaster/videobroadcaster.py | |
index cffe3e3..509d433 100644 | |
--- a/piwall2/broadcaster/videobroadcaster.py | |
+++ b/piwall2/broadcaster/videobroadcaster.py | |
@@ -20,8 +20,8 @@ class VideoBroadcaster: | |
END_OF_VIDEO_MAGIC_BYTES = b'PIWALL2_END_OF_VIDEO_MAGIC_BYTES' | |
- __VIDEO_URL_TYPE_YOUTUBEDL = 'video_url_type_youtubedl' | |
- __VIDEO_URL_TYPE_FILE = 'video_url_type_file' | |
+ __VIDEO_URL_TYPE_YOUTUBE = 'video_url_type_youtube' | |
+ __VIDEO_URL_TYPE_LOCAL_FILE = 'video_url_type_local_file' | |
__AUDIO_FORMAT = 'bestaudio' | |
# Touch this file when video playing is done. | |
@@ -82,6 +82,8 @@ class VideoBroadcaster: | |
def __broadcast_internal(self): | |
self.__logger.info(f"Starting broadcast for: {self.__video_url}") | |
+ self.__start_receivers() | |
+ | |
""" | |
What's going on here? We invoke youtube-dl (ytdl) three times in the broadcast code: | |
1) To populate video metadata, including dimensions which allow us to know how much to crop the video | |
@@ -114,7 +116,6 @@ class VideoBroadcaster: | |
""" | |
download_and_convert_video_proc = self.__start_download_and_convert_video_proc() | |
self.__get_video_info(assert_data_not_yet_loaded = True) | |
- self.__start_receivers() | |
""" | |
This `sleep` makes the videos more likely to start in-sync across all the TVs, but I'm not totally | |
@@ -132,7 +133,7 @@ class VideoBroadcaster: | |
See data collected on the effectiveness of this sleep: | |
https://gist.github.com/dasl-/e5c05bf89c7a92d43881a2ff978dc889 | |
""" | |
- time.sleep(2) | |
+ # time.sleep(2) | |
video_broadcast_proc = self.__start_video_broadcast_proc(download_and_convert_video_proc) | |
self.__logger.info("Waiting for download_and_convert_video and video_broadcast procs to end...") | |
@@ -176,7 +177,7 @@ class VideoBroadcaster: | |
ffmpeg_input_clause = self.__get_ffmpeg_input_clause() | |
audio_clause = '-c:a mp2 -b:a 192k' # TODO: is this necessary? Can we use mp3? | |
- if self.__get_video_url_type() == self.__VIDEO_URL_TYPE_FILE: | |
+ if self.__get_video_url_type() == self.__VIDEO_URL_TYPE_LOCAL_FILE: | |
# Don't transcode audio if we don't need to | |
audio_clause = '-c:a copy' | |
@@ -195,6 +196,13 @@ class VideoBroadcaster: | |
return download_and_convert_video_proc | |
def __start_video_broadcast_proc(self, download_and_convert_video_proc): | |
+ msg = { | |
+ 'video_width': self.__get_video_info()['width'], | |
+ 'video_height': self.__get_video_info()['height'], | |
+ } | |
+ self.__control_message_helper.send_msg(ControlMessageHelper.TYPE_VIDEO_DIMENSIONS, msg) | |
+ self.__logger.info("Sent video_dimensions control message.") | |
+ | |
# See: https://github.com/dasl-/piwall2/blob/main/docs/controlling_video_broadcast_speed.adoc | |
mbuffer_size = round(Receiver.VIDEO_PLAYBACK_MBUFFER_SIZE_BYTES / 2) | |
burst_throttling_clause = (f'HOME=/home/pi mbuffer -q -l /tmp/mbuffer.out -m {mbuffer_size}b | ' + | |
@@ -222,8 +230,7 @@ class VideoBroadcaster: | |
def __start_receivers(self): | |
msg = { | |
'log_uuid': Logger.get_uuid(), | |
- 'video_width': self.__get_video_info()['width'], | |
- 'video_height': self.__get_video_info()['height'], | |
+ 'video_url_type': self.__get_video_url_type() | |
} | |
self.__control_message_helper.send_msg(ControlMessageHelper.TYPE_PLAY_VIDEO, msg) | |
self.__logger.info("Sent play_video control message.") | |
@@ -242,7 +249,7 @@ class VideoBroadcaster: | |
def __get_ffmpeg_input_clause(self): | |
video_url_type = self.__get_video_url_type() | |
- if video_url_type == self.__VIDEO_URL_TYPE_YOUTUBEDL: | |
+ if video_url_type == self.__VIDEO_URL_TYPE_YOUTUBE: | |
""" | |
Pipe to mbuffer to avoid video drop outs when youtube-dl temporarily loses its connection | |
and is trying to reconnect: | |
@@ -294,7 +301,7 @@ class VideoBroadcaster: | |
) | |
return f"-i <({youtube_dl_video_cmd}) -i <({youtube_dl_audio_cmd})" | |
- elif video_url_type == self.__VIDEO_URL_TYPE_FILE: | |
+ elif video_url_type == self.__VIDEO_URL_TYPE_LOCAL_FILE: | |
return f"-i {shlex.quote(self.__video_url)} " | |
# Lazily populate video_info from youtube. This takes a couple seconds, as it invokes youtube-dl on the video. | |
@@ -306,7 +313,7 @@ class VideoBroadcaster: | |
return self.__video_info | |
video_url_type = self.__get_video_url_type() | |
- if video_url_type == self.__VIDEO_URL_TYPE_YOUTUBEDL: | |
+ if video_url_type == self.__VIDEO_URL_TYPE_YOUTUBE: | |
self.__logger.info("Downloading and populating video metadata...") | |
ydl_opts = { | |
'format': self.__config_loader.get_youtube_dl_video_format(), | |
@@ -347,7 +354,7 @@ class VideoBroadcaster: | |
self.__logger.info(f"Using: {self.__video_info['vcodec']} / {self.__video_info['ext']}@" + | |
f"{self.__video_info['width']}x{self.__video_info['height']}") | |
- elif video_url_type == self.__VIDEO_URL_TYPE_FILE: | |
+ elif video_url_type == self.__VIDEO_URL_TYPE_LOCAL_FILE: | |
# TODO: guard against unsupported video formats | |
ffprobe_cmd = ('ffprobe -hide_banner -v 0 -of csv=p=0 -select_streams v:0 -show_entries stream=width,height ' + | |
shlex.quote(self.__video_url)) | |
@@ -365,9 +372,9 @@ class VideoBroadcaster: | |
def __get_video_url_type(self): | |
if self.__video_url.startswith('http://') or self.__video_url.startswith('https://'): | |
- return self.__VIDEO_URL_TYPE_YOUTUBEDL | |
+ return self.__VIDEO_URL_TYPE_YOUTUBE | |
else: | |
- return self.__VIDEO_URL_TYPE_FILE | |
+ return self.__VIDEO_URL_TYPE_LOCAL_FILE | |
def __update_youtube_dl(self): | |
update_youtube_dl_output = (subprocess | |
diff --git a/piwall2/controlmessagehelper.py b/piwall2/controlmessagehelper.py | |
index 3be55ef..783227e 100644 | |
--- a/piwall2/controlmessagehelper.py | |
+++ b/piwall2/controlmessagehelper.py | |
@@ -16,6 +16,7 @@ class ControlMessageHelper: | |
TYPE_PLAY_VIDEO = 'play_video' | |
TYPE_SKIP_VIDEO = 'skip_video' | |
TYPE_DISPLAY_MODE = 'display_mode' | |
+ TYPE_VIDEO_DIMENSIONS = 'video_dimensions' | |
CTRL_MSG_TYPE_KEY = 'msg_type' | |
CONTENT_KEY = 'content' | |
diff --git a/piwall2/displaymode.py b/piwall2/displaymode.py | |
index 6664fb0..02e552d 100644 | |
--- a/piwall2/displaymode.py | |
+++ b/piwall2/displaymode.py | |
@@ -5,3 +5,5 @@ class DisplayMode: | |
# Repeat mode is like this: https://i.imgur.com/cpS61s8.png | |
DISPLAY_MODE_TILE = 'DISPLAY_MODE_TILE' | |
DISPLAY_MODE_REPEAT = 'DISPLAY_MODE_REPEAT' | |
+ | |
+ DISPLAY_MODES = (DISPLAY_MODE_TILE, DISPLAY_MODE_REPEAT) | |
diff --git a/piwall2/receiver/receiver.py b/piwall2/receiver/receiver.py | |
index bcbcb46..7ccc6fc 100644 | |
--- a/piwall2/receiver/receiver.py | |
+++ b/piwall2/receiver/receiver.py | |
@@ -19,11 +19,6 @@ class Receiver: | |
VIDEO_PLAYBACK_MBUFFER_SIZE_BYTES = 1024 * 1024 * 400 # 400 MB | |
- __DEFAULT_CROP_ARGS = { | |
- DisplayMode.DISPLAY_MODE_TILE: None, | |
- DisplayMode.DISPLAY_MODE_REPEAT: None, | |
- } | |
- | |
def __init__(self): | |
self.__logger = Logger().set_namespace(self.__class__.__name__) | |
self.__logger.info("Started receiver!") | |
@@ -34,10 +29,8 @@ class Receiver: | |
self.__display_mode = DisplayMode.DISPLAY_MODE_TILE | |
self.__display_mode2 = DisplayMode.DISPLAY_MODE_TILE | |
- # Crop arguments to send to omxplayer for the currently playing video if the display mode changes. | |
- # These change per video, thus we just initialize them to dummy values in the constructor. | |
- self.__crop_args = self.__DEFAULT_CROP_ARGS | |
- self.__crop_args2 = self.__DEFAULT_CROP_ARGS | |
+ self.__crop_args = None | |
+ self.__crop_args2 = None | |
config_loader = ConfigLoader() | |
self.__receiver_config_stanza = config_loader.get_own_receiver_config_stanza() | |
@@ -89,6 +82,9 @@ class Receiver: | |
self.__stop_video_playback_if_playing() | |
self.__receive_and_play_video_proc = self.__receive_and_play_video(ctrl_msg) | |
self.__receive_and_play_video_proc_pgid = os.getpgid(self.__receive_and_play_video_proc.pid) | |
+ elif msg_type == ControlMessageHelper.TYPE_VIDEO_DIMENSIONS: | |
+ if self.__is_video_playback_in_progress: | |
+ self.__set_video_crop_args(ctrl_msg) | |
elif msg_type == ControlMessageHelper.TYPE_SKIP_VIDEO: | |
if self.__is_video_playback_in_progress: | |
self.__stop_video_playback_if_playing() | |
@@ -101,29 +97,25 @@ class Receiver: | |
old_display_mode = self.__display_mode | |
old_display_mode2 = self.__display_mode2 | |
for tv_num, tv_id in self.__tv_ids.items(): | |
+ display_mode_to_set = display_mode_by_tv_id[tv_id] | |
+ if display_mode_to_set not in DisplayMode.DISPLAY_MODES: | |
+ display_mode_to_set = DisplayMode.DISPLAY_MODE_TILE | |
if tv_id in display_mode_by_tv_id: | |
if tv_num == 1: | |
- self.__display_mode = display_mode_by_tv_id[tv_id] | |
+ self.__display_mode = display_mode_to_set | |
else: | |
- self.__display_mode2 = display_mode_by_tv_id[tv_id] | |
- if self.__is_video_playback_in_progress and old_display_mode != self.__display_mode: | |
- if self.__display_mode == DisplayMode.DISPLAY_MODE_REPEAT: | |
- self.__omxplayer_controller.set_crop(self.__crop_args[DisplayMode.DISPLAY_MODE_REPEAT]) | |
- else: | |
- self.__omxplayer_controller.set_crop(self.__crop_args[DisplayMode.DISPLAY_MODE_TILE]) | |
- if self.__is_video_playback_in_progress and old_display_mode2 != self.__display_mode2: | |
- pass # TODO | |
+ self.__display_mode2 = display_mode_to_set | |
+ if self.__is_video_playback_in_progress and self.__crop_args and old_display_mode != self.__display_mode: | |
+ self.__omxplayer_controller.set_crop(self.__crop_args[self.__display_mode]) | |
+ if self.__is_video_playback_in_progress and self.__crop_args2 and old_display_mode2 != self.__display_mode2: | |
+ pass # TODO display_mode2 with a second dbus interface name | |
def __receive_and_play_video(self, ctrl_msg): | |
ctrl_msg_content = ctrl_msg[ControlMessageHelper.CONTENT_KEY] | |
self.__orig_log_uuid = Logger.get_uuid() | |
Logger.set_uuid(ctrl_msg_content['log_uuid']) | |
- cmd, self.__crop_args, self.__crop_args2 = ( | |
- self.__receiver_command_builder.build_receive_and_play_video_command_and_get_crop_args( | |
- ctrl_msg_content['log_uuid'], ctrl_msg_content['video_width'], | |
- ctrl_msg_content['video_height'], self.__video_player_volume_pct, | |
- self.__display_mode, self.__display_mode2 | |
- ) | |
+ cmd = self.__receiver_command_builder.build_receive_and_play_video_command( | |
+ ctrl_msg_content['log_uuid'], self.__video_player_volume_pct | |
) | |
self.__logger.info(f"Running receive_and_play_video command: {cmd}") | |
self.__is_video_playback_in_progress = True | |
@@ -132,6 +124,13 @@ class Receiver: | |
) | |
return proc | |
+ def __set_video_crop_args(self, ctrl_msg): | |
+ ctrl_msg_content = ctrl_msg[ControlMessageHelper.CONTENT_KEY] | |
+ self.__crop_args, self.__crop_args2 = self.__receiver_command_builder.get_crop_dimensions( | |
+ ctrl_msg_content['video_width'], ctrl_msg_content['video_height'] | |
+ ) | |
+ self.__omxplayer_controller.set_crop(self.__crop_args[self.__display_mode]) | |
+ | |
def __stop_video_playback_if_playing(self): | |
if not self.__is_video_playback_in_progress: | |
return | |
@@ -144,6 +143,8 @@ class Receiver: | |
pass | |
Logger.set_uuid(self.__orig_log_uuid) | |
self.__is_video_playback_in_progress = False | |
+ self.__crop_args = None | |
+ self.__crop_args2 = None | |
# The first video that is played after a system restart appears to have a lag in starting, | |
# which can affect video synchronization across the receivers. Ensure we have played at | |
diff --git a/piwall2/receiver/receivercommandbuilder.py b/piwall2/receiver/receivercommandbuilder.py | |
index b9e4437..d4c3f64 100644 | |
--- a/piwall2/receiver/receivercommandbuilder.py | |
+++ b/piwall2/receiver/receivercommandbuilder.py | |
@@ -15,18 +15,12 @@ class ReceiverCommandBuilder: | |
self.__config_loader = config_loader | |
self.__receiver_config_stanza = receiver_config_stanza | |
- def build_receive_and_play_video_command_and_get_crop_args( | |
- self, log_uuid, video_width, video_height, volume_pct, display_mode, display_mode2 | |
- ): | |
+ def build_receive_and_play_video_command(self, log_uuid, volume_pct): | |
adev, adev2 = self.__get_video_command_adev_args() | |
display, display2 = self.__get_video_command_display_args() | |
- crop_args, crop_args2 = self.__get_video_command_crop_args(video_width, video_height) | |
- crop = crop_args[display_mode] | |
- crop2 = crop_args2[display_mode2] | |
- | |
- volume_pct = VolumeController.normalize_vol_pct(volume_pct) | |
# See: https://github.com/popcornmix/omxplayer/#volume-rw | |
+ volume_pct = VolumeController.normalize_vol_pct(volume_pct) | |
if volume_pct == 0: | |
volume_millibels = VolumeController.GLOBAL_MIN_VOL_VAL | |
else: | |
@@ -65,16 +59,16 @@ class ReceiverCommandBuilder: | |
f'{piwall2.receiver.receiver.Receiver.VIDEO_PLAYBACK_MBUFFER_SIZE_BYTES}b') | |
# See: https://github.com/dasl-/piwall2/blob/main/docs/configuring_omxplayer.adoc | |
- omx_cmd_template = ('omxplayer --crop {0} --adev {1} --display {2} --vol {3} --aspect-mode stretch ' + | |
- '--no-keys --timeout 30 --threshold 0.2 --video_fifo 35 --genlog pipe:0') | |
+ omx_cmd_template = ('omxplayer --adev {0} --display {1} --vol {2} --aspect-mode stretch ' + | |
+ '--no-keys --timeout 30 --threshold 0.2 --video_fifo 10 --genlog pipe:0') | |
omx_cmd = omx_cmd_template.format( | |
- shlex.quote(crop), shlex.quote(adev), shlex.quote(display), shlex.quote(str(volume_millibels)) | |
+ shlex.quote(adev), shlex.quote(display), shlex.quote(str(volume_millibels)) | |
) | |
cmd = 'set -o pipefail && ' | |
if self.__receiver_config_stanza['is_dual_video_output']: | |
omx_cmd2 = omx_cmd_template.format( | |
- shlex.quote(crop2), shlex.quote(adev2), shlex.quote(display2), shlex.quote(str(volume_millibels)) | |
+ shlex.quote(adev2), shlex.quote(display2), shlex.quote(str(volume_millibels)) | |
) | |
cmd += f'{mbuffer_cmd} | tee >({omx_cmd}) >({omx_cmd2}) >/dev/null' | |
else: | |
@@ -82,51 +76,7 @@ class ReceiverCommandBuilder: | |
receiver_cmd = (f'{DirectoryUtils().root_dir}/bin/receive_and_play_video --command {shlex.quote(cmd)} ' + | |
f'--log-uuid {shlex.quote(log_uuid)}') | |
- return (receiver_cmd, crop_args, crop_args2) | |
- | |
- def __get_video_command_adev_args(self): | |
- receiver_config = self.__receiver_config_stanza | |
- adev = None | |
- if receiver_config['audio'] == 'hdmi' or receiver_config['audio'] == 'hdmi0': | |
- adev = 'hdmi' | |
- elif receiver_config['audio'] == 'headphone': | |
- adev = 'local' | |
- elif receiver_config['audio'] == 'hdmi_alsa' or receiver_config['audio'] == 'hdmi0_alsa': | |
- adev = 'alsa:default:CARD=b1' | |
- else: | |
- raise Exception(f"Unexpected audio config value: {receiver_config['audio']}") | |
- | |
- adev2 = None | |
- if receiver_config['is_dual_video_output']: | |
- if receiver_config['audio2'] == 'hdmi1': | |
- adev2 = 'hdmi1' | |
- elif receiver_config['audio2'] == 'headphone': | |
- adev2 = 'local' | |
- elif receiver_config['audio'] == 'hdmi1_alsa': | |
- adev2 = 'alsa:default:CARD=b2' | |
- else: | |
- raise Exception(f"Unexpected audio2 config value: {receiver_config['audio2']}") | |
- | |
- return (adev, adev2) | |
- | |
- def __get_video_command_display_args(self): | |
- receiver_config = self.__receiver_config_stanza | |
- display = None | |
- if receiver_config['video'] == 'hdmi' or receiver_config['video'] == 'hdmi0': | |
- display = '2' | |
- elif receiver_config['video'] == 'composite': | |
- display = '3' | |
- else: | |
- raise Exception(f"Unexpected video config value: {receiver_config['video']}") | |
- | |
- display2 = None | |
- if receiver_config['is_dual_video_output']: | |
- if receiver_config['video2'] == 'hdmi1': | |
- display2 = '7' | |
- else: | |
- raise Exception(f"Unexpected video2 config value: {receiver_config['video2']}") | |
- | |
- return (display, display2) | |
+ return receiver_cmd | |
""" | |
Returns a set of crop args supporting two display modes: tile mode and repeat mode. | |
@@ -136,7 +86,7 @@ class ReceiverCommandBuilder: | |
We return four crop settings because for each mode, we calculate the crop arguments | |
for each of two TVs (each receiver can have at most two TVs hooked up to it). | |
""" | |
- def __get_video_command_crop_args(self, video_width, video_height): | |
+ def get_crop_dimensions(self, video_width, video_height): | |
receiver_config = self.__receiver_config_stanza | |
##################################################################################### | |
@@ -230,6 +180,50 @@ class ReceiverCommandBuilder: | |
} | |
return (crop_args, crop_args2) | |
+ def __get_video_command_adev_args(self): | |
+ receiver_config = self.__receiver_config_stanza | |
+ adev = None | |
+ if receiver_config['audio'] == 'hdmi' or receiver_config['audio'] == 'hdmi0': | |
+ adev = 'hdmi' | |
+ elif receiver_config['audio'] == 'headphone': | |
+ adev = 'local' | |
+ elif receiver_config['audio'] == 'hdmi_alsa' or receiver_config['audio'] == 'hdmi0_alsa': | |
+ adev = 'alsa:default:CARD=b1' | |
+ else: | |
+ raise Exception(f"Unexpected audio config value: {receiver_config['audio']}") | |
+ | |
+ adev2 = None | |
+ if receiver_config['is_dual_video_output']: | |
+ if receiver_config['audio2'] == 'hdmi1': | |
+ adev2 = 'hdmi1' | |
+ elif receiver_config['audio2'] == 'headphone': | |
+ adev2 = 'local' | |
+ elif receiver_config['audio'] == 'hdmi1_alsa': | |
+ adev2 = 'alsa:default:CARD=b2' | |
+ else: | |
+ raise Exception(f"Unexpected audio2 config value: {receiver_config['audio2']}") | |
+ | |
+ return (adev, adev2) | |
+ | |
+ def __get_video_command_display_args(self): | |
+ receiver_config = self.__receiver_config_stanza | |
+ display = None | |
+ if receiver_config['video'] == 'hdmi' or receiver_config['video'] == 'hdmi0': | |
+ display = '2' | |
+ elif receiver_config['video'] == 'composite': | |
+ display = '3' | |
+ else: | |
+ raise Exception(f"Unexpected video config value: {receiver_config['video']}") | |
+ | |
+ display2 = None | |
+ if receiver_config['is_dual_video_output']: | |
+ if receiver_config['video2'] == 'hdmi1': | |
+ display2 = '7' | |
+ else: | |
+ raise Exception(f"Unexpected video2 config value: {receiver_config['video2']}") | |
+ | |
+ return (display, display2) | |
+ | |
""" | |
The displayable width and height represents the section of the video that the wall will be | |
displaying. A section of these dimensions will be taken from the center of the original |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment