-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathapp.py
More file actions
executable file
·160 lines (137 loc) · 6.19 KB
/
app.py
File metadata and controls
executable file
·160 lines (137 loc) · 6.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#!/usr/bin/python3
import subprocess
import sys
import signal
import threading
import configparser
# TODO: make sure LD_LIBRARY_PATH / DYLD_LIBRARY_PATH is defined here ...
# it may be undefined when using a wrapper bash script, then libgpac import fails loading
gpac_prefix = subprocess.check_output(['pkg-config', '--variable=prefix', 'gpac']).decode('utf-8').strip()
share_folder = gpac_prefix + '/share/gpac/python/'
sys.path.append(share_folder)
import libgpac as gpac
def load_configuration(config_file):
config = configparser.ConfigParser(inline_comment_prefixes=(';', '#'))
config.read(config_file)
src_args = {}
server_args = {}
gateway_args = {}
mode = ''
repair_args = {}
for section in config.sections():
if section == 'Source':
src_args = dict(config['Source'])
elif section == 'Server':
server_args = dict(config['Server'])
elif section == 'Gateway':
gateway_args = dict(config['Gateway'])
elif section == 'Mode':
mode = config['Mode'].get('mode', '').lower()
elif section == 'Repair':
repair_args = dict(config['Repair'])
return src_args, server_args, gateway_args, mode, repair_args
def main():
# Parse command-line arguments
if len(sys.argv) < 2:
print("Usage: python app.py <config_file>")
return
config_file = sys.argv[1]
# Load configuration from the specified file
src_args, server_args, gateway_args, mode, repair_args = load_configuration(config_file)
# Merge command-line arguments with configuration
for arg in sys.argv[2:]:
key, value = arg.split('=')
if key == "mode":
mode = value
elif key in src_args:
src_args[key] = value
elif key in server_args:
server_args[key]=value
elif key in gateway_args:
gateway_args[key] = value
else:
print("invalid option from cli: retrurning")
return
# Prepare options for libgpac
opts = ["myapp"]
opts.append("-no-block")
opts.append("-no-h2")
opts.append("-rescan-fonts")
opts.append("--chkiso")
opts.append("--minrecv=0")
#opts.append("-logs=core@debug")
#opts.append("-font-dirs=/System/Library/Fonts")
gpac.set_args(opts)
# Create session
fs = gpac.FilterSession()
# Load server or gateway filter based on mode
if mode == 'server':
# Load source filter
if 'stream_src' in src_args and src_args['stream_src'].strip(): # Check if stream_src is not empty
src_filter = src_args['stream_src']
src = fs.load_src(src_filter)
dasher = fs.load("dashin:forward=file:split_as")
manifest_src = ""
else:
src = fs.load_src("avgen")
aenc = fs.load(f"ffenc:c={src_args.get('a_enc', 'aac')}")
venc = fs.load(f"ffenc:c={src_args.get('v_enc', 'avc')}")
reframer = fs.load(f"reframer:rt=on")
dasher = fs.load("dasher:dmode=dynamic:stl:tsb=63")
manifest_src=server_args['manifest_src']
# Load destination filter for server mode
dst_filter_base = f"{server_args['protocol']}{server_args['ip_dst']}:{server_args['port_dst']}/{manifest_src}:furl={server_args['fdt_absolute_url']}:carousel={server_args['carousel']}:ifce={server_args['ifce']}:use_inband={server_args['use_inband_transport']}"
dst_filter = (dst_filter_base + (":llmode" if server_args['low_latency'] == "true" else "")
+ (f":errsim={server_args['errsim']}" if server_args.get('errsim') else ""))
dst = fs.load_dst(dst_filter)
# Setup repair servers re-using the same DASH session
if repair_args['repair'] != "no":
for server in repair_args['repair_urls'].split('\n'):
repair_filter = server + f"/{manifest_src}:ifce={server_args['ifce']}:rdirs=gmem:max_cache_segs=32"
# Use source instead of multicast server for repair
# fs.load_dst(repair_filter)
repair_args['repair_urls'] = src_args['stream_src']
gpac.set_logs(server_args["logs"])
elif mode == 'gateway':
# Load source for gateway
if repair_args['repair'] == "no":
repair_urls = ""
else:
repair_urls = ",".join(src_args['stream_src'].split('\n'))
src_sess_base = f"{gateway_args['protocol']}{gateway_args['ip_src']}:{gateway_args['port_src']}:ifce={gateway_args['ifce']}:repair={repair_args['repair']}:nbcached={gateway_args['nbcached']}"
src_sess = src_sess_base + (f"::repair_urls={repair_urls}" if repair_urls!="" else "")
src = fs.load_src(src_sess)
# load dash client
dasher_base= f"dashin:forward=file:split_as:keep_burl={gateway_args['keep_base_url']}"
dasher_string = dasher_base + (f":relative_url={gateway_args['relative_url']}" if gateway_args['keep_base_url'] == "inject" else "")
dasher= fs.load(dasher_string)
#load http server
#Romain: :max_cache_size=-{gateway_args['max_cache_size']}
dst_sess = f"{gateway_args['ip_addr']}:{gateway_args['port_addr']}/:rdirs={gateway_args['rdirs']}:reqlog='*':cors=auto:sutc={gateway_args['sutc']}:max_cache_segs={gateway_args['max_segs']}"
print(f"playback link : {gateway_args['ip_addr']}:{gateway_args['port_addr']}/{gateway_args['dst']}")
dst = fs.load_dst(dst_sess)
gpac.set_logs(gateway_args["logs"])
else:
print("Invalid mode specified in configuration file")
return
def shutdown_handler(signum, _):
if signum:
print(f"\nReceived signal {signum}, shutting down cleanly...")
fs.delete()
gpac.close()
sys.exit(0)
signal.signal(signal.SIGINT, shutdown_handler)
signal.signal(signal.SIGTERM, shutdown_handler)
signal.signal(signal.SIGHUP, shutdown_handler)
try:
# Keyboard interrupt not caught unless fs.run is wrapped in a python thread
t = threading.Thread(target=fs.run)
t.start()
t.join()
except KeyboardInterrupt:
pass
finally:
pass
shutdown_handler()
if __name__ == "__main__":
main()