Live video on the AT Protocol
1project(
2 'streamplace',
3 'c',
4 'cpp',
5 default_options: {
6 'cpp_std': 'c++11',
7 'default_library': 'static',
8 'auto_features': 'disabled',
9 'force_fallback_for': 'gio-2.0,gstreamer-controller-1.0,gstreamer-app-1.0,gstreamer-pbutils-1.0,glib-2.0,gobject-2.0,gio-2.0,gio-unix-2.0,fdk-aac,zlib,libffi,pcre2,intl,proxy-libintl,x264,freetype2,libpng,libjpeg,fontconfig,pango,opus,fribidi,harfbuzz,nettle,cairo,pixman,expat,openssl',
10 'buildtype': 'debugoptimized',
11 'prefix': meson.current_build_dir(), # otherwise mac meson will try and do /opt/homebrew sometimes
12 'libdir': 'lib'
13 },
14)
15
16env = {}
17if get_option('default_library') == 'static'
18 env = {
19 'PKG_CONFIG_PATH': meson.current_build_dir() + '/meson-uninstalled',
20 }
21else
22 env = {
23 'PKG_CONFIG_PATH': meson.current_build_dir() + '/lib/pkgconfig',
24 }
25endif
26
27GOOS = meson.get_external_property('GOOS', host_machine.system())
28GOARCH = meson.get_external_property('GOARCH', host_machine.cpu())
29if GOARCH == 'x86_64'
30 GOARCH = 'amd64'
31endif
32if GOARCH == 'aarch64'
33 GOARCH = 'arm64'
34endif
35if meson.is_cross_build()
36 env += {
37 'GOOS': GOOS,
38 'GOARCH': GOARCH,
39 'CGO_ENABLED': '1',
40 'CC': meson.get_compiler('c', native: false).cmd_array()[0],
41 }
42endif
43
44c2pa_go_opts = {}
45triple = meson.get_external_property('RUST_TRIPLE', '')
46if triple != ''
47 c2pa_go_opts += {'RUST_TRIPLE': triple}
48endif
49c2pa_go_proj = subproject(
50 'c2pa_go',
51 default_options: c2pa_go_opts,
52)
53c2pa_go_dep = c2pa_go_proj.get_variable('c2pa_go_dep')
54
55streamplace_deps = []
56# if host_machine.system() == 'linux'
57# mistserver_proj = subproject(
58# 'mistserver',
59# default_options: {
60# 'APPNAME': 'MistServer',glib
61# },
62# )
63# mistserver = mistserver_proj.get_variable('libmistserver_dep')
64# streamplace_deps += mistserver
65# endif
66
67x264_proj = subproject(
68 'x264',
69 default_options: {},
70)
71
72proxy_libintl_proj = subproject(
73 'proxy-libintl',
74 default_options: {},
75)
76
77ffmpeg_opts = {
78 'aac_adtstoasc_bsf': 'enabled',
79 'aac_decoder': 'enabled',
80 'aac_latm_parser': 'enabled',
81 'aac_parser': 'enabled',
82 'aformat_filter': 'enabled',
83 'aresample_filter': 'enabled',
84 'asetnsamples_filter': 'enabled',
85 'auto_features': 'enabled',
86 'concat_demuxer': 'enabled',
87 'concat_filter': 'enabled',
88 'concat_protocol': 'enabled',
89 'concatf_protocol': 'enabled',
90 'extract_extradata_bsf': 'enabled',
91 'fd_protocol': 'enabled',
92 'fifo_muxer': 'enabled',
93 'file_protocol': 'enabled',
94 'flac_decoder': 'enabled',
95 'flac_demuxer': 'enabled',
96 'flac_muxer': 'enabled',
97 'flac_parser': 'enabled',
98 'flv_demuxer': 'enabled',
99 'format_filter': 'enabled',
100 'fps_filter': 'enabled',
101 'gpl': 'enabled',
102 'h264_cuvid_decoder': 'enabled',
103 'h264_decoder': 'enabled',
104 'h264_metadata_bsf': 'enabled',
105 'h264_mp4toannexb_bsf': 'enabled',
106 'h264_parser': 'enabled',
107 'h264_redundant_pps_bsf': 'enabled',
108 'hevc_cuvid_decoder': 'enabled',
109 'hevc_mp4toannexb_bsf': 'enabled',
110 'hevc_muxer': 'enabled',
111 'hevc_parser': 'enabled',
112 'hls_muxer': 'enabled',
113 'http_protocol': 'enabled',
114 'hwdownload_filter': 'enabled',
115 'image2_demuxer': 'enabled',
116 'libxcb': 'enabled',
117 'matroska_audio_muxer': 'enabled',
118 'matroska_demuxer': 'enabled',
119 'matroska_muxer': 'enabled',
120 'mov_demuxer': 'enabled',
121 'mp3_decoder': 'enabled',
122 'mp3_demuxer': 'enabled',
123 'mp3_muxer': 'enabled',
124 'mp4_muxer': 'enabled',
125 'mpegaudio_parser': 'enabled',
126 'mpegts_demuxer': 'enabled',
127 'mpegts_muxer': 'enabled',
128 'network': 'enabled',
129 'null_muxer': 'enabled',
130 'opus_decoder': 'enabled',
131 'opus_parser': 'enabled',
132 'pipe_protocol': 'enabled',
133 'png_decoder': 'enabled',
134 'png_parser': 'enabled',
135 'rtmp_protocol': 'enabled',
136 'scale_filter': 'enabled',
137 'segment_muxer': 'enabled',
138 'stream_segment_muxer': 'enabled',
139 'select_filter': 'enabled',
140 'signature_filter': 'enabled',
141 'tcp_protocol': 'enabled',
142 'vorbis_decoder': 'enabled',
143 'vorbis_parser': 'enabled',
144 'vp8_cuvid_decoder': 'enabled',
145 'vp8_parser': 'enabled',
146 'vp9_cuvid_decoder': 'enabled',
147 'vp9_parser': 'enabled',
148 'wav_demuxer': 'enabled',
149 'wav_muxer': 'enabled',
150 'webm_muxer': 'enabled',
151 'x86asm': 'enabled',
152 'mov_muxer': 'enabled',
153 'vp9_superframe_bsf': 'enabled',
154 'ac3_parser': 'enabled',
155 'pgs_frame_merge_bsf': 'enabled',
156 'libx264': 'enabled',
157 'libx264_encoder': 'enabled',
158 'libx264rgb_encoder': 'enabled',
159 'mpegtsraw_demuxer': 'enabled',
160 'adts_muxer': 'enabled',
161 'latm_muxer': 'enabled',
162 'vvc_mp4toannexb_bsf': 'enabled',
163}
164
165if host_machine.system() != 'windows'
166 ffmpeg_opts += {'nanosleep': 'enabled'}
167endif
168
169# Someday maybe once the meson port of ffmpeg supports cuda
170
171# if host_machine.system() != 'darwin'
172# ffmpeg_opts += {
173# 'ff_cuda_llvm': 'enabled',
174# 'cuda': 'enabled',
175# 'hwupload_cuda_filter': 'enabled',
176# 'scale_cuda_filter': 'enabled',
177# # 'signature_cuda_filter': 'enabled',
178# 'ffnvcodec': 'enabled',
179# 'h264_nvenc_encoder': 'enabled',
180# 'nvenc': 'enabled',
181# 'nvdec': 'enabled',
182# 'h264_nvdec_hwaccel': 'enabled',
183# 'libdl': 'enabled',
184# }
185# endif
186
187ffmpeg_proj = subproject(
188 'FFmpeg',
189 # vvc seems to have problems building as a submodule?
190 default_options: ffmpeg_opts,
191)
192avformat = ffmpeg_proj.get_variable('libavformat_dep')
193avfilter = ffmpeg_proj.get_variable('libavfilter_dep')
194streamplace_deps += [avformat, avfilter]
195
196gstreamer_proj = subproject(
197 'gstreamer-full',
198 default_options: {},
199)
200
201streamplace_deps += [
202 dependency('gio-2.0'),
203 dependency('gstreamer-controller-1.0'),
204 dependency('gstreamer-app-1.0'),
205 dependency('gstreamer-pbutils-1.0'),
206 dependency('libffi'),
207]
208
209atproto = subproject(
210 'atproto',
211 default_options: {},
212)
213
214if get_option('default_library') == 'static'
215 gst_full_dep = gstreamer_proj.get_variable('gst_full_dep')
216 streamplace_deps += [
217 gst_full_dep,
218 dependency('gstplayback'),
219 ]
220endif
221
222subdir('rust/iroh-streamplace')
223
224if host_machine.system() == 'darwin'
225 streamplace_deps += [
226 dependency(
227 'appleframeworks',
228 modules: ['CoreFoundation', 'Security', 'SystemConfiguration'],
229 ),
230 ]
231endif
232if host_machine.system() == 'windows'
233 add_project_link_arguments(
234 [
235 '-lntdll',
236 '-luserenv',
237 '-lcrypt32',
238 '-lbcrypt',
239 '-static-libstdc++',
240 '-static-libgcc',
241 ],
242 language: ['c', 'cpp'],
243 )
244endif
245
246pkg = import('pkgconfig')
247pkg.generate(
248 name: 'streamplacedeps',
249 libraries: [streamplace_deps, c2pa_go_dep, iroh_streamplace_dep],
250 description: 'all streamplace dependencies bundled for easy inclusion',
251)
252
253# dummy executable that we use as a target to convince meson to build all the streamplace dependencies
254executable(
255 'streamplacedeps',
256 ['cmd/streamplace/empty.c'],
257 dependencies: [
258 streamplace_deps,
259 ],
260 link_with: [c2pa_go_dep, iroh_streamplace_dep],
261 install_tag: 'streamplacedeps',
262)
263
264if get_option('default_library') == 'static'
265 prog_go = find_program('go')
266
267 flagbuilder = custom_target(
268 'flagbuilder',
269 input: ['pkg/config/git/git.go'],
270 output: ['flagbuilder'],
271 command: [prog_go, 'build', '-o', '@OUTPUT0@', '@INPUT@'],
272 build_always_stale: true,
273 env: {
274 'CGO_ENABLED': '0',
275 },
276 )
277 version_cmd = run_command(prog_go, 'run', 'pkg/config/git/git.go', '-v', check: true, env: {
278 'CGO_ENABLED': '0',
279 })
280 version = version_cmd.stdout().strip()
281
282 streamplace_go = custom_target(
283 'streamplace.go',
284 input: 'cmd/libstreamplace/streamplace.go',
285 output: 'streamplace.go',
286 command: ['cp', '@INPUT@', '@OUTPUT@'],
287 )
288 flags = custom_target(
289 'flags',
290 input: [],
291 output: ['build-flags.go'],
292 command: [flagbuilder, '-o', '@OUTPUT0@'],
293 build_always_stale: true,
294 )
295
296 libstreamplace = custom_target(
297 'libstreamplace',
298 input: [streamplace_go, flags],
299 output: ['streamplace.a', 'streamplace.h'],
300 command: [
301 prog_go,
302 'build',
303 '-o', '@OUTPUT0@',
304 '-buildmode', 'c-archive',
305 '-tags', 'netgo,static',
306 '@INPUT@',
307 ],
308 build_always_stale: true,
309 env: env,
310 )
311
312 if build_machine.system() == 'linux' and host_machine.system() == 'darwin'
313 # this only exists to convince meson to build all of the streamplace dependencies
314 # the real binary comes from the `go build` command below
315 cstreamplace = executable(
316 'cstreamplace',
317 ['cmd/streamplace/streamplace.c', libstreamplace],
318 dependencies: [
319 streamplace_deps,
320 ],
321 link_with: [c2pa_go_dep, iroh_streamplace_dep],
322 )
323
324 streamplace = custom_target(
325 'streamplace',
326 input: [cstreamplace, flags],
327 output: ['streamplace'],
328 command: [
329 prog_go,
330 'build',
331 '-o', '@OUTPUT0@',
332 '-tags', 'netgo,static',
333 'streamplace.go',
334 '@INPUT1@'
335 ],
336 build_always_stale: true,
337 env: env,
338 )
339 else
340 streamplace = executable(
341 'streamplace',
342 ['cmd/streamplace/streamplace.c', libstreamplace],
343 dependencies: [
344 streamplace_deps,
345 ],
346 link_with: [c2pa_go_dep, iroh_streamplace_dep],
347 )
348 endif
349
350
351 if not meson.is_cross_build()
352 test(
353 'go-tests',
354 prog_go,
355 depends: [streamplace],
356 env: env,
357 verbose: true,
358 timeout: 0,
359 args: [
360 'test',
361 '-p', '1',
362 '-timeout', '600s',
363 '@0@/pkg/...'.format(meson.current_source_dir()),
364 '@0@/cmd/...'.format(meson.current_source_dir()),
365 ],
366 )
367 endif
368
369 if host_machine.system() == 'windows'
370 prog_zip = find_program('zip')
371 archive_name = 'streamplace-' + version + '-' + GOOS + '-' + GOARCH + '.zip'
372 custom_target(
373 'archive',
374 input: [streamplace],
375 output: ['streamplace.zip'],
376 command: [prog_zip, '../bin/' + archive_name, '@INPUT@'],
377 install: true,
378 install_dir: './bin',
379 build_by_default: false,
380 )
381 else
382 prog_tar = find_program('tar')
383 # archive_name = streamplace-$(VERSION)-$$GOOS-$$GOARCH.tar.gz
384 archive_name = 'streamplace-' + version + '-' + GOOS + '-' + GOARCH + '.tar.gz'
385 custom_target(
386 'archive',
387 input: [streamplace],
388 output: ['streamplace.tar.gz'],
389 command: [prog_tar, '-czvf', '../bin/' + archive_name, '@INPUT@'],
390 install: true,
391 install_dir: './bin',
392 build_by_default: false,
393 )
394 endif
395endif