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