Changes of Revision 41
obs-studio.changes
Changed
x
1
2
-------------------------------------------------------------------
3
+Tue Jan 17 23:38:37 UTC 2017 - jimmy@boombatower.com
4
+
5
+- Update to version 17.0.1:
6
+ * deps/libff: Fix VP8/VP9/webm alpha support
7
+ * rtmp-services: Increase video bitrate limit for YouTube
8
+ * obs-outputs: fix build error on freebsd
9
+ * Update translations from Crowdin
10
+ * [CI] Use prebuilt deps so we can build on 10.9
11
+ * CI: Build more features into FFMPEG deps
12
+ * CI: Update browser plugin ref and build scripts.
13
+ * CI: Fix zip permission issue on CEF plist files
14
+ * obs-x264: ignore opencl param
15
+ * enc-amf: Update to 1.4.3.8
16
+ * CI: Ability to make packages on travis
17
+ * CI: actually call packagesbuild from the right place 😑
18
+ * cmake: Remove unnecessary find_package calls
19
+ * libobs: Fix scale filtering bug when duplicating scenes
20
+ * win-capture: Don't use FindWindow for game capture keepalive
21
+ * CI: Install Packages and use the full version
22
+ * Revert "win-capture: Use FindWindowEx to traverse window list"
23
+ * obs-filters.c: Fix color correction filter OpenGL crash
24
+ * obs-filters.c: Fix color correction filter saturation
25
+ * Update translations from Crowdin
26
+ * UI: Fix bug with uncopied profile import/export files
27
+ * win-capture: Fix game capture size bug when rehooking
28
+ * libobs: Add func to enum active and inactive child tree
29
+ * libobs: Enumerate full tree when adding active child
30
+ * libobs: Add callback for enumerating all scene children
31
+ * obs-x264: Allow opencl through much longer alias
32
+ * libobs: Update to version 17.0.1
33
+
34
+-------------------------------------------------------------------
35
Mon Dec 26 08:32:58 UTC 2016 - jimmy@boombatower.com
36
37
- Update to version 0.17.0:
38
obs-studio.spec
Changed
8
1
2
Name: obs-studio
3
-Version: 0.17.0
4
+Version: 17.0.1
5
Release: 0
6
Summary: A recording/broadcasting program
7
8
_service
Changed
10
1
2
<services>
3
<service name="tar_scm" mode="disabled">
4
<param name="versionformat">@PARENT_TAG@</param>
5
- <param name="revision">refs/tags/0.17.0</param>
6
+ <param name="revision">refs/tags/17.0.1</param>
7
<param name="url">git://github.com/jp9000/obs-studio.git</param>
8
<param name="scm">git</param>
9
<param name="changesgenerate">enable</param>
10
_servicedata
Changed
9
1
2
<servicedata>
3
<service name="tar_scm">
4
<param name="url">git://github.com/jp9000/obs-studio.git</param>
5
- <param name="changesrevision">93e084088f3c1f3979d78eea3c5d9220b1cea3f7</param>
6
+ <param name="changesrevision">5f5582b87efe396812131b7a2211f1e0e5e85768</param>
7
</service>
8
</servicedata>
9
obs-studio-0.17.0.tar.xz/CI/before-deploy-osx.sh -> obs-studio-17.0.1.tar.xz/CI/before-deploy-osx.sh
Changed
15
1
2
export GIT_HASH=$(git rev-parse --short HEAD)
3
export FILE_DATE=$(date +%Y-%m-%d.%H:%M:%S)
4
-export FILENAME=$FILE_DATE-$GIT_HASH-osx.zip
5
+export FILENAME=$FILE_DATE-$GIT_HASH-osx.pkg
6
mkdir nightly
7
cd ./build
8
sudo python ../CI/install/osx/build_app.py
9
-zip -r -X $FILENAME OBS.app
10
-mv ./$FILENAME ../nightly
11
+packagesbuild ../CI/install/osx/CMakeLists.pkgproj
12
+
13
+sudo cp OBS.pkg ./$FILENAME
14
+sudo mv ./$FILENAME ../nightly
15
obs-studio-0.17.0.tar.xz/CI/before-script-osx.sh -> obs-studio-17.0.1.tar.xz/CI/before-script-osx.sh
Changed
8
1
2
mkdir build
3
cd build
4
-cmake -DBUILD_BROWSER=ON -DCEF_ROOT_DIR=$PWD/../../cef_binary_3.2704.1434.gec3e9ed_macosx64 ..
5
\ No newline at end of file
6
+cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.9 -DDepsPath=/tmp/obsdeps -DBUILD_BROWSER=ON -DCEF_ROOT_DIR=$PWD/../../cef_binary_3.2883.1540.gedbfb20_macosx64 ..
7
\ No newline at end of file
8
obs-studio-0.17.0.tar.xz/CI/install-dependencies-osx.sh -> obs-studio-17.0.1.tar.xz/CI/install-dependencies-osx.sh
Changed
30
1
2
+curl -L -O https://s3-us-west-2.amazonaws.com/obs-nightly/Packages.pkg
3
+sudo installer -pkg ./Packages.pkg -target /
4
+
5
brew update
6
7
#Base OBS Deps
8
-brew install ffmpeg x264 qt5
9
+brew install qt5
10
+
11
+curl -L -O https://s3-us-west-2.amazonaws.com/obs-nightly/osx-deps.tar.gz
12
+tar -xf ./osx-deps.tar.gz -C /tmp
13
14
# CEF Stuff
15
cd ../
16
-curl -kLO http://opensource.spotify.com/cefbuilds/cef_binary_3.2704.1434.gec3e9ed_macosx64.tar.bz2
17
-tar -xf ./cef_binary_3.2704.1434.gec3e9ed_macosx64.tar.bz2
18
-cd ./cef_binary_3.2704.1434.gec3e9ed_macosx64
19
+curl -kLO http://opensource.spotify.com/cefbuilds/cef_binary_3.2883.1540.gedbfb20_macosx64.tar.bz2
20
+tar -xf ./cef_binary_3.2883.1540.gedbfb20_macosx64.tar.bz2
21
+cd ./cef_binary_3.2883.1540.gedbfb20_macosx64
22
mkdir build
23
cd ./build
24
-cmake -DCMAKE_CXX_FLAGS="-std=c++11 -stdlib=libc++" -DCMAKE_EXE_LINKER_FLAGS="-std=c++11 -stdlib=libc++" ..
25
+cmake -DCMAKE_CXX_FLAGS="-std=c++11 -stdlib=libc++" -DCMAKE_EXE_LINKER_FLAGS="-std=c++11 -stdlib=libc++" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.9 ..
26
make -j4
27
mkdir libcef_dll
28
-mv ./libcef_dll_wrapper/libcef_dll_wrapper.a ./libcef_dll/libcef_dll_wrapper.a
29
cd ../../
30
obs-studio-17.0.1.tar.xz/CI/install/osx/CMakeLists.pkgproj
Added
1023
1
2
+<?xml version="1.0" encoding="UTF-8"?>
3
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
4
+<plist version="1.0">
5
+<dict>
6
+ <key>PACKAGES</key>
7
+ <array>
8
+ <dict>
9
+ <key>PACKAGE_FILES</key>
10
+ <dict>
11
+ <key>DEFAULT_INSTALL_LOCATION</key>
12
+ <string>/</string>
13
+ <key>HIERARCHY</key>
14
+ <dict>
15
+ <key>CHILDREN</key>
16
+ <array>
17
+ <dict>
18
+ <key>CHILDREN</key>
19
+ <array>
20
+ <dict>
21
+ <key>CHILDREN</key>
22
+ <array/>
23
+ <key>GID</key>
24
+ <integer>80</integer>
25
+ <key>PATH</key>
26
+ <string>../../../build/OBS.app</string>
27
+ <key>PATH_TYPE</key>
28
+ <integer>3</integer>
29
+ <key>PERMISSIONS</key>
30
+ <integer>493</integer>
31
+ <key>TYPE</key>
32
+ <integer>3</integer>
33
+ <key>UID</key>
34
+ <integer>0</integer>
35
+ </dict>
36
+ <dict>
37
+ <key>CHILDREN</key>
38
+ <array/>
39
+ <key>GID</key>
40
+ <integer>80</integer>
41
+ <key>PATH</key>
42
+ <string>Utilities</string>
43
+ <key>PATH_TYPE</key>
44
+ <integer>0</integer>
45
+ <key>PERMISSIONS</key>
46
+ <integer>493</integer>
47
+ <key>TYPE</key>
48
+ <integer>1</integer>
49
+ <key>UID</key>
50
+ <integer>0</integer>
51
+ </dict>
52
+ </array>
53
+ <key>GID</key>
54
+ <integer>80</integer>
55
+ <key>PATH</key>
56
+ <string>Applications</string>
57
+ <key>PATH_TYPE</key>
58
+ <integer>0</integer>
59
+ <key>PERMISSIONS</key>
60
+ <integer>509</integer>
61
+ <key>TYPE</key>
62
+ <integer>1</integer>
63
+ <key>UID</key>
64
+ <integer>0</integer>
65
+ </dict>
66
+ <dict>
67
+ <key>CHILDREN</key>
68
+ <array>
69
+ <dict>
70
+ <key>CHILDREN</key>
71
+ <array>
72
+ <dict>
73
+ <key>CHILDREN</key>
74
+ <array>
75
+ <dict>
76
+ <key>CHILDREN</key>
77
+ <array>
78
+ <dict>
79
+ <key>CHILDREN</key>
80
+ <array>
81
+ <dict>
82
+ <key>CHILDREN</key>
83
+ <array>
84
+ <dict>
85
+ <key>CHILDREN</key>
86
+ <array/>
87
+ <key>GID</key>
88
+ <integer>80</integer>
89
+ <key>PATH</key>
90
+ <string>../../../build/plugins/obs-browser/CEF.app</string>
91
+ <key>PATH_TYPE</key>
92
+ <integer>3</integer>
93
+ <key>PERMISSIONS</key>
94
+ <integer>493</integer>
95
+ <key>TYPE</key>
96
+ <integer>3</integer>
97
+ <key>UID</key>
98
+ <integer>0</integer>
99
+ </dict>
100
+ <dict>
101
+ <key>CHILDREN</key>
102
+ <array/>
103
+ <key>GID</key>
104
+ <integer>80</integer>
105
+ <key>PATH</key>
106
+ <string>../../../build/plugins/obs-browser/obs-browser.so</string>
107
+ <key>PATH_TYPE</key>
108
+ <integer>3</integer>
109
+ <key>PERMISSIONS</key>
110
+ <integer>493</integer>
111
+ <key>TYPE</key>
112
+ <integer>3</integer>
113
+ <key>UID</key>
114
+ <integer>0</integer>
115
+ </dict>
116
+ </array>
117
+ <key>GID</key>
118
+ <integer>80</integer>
119
+ <key>PATH</key>
120
+ <string>bin</string>
121
+ <key>PATH_TYPE</key>
122
+ <integer>0</integer>
123
+ <key>PERMISSIONS</key>
124
+ <integer>493</integer>
125
+ <key>TYPE</key>
126
+ <integer>2</integer>
127
+ <key>UID</key>
128
+ <integer>0</integer>
129
+ </dict>
130
+ </array>
131
+ <key>GID</key>
132
+ <integer>80</integer>
133
+ <key>PATH</key>
134
+ <string>obs-browser</string>
135
+ <key>PATH_TYPE</key>
136
+ <integer>0</integer>
137
+ <key>PERMISSIONS</key>
138
+ <integer>493</integer>
139
+ <key>TYPE</key>
140
+ <integer>2</integer>
141
+ <key>UID</key>
142
+ <integer>0</integer>
143
+ </dict>
144
+ </array>
145
+ <key>GID</key>
146
+ <integer>80</integer>
147
+ <key>PATH</key>
148
+ <string>plugins</string>
149
+ <key>PATH_TYPE</key>
150
+ <integer>0</integer>
151
+ <key>PERMISSIONS</key>
152
+ <integer>493</integer>
153
+ <key>TYPE</key>
154
+ <integer>2</integer>
155
+ <key>UID</key>
156
+ <integer>0</integer>
157
+ </dict>
158
+ </array>
159
+ <key>GID</key>
160
+ <integer>80</integer>
161
+ <key>PATH</key>
162
+ <string>obs-studio</string>
163
+ <key>PATH_TYPE</key>
164
+ <integer>0</integer>
165
+ <key>PERMISSIONS</key>
166
+ <integer>493</integer>
167
+ <key>TYPE</key>
168
+ <integer>2</integer>
169
+ <key>UID</key>
170
+ <integer>0</integer>
171
+ </dict>
172
+ </array>
173
+ <key>GID</key>
174
+ <integer>80</integer>
175
+ <key>PATH</key>
176
+ <string>Application Support</string>
177
+ <key>PATH_TYPE</key>
178
+ <integer>0</integer>
179
+ <key>PERMISSIONS</key>
180
+ <integer>493</integer>
181
+ <key>TYPE</key>
182
+ <integer>1</integer>
183
+ <key>UID</key>
184
+ <integer>0</integer>
185
+ </dict>
186
+ <dict>
187
+ <key>CHILDREN</key>
188
+ <array/>
189
+ <key>GID</key>
190
+ <integer>0</integer>
191
+ <key>PATH</key>
192
+ <string>Documentation</string>
193
+ <key>PATH_TYPE</key>
194
+ <integer>0</integer>
195
+ <key>PERMISSIONS</key>
196
+ <integer>493</integer>
197
+ <key>TYPE</key>
198
+ <integer>1</integer>
199
+ <key>UID</key>
200
+ <integer>0</integer>
201
+ </dict>
202
+ <dict>
203
+ <key>CHILDREN</key>
204
+ <array/>
205
+ <key>GID</key>
206
+ <integer>0</integer>
207
+ <key>PATH</key>
208
+ <string>Filesystems</string>
209
+ <key>PATH_TYPE</key>
210
+ <integer>0</integer>
211
+ <key>PERMISSIONS</key>
212
+ <integer>493</integer>
213
+ <key>TYPE</key>
214
+ <integer>1</integer>
215
+ <key>UID</key>
216
+ <integer>0</integer>
217
+ </dict>
218
+ <dict>
219
+ <key>CHILDREN</key>
220
+ <array/>
221
+ <key>GID</key>
222
+ <integer>0</integer>
223
+ <key>PATH</key>
224
+ <string>Frameworks</string>
225
+ <key>PATH_TYPE</key>
226
+ <integer>0</integer>
227
+ <key>PERMISSIONS</key>
228
+ <integer>493</integer>
229
+ <key>TYPE</key>
230
+ <integer>1</integer>
231
+ <key>UID</key>
232
+ <integer>0</integer>
233
+ </dict>
234
+ <dict>
235
+ <key>CHILDREN</key>
236
+ <array/>
237
+ <key>GID</key>
238
+ <integer>0</integer>
239
+ <key>PATH</key>
240
+ <string>Input Methods</string>
241
+ <key>PATH_TYPE</key>
242
+ <integer>0</integer>
243
+ <key>PERMISSIONS</key>
244
+ <integer>493</integer>
245
+ <key>TYPE</key>
246
+ <integer>1</integer>
247
+ <key>UID</key>
248
+ <integer>0</integer>
249
+ </dict>
250
+ <dict>
251
+ <key>CHILDREN</key>
252
+ <array/>
253
+ <key>GID</key>
254
+ <integer>0</integer>
255
+ <key>PATH</key>
256
+ <string>Internet Plug-Ins</string>
257
+ <key>PATH_TYPE</key>
258
+ <integer>0</integer>
259
+ <key>PERMISSIONS</key>
260
+ <integer>493</integer>
261
+ <key>TYPE</key>
262
+ <integer>1</integer>
263
+ <key>UID</key>
264
+ <integer>0</integer>
265
+ </dict>
266
+ <dict>
267
+ <key>CHILDREN</key>
268
+ <array/>
269
+ <key>GID</key>
270
+ <integer>0</integer>
271
+ <key>PATH</key>
272
+ <string>LaunchAgents</string>
273
+ <key>PATH_TYPE</key>
274
+ <integer>0</integer>
275
+ <key>PERMISSIONS</key>
276
+ <integer>493</integer>
277
+ <key>TYPE</key>
278
+ <integer>1</integer>
279
+ <key>UID</key>
280
+ <integer>0</integer>
281
+ </dict>
282
+ <dict>
283
+ <key>CHILDREN</key>
284
+ <array/>
285
+ <key>GID</key>
286
+ <integer>0</integer>
287
+ <key>PATH</key>
288
+ <string>LaunchDaemons</string>
289
+ <key>PATH_TYPE</key>
290
+ <integer>0</integer>
291
+ <key>PERMISSIONS</key>
292
+ <integer>493</integer>
293
+ <key>TYPE</key>
294
+ <integer>1</integer>
295
+ <key>UID</key>
296
+ <integer>0</integer>
297
+ </dict>
298
+ <dict>
299
+ <key>CHILDREN</key>
300
+ <array/>
301
+ <key>GID</key>
302
+ <integer>0</integer>
303
+ <key>PATH</key>
304
+ <string>PreferencePanes</string>
305
+ <key>PATH_TYPE</key>
306
+ <integer>0</integer>
307
+ <key>PERMISSIONS</key>
308
+ <integer>493</integer>
309
+ <key>TYPE</key>
310
+ <integer>1</integer>
311
+ <key>UID</key>
312
+ <integer>0</integer>
313
+ </dict>
314
+ <dict>
315
+ <key>CHILDREN</key>
316
+ <array/>
317
+ <key>GID</key>
318
+ <integer>0</integer>
319
+ <key>PATH</key>
320
+ <string>Preferences</string>
321
+ <key>PATH_TYPE</key>
322
+ <integer>0</integer>
323
+ <key>PERMISSIONS</key>
324
+ <integer>493</integer>
325
+ <key>TYPE</key>
326
+ <integer>1</integer>
327
+ <key>UID</key>
328
+ <integer>0</integer>
329
+ </dict>
330
+ <dict>
331
+ <key>CHILDREN</key>
332
+ <array/>
333
+ <key>GID</key>
334
+ <integer>80</integer>
335
+ <key>PATH</key>
336
+ <string>Printers</string>
337
+ <key>PATH_TYPE</key>
338
+ <integer>0</integer>
339
+ <key>PERMISSIONS</key>
340
+ <integer>493</integer>
341
+ <key>TYPE</key>
342
+ <integer>1</integer>
343
+ <key>UID</key>
344
+ <integer>0</integer>
345
+ </dict>
346
+ <dict>
347
+ <key>CHILDREN</key>
348
+ <array/>
349
+ <key>GID</key>
350
+ <integer>0</integer>
351
+ <key>PATH</key>
352
+ <string>PrivilegedHelperTools</string>
353
+ <key>PATH_TYPE</key>
354
+ <integer>0</integer>
355
+ <key>PERMISSIONS</key>
356
+ <integer>493</integer>
357
+ <key>TYPE</key>
358
+ <integer>1</integer>
359
+ <key>UID</key>
360
+ <integer>0</integer>
361
+ </dict>
362
+ <dict>
363
+ <key>CHILDREN</key>
364
+ <array/>
365
+ <key>GID</key>
366
+ <integer>0</integer>
367
+ <key>PATH</key>
368
+ <string>QuickLook</string>
369
+ <key>PATH_TYPE</key>
370
+ <integer>0</integer>
371
+ <key>PERMISSIONS</key>
372
+ <integer>493</integer>
373
+ <key>TYPE</key>
374
+ <integer>1</integer>
375
+ <key>UID</key>
376
+ <integer>0</integer>
377
+ </dict>
378
+ <dict>
379
+ <key>CHILDREN</key>
380
+ <array/>
381
+ <key>GID</key>
382
+ <integer>0</integer>
383
+ <key>PATH</key>
384
+ <string>QuickTime</string>
385
+ <key>PATH_TYPE</key>
386
+ <integer>0</integer>
387
+ <key>PERMISSIONS</key>
388
+ <integer>493</integer>
389
+ <key>TYPE</key>
390
+ <integer>1</integer>
391
+ <key>UID</key>
392
+ <integer>0</integer>
393
+ </dict>
394
+ <dict>
395
+ <key>CHILDREN</key>
396
+ <array/>
397
+ <key>GID</key>
398
+ <integer>0</integer>
399
+ <key>PATH</key>
400
+ <string>Screen Savers</string>
401
+ <key>PATH_TYPE</key>
402
+ <integer>0</integer>
403
+ <key>PERMISSIONS</key>
404
+ <integer>493</integer>
405
+ <key>TYPE</key>
406
+ <integer>1</integer>
407
+ <key>UID</key>
408
+ <integer>0</integer>
409
+ </dict>
410
+ <dict>
411
+ <key>CHILDREN</key>
412
+ <array/>
413
+ <key>GID</key>
414
+ <integer>0</integer>
415
+ <key>PATH</key>
416
+ <string>Scripts</string>
417
+ <key>PATH_TYPE</key>
418
+ <integer>0</integer>
419
+ <key>PERMISSIONS</key>
420
+ <integer>493</integer>
421
+ <key>TYPE</key>
422
+ <integer>1</integer>
423
+ <key>UID</key>
424
+ <integer>0</integer>
425
+ </dict>
426
+ <dict>
427
+ <key>CHILDREN</key>
428
+ <array/>
429
+ <key>GID</key>
430
+ <integer>0</integer>
431
+ <key>PATH</key>
432
+ <string>Services</string>
433
+ <key>PATH_TYPE</key>
434
+ <integer>0</integer>
435
+ <key>PERMISSIONS</key>
436
+ <integer>493</integer>
437
+ <key>TYPE</key>
438
+ <integer>1</integer>
439
+ <key>UID</key>
440
+ <integer>0</integer>
441
+ </dict>
442
+ <dict>
443
+ <key>CHILDREN</key>
444
+ <array/>
445
+ <key>GID</key>
446
+ <integer>0</integer>
447
+ <key>PATH</key>
448
+ <string>Widgets</string>
449
+ <key>PATH_TYPE</key>
450
+ <integer>0</integer>
451
+ <key>PERMISSIONS</key>
452
+ <integer>493</integer>
453
+ <key>TYPE</key>
454
+ <integer>1</integer>
455
+ <key>UID</key>
456
+ <integer>0</integer>
457
+ </dict>
458
+ </array>
459
+ <key>GID</key>
460
+ <integer>0</integer>
461
+ <key>PATH</key>
462
+ <string>Library</string>
463
+ <key>PATH_TYPE</key>
464
+ <integer>0</integer>
465
+ <key>PERMISSIONS</key>
466
+ <integer>493</integer>
467
+ <key>TYPE</key>
468
+ <integer>1</integer>
469
+ <key>UID</key>
470
+ <integer>0</integer>
471
+ </dict>
472
+ <dict>
473
+ <key>CHILDREN</key>
474
+ <array>
475
+ <dict>
476
+ <key>CHILDREN</key>
477
+ <array>
478
+ <dict>
479
+ <key>CHILDREN</key>
480
+ <array/>
481
+ <key>GID</key>
482
+ <integer>0</integer>
483
+ <key>PATH</key>
484
+ <string>Extensions</string>
485
+ <key>PATH_TYPE</key>
486
+ <integer>0</integer>
487
+ <key>PERMISSIONS</key>
488
+ <integer>493</integer>
489
+ <key>TYPE</key>
490
+ <integer>1</integer>
491
+ <key>UID</key>
492
+ <integer>0</integer>
493
+ </dict>
494
+ </array>
495
+ <key>GID</key>
496
+ <integer>0</integer>
497
+ <key>PATH</key>
498
+ <string>Library</string>
499
+ <key>PATH_TYPE</key>
500
+ <integer>0</integer>
501
+ <key>PERMISSIONS</key>
502
+ <integer>493</integer>
503
+ <key>TYPE</key>
504
+ <integer>1</integer>
505
+ <key>UID</key>
506
+ <integer>0</integer>
507
+ </dict>
508
+ </array>
509
+ <key>GID</key>
510
+ <integer>0</integer>
511
+ <key>PATH</key>
512
+ <string>System</string>
513
+ <key>PATH_TYPE</key>
514
+ <integer>0</integer>
515
+ <key>PERMISSIONS</key>
516
+ <integer>493</integer>
517
+ <key>TYPE</key>
518
+ <integer>1</integer>
519
+ <key>UID</key>
520
+ <integer>0</integer>
521
+ </dict>
522
+ <dict>
523
+ <key>CHILDREN</key>
524
+ <array>
525
+ <dict>
526
+ <key>CHILDREN</key>
527
+ <array/>
528
+ <key>GID</key>
529
+ <integer>0</integer>
530
+ <key>PATH</key>
531
+ <string>Shared</string>
532
+ <key>PATH_TYPE</key>
533
+ <integer>0</integer>
534
+ <key>PERMISSIONS</key>
535
+ <integer>1023</integer>
536
+ <key>TYPE</key>
537
+ <integer>1</integer>
538
+ <key>UID</key>
539
+ <integer>0</integer>
540
+ </dict>
541
+ </array>
542
+ <key>GID</key>
543
+ <integer>80</integer>
544
+ <key>PATH</key>
545
+ <string>Users</string>
546
+ <key>PATH_TYPE</key>
547
+ <integer>0</integer>
548
+ <key>PERMISSIONS</key>
549
+ <integer>493</integer>
550
+ <key>TYPE</key>
551
+ <integer>1</integer>
552
+ <key>UID</key>
553
+ <integer>0</integer>
554
+ </dict>
555
+ </array>
556
+ <key>GID</key>
557
+ <integer>0</integer>
558
+ <key>PATH</key>
559
+ <string>/</string>
560
+ <key>PATH_TYPE</key>
561
+ <integer>0</integer>
562
+ <key>PERMISSIONS</key>
563
+ <integer>493</integer>
564
+ <key>TYPE</key>
565
+ <integer>1</integer>
566
+ <key>UID</key>
567
+ <integer>0</integer>
568
+ </dict>
569
+ <key>PAYLOAD_TYPE</key>
570
+ <integer>0</integer>
571
+ <key>VERSION</key>
572
+ <integer>2</integer>
573
+ </dict>
574
+ <key>PACKAGE_SCRIPTS</key>
575
+ <dict>
576
+ <key>POSTINSTALL_PATH</key>
577
+ <dict/>
578
+ <key>PREINSTALL_PATH</key>
579
+ <dict/>
580
+ <key>RESOURCES</key>
581
+ <array/>
582
+ </dict>
583
+ <key>PACKAGE_SETTINGS</key>
584
+ <dict>
585
+ <key>AUTHENTICATION</key>
586
+ <integer>1</integer>
587
+ <key>CONCLUSION_ACTION</key>
588
+ <integer>0</integer>
589
+ <key>IDENTIFIER</key>
590
+ <string>org.obsproject.pkg.obs-studio</string>
591
+ <key>NAME</key>
592
+ <string>OBS</string>
593
+ <key>OVERWRITE_PERMISSIONS</key>
594
+ <false/>
595
+ <key>VERSION</key>
596
+ <string>1.0</string>
597
+ </dict>
598
+ <key>UUID</key>
599
+ <string>19CCE3F2-8911-4364-B673-8B5BC3ABD4DA</string>
600
+ </dict>
601
+ <dict>
602
+ <key>PACKAGE_SETTINGS</key>
603
+ <dict>
604
+ <key>LOCATION</key>
605
+ <integer>0</integer>
606
+ <key>NAME</key>
607
+ <string>SyphonInject</string>
608
+ </dict>
609
+ <key>PATH</key>
610
+ <dict>
611
+ <key>PATH</key>
612
+ <string>SyphonInject.pkg</string>
613
+ <key>PATH_TYPE</key>
614
+ <integer>1</integer>
615
+ </dict>
616
+ <key>TYPE</key>
617
+ <integer>1</integer>
618
+ <key>UUID</key>
619
+ <string>0CC9C67E-4D14-4794-9930-019925513B1C</string>
620
+ </dict>
621
+ </array>
622
+ <key>PROJECT</key>
623
+ <dict>
624
+ <key>PROJECT_COMMENTS</key>
625
+ <dict>
626
+ <key>NOTES</key>
627
+ <data>
628
+ PCFET0NUWVBFIGh0bWwgUFVCTElDICItLy9XM0MvL0RURCBIVE1M
629
+ IDQuMDEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvVFIvaHRtbDQv
630
+ c3RyaWN0LmR0ZCI+CjxodG1sPgo8aGVhZD4KPG1ldGEgaHR0cC1l
631
+ cXVpdj0iQ29udGVudC1UeXBlIiBjb250ZW50PSJ0ZXh0L2h0bWw7
632
+ IGNoYXJzZXQ9VVRGLTgiPgo8bWV0YSBodHRwLWVxdWl2PSJDb250
633
+ ZW50LVN0eWxlLVR5cGUiIGNvbnRlbnQ9InRleHQvY3NzIj4KPHRp
634
+ dGxlPjwvdGl0bGU+CjxtZXRhIG5hbWU9IkdlbmVyYXRvciIgY29u
635
+ dGVudD0iQ29jb2EgSFRNTCBXcml0ZXIiPgo8bWV0YSBuYW1lPSJD
636
+ b2NvYVZlcnNpb24iIGNvbnRlbnQ9IjE1MDQuNzYiPgo8c3R5bGUg
637
+ dHlwZT0idGV4dC9jc3MiPgo8L3N0eWxlPgo8L2hlYWQ+Cjxib2R5
638
+ Pgo8L2JvZHk+CjwvaHRtbD4K
639
+ </data>
640
+ </dict>
641
+ <key>PROJECT_PRESENTATION</key>
642
+ <dict>
643
+ <key>BACKGROUND</key>
644
+ <dict>
645
+ <key>ALIGNMENT</key>
646
+ <integer>4</integer>
647
+ <key>BACKGROUND_PATH</key>
648
+ <dict>
649
+ <key>PATH</key>
650
+ <string>obs.png</string>
651
+ <key>PATH_TYPE</key>
652
+ <integer>1</integer>
653
+ </dict>
654
+ <key>CUSTOM</key>
655
+ <integer>1</integer>
656
+ <key>SCALING</key>
657
+ <integer>0</integer>
658
+ </dict>
659
+ <key>INSTALLATION TYPE</key>
660
+ <dict>
661
+ <key>HIERARCHIES</key>
662
+ <dict>
663
+ <key>INSTALLER</key>
664
+ <dict>
665
+ <key>LIST</key>
666
+ <array>
667
+ <dict>
668
+ <key>DESCRIPTION</key>
669
+ <array/>
670
+ <key>OPTIONS</key>
671
+ <dict>
672
+ <key>HIDDEN</key>
673
+ <false/>
674
+ <key>STATE</key>
675
+ <integer>0</integer>
676
+ </dict>
677
+ <key>PACKAGE_UUID</key>
678
+ <string>19CCE3F2-8911-4364-B673-8B5BC3ABD4DA</string>
679
+ <key>REQUIREMENTS</key>
680
+ <array/>
681
+ <key>TITLE</key>
682
+ <array/>
683
+ <key>TOOLTIP</key>
684
+ <array/>
685
+ <key>TYPE</key>
686
+ <integer>0</integer>
687
+ <key>UUID</key>
688
+ <string>7C540711-59F4-479C-9CFD-8C4D6594992E</string>
689
+ </dict>
690
+ <dict>
691
+ <key>DESCRIPTION</key>
692
+ <array/>
693
+ <key>OPTIONS</key>
694
+ <dict>
695
+ <key>HIDDEN</key>
696
+ <false/>
697
+ <key>STATE</key>
698
+ <integer>1</integer>
699
+ </dict>
700
+ <key>PACKAGE_UUID</key>
701
+ <string>0CC9C67E-4D14-4794-9930-019925513B1C</string>
702
+ <key>REQUIREMENTS</key>
703
+ <array/>
704
+ <key>TITLE</key>
705
+ <array/>
706
+ <key>TOOLTIP</key>
707
+ <array/>
708
+ <key>TYPE</key>
709
+ <integer>0</integer>
710
+ <key>UUID</key>
711
+ <string>BBDE08F6-D7EE-47CB-881F-7F208B3A604B</string>
712
+ </dict>
713
+ </array>
714
+ <key>REMOVED</key>
715
+ <dict/>
716
+ </dict>
717
+ </dict>
718
+ <key>INSTALLATION TYPE</key>
719
+ <integer>0</integer>
720
+ <key>MODE</key>
721
+ <integer>0</integer>
722
+ </dict>
723
+ <key>INSTALLATION_STEPS</key>
724
+ <array>
725
+ <dict>
726
+ <key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
727
+ <string>ICPresentationViewIntroductionController</string>
728
+ <key>INSTALLER_PLUGIN</key>
729
+ <string>Introduction</string>
730
+ <key>LIST_TITLE_KEY</key>
731
+ <string>InstallerSectionTitle</string>
732
+ </dict>
733
+ <dict>
734
+ <key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
735
+ <string>ICPresentationViewReadMeController</string>
736
+ <key>INSTALLER_PLUGIN</key>
737
+ <string>ReadMe</string>
738
+ <key>LIST_TITLE_KEY</key>
739
+ <string>InstallerSectionTitle</string>
740
+ </dict>
741
+ <dict>
742
+ <key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
743
+ <string>ICPresentationViewLicenseController</string>
744
+ <key>INSTALLER_PLUGIN</key>
745
+ <string>License</string>
746
+ <key>LIST_TITLE_KEY</key>
747
+ <string>InstallerSectionTitle</string>
748
+ </dict>
749
+ <dict>
750
+ <key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
751
+ <string>ICPresentationViewDestinationSelectController</string>
752
+ <key>INSTALLER_PLUGIN</key>
753
+ <string>TargetSelect</string>
754
+ <key>LIST_TITLE_KEY</key>
755
+ <string>InstallerSectionTitle</string>
756
+ </dict>
757
+ <dict>
758
+ <key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
759
+ <string>ICPresentationViewInstallationTypeController</string>
760
+ <key>INSTALLER_PLUGIN</key>
761
+ <string>PackageSelection</string>
762
+ <key>LIST_TITLE_KEY</key>
763
+ <string>InstallerSectionTitle</string>
764
+ </dict>
765
+ <dict>
766
+ <key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
767
+ <string>ICPresentationViewInstallationController</string>
768
+ <key>INSTALLER_PLUGIN</key>
769
+ <string>Install</string>
770
+ <key>LIST_TITLE_KEY</key>
771
+ <string>InstallerSectionTitle</string>
772
+ </dict>
773
+ <dict>
774
+ <key>ICPRESENTATION_CHAPTER_VIEW_CONTROLLER_CLASS</key>
775
+ <string>ICPresentationViewSummaryController</string>
776
+ <key>INSTALLER_PLUGIN</key>
777
+ <string>Summary</string>
778
+ <key>LIST_TITLE_KEY</key>
779
+ <string>InstallerSectionTitle</string>
780
+ </dict>
781
+ </array>
782
+ <key>INTRODUCTION</key>
783
+ <dict>
784
+ <key>LOCALIZATIONS</key>
785
+ <array/>
786
+ </dict>
787
+ <key>LICENSE</key>
788
+ <dict>
789
+ <key>KEYWORDS</key>
790
+ <dict/>
791
+ <key>LOCALIZATIONS</key>
792
+ <array/>
793
+ <key>MODE</key>
794
+ <integer>0</integer>
795
+ </dict>
796
+ <key>README</key>
797
+ <dict>
798
+ <key>LOCALIZATIONS</key>
799
+ <array/>
800
+ </dict>
801
+ <key>SUMMARY</key>
802
+ <dict>
803
+ <key>LOCALIZATIONS</key>
804
+ <array/>
805
+ </dict>
806
+ <key>TITLE</key>
807
+ <dict>
808
+ <key>LOCALIZATIONS</key>
809
+ <array>
810
+ <dict>
811
+ <key>LANGUAGE</key>
812
+ <string>English</string>
813
+ <key>VALUE</key>
814
+ <string>OBS</string>
815
+ </dict>
816
+ </array>
817
+ </dict>
818
+ </dict>
819
+ <key>PROJECT_REQUIREMENTS</key>
820
+ <dict>
821
+ <key>LIST</key>
822
+ <array/>
823
+ <key>POSTINSTALL_PATH</key>
824
+ <dict/>
825
+ <key>PREINSTALL_PATH</key>
826
+ <dict/>
827
+ <key>RESOURCES</key>
828
+ <array/>
829
+ <key>ROOT_VOLUME_ONLY</key>
830
+ <false/>
831
+ </dict>
832
+ <key>PROJECT_SETTINGS</key>
833
+ <dict>
834
+ <key>ADVANCED_OPTIONS</key>
835
+ <dict/>
836
+ <key>BUILD_FORMAT</key>
837
+ <integer>0</integer>
838
+ <key>BUILD_PATH</key>
839
+ <dict>
840
+ <key>PATH</key>
841
+ <string>../../../build</string>
842
+ <key>PATH_TYPE</key>
843
+ <integer>3</integer>
844
+ </dict>
845
+ <key>EXCLUDED_FILES</key>
846
+ <array>
847
+ <dict>
848
+ <key>PATTERNS_ARRAY</key>
849
+ <array>
850
+ <dict>
851
+ <key>REGULAR_EXPRESSION</key>
852
+ <false/>
853
+ <key>STRING</key>
854
+ <string>.DS_Store</string>
855
+ <key>TYPE</key>
856
+ <integer>0</integer>
857
+ </dict>
858
+ </array>
859
+ <key>PROTECTED</key>
860
+ <true/>
861
+ <key>PROXY_NAME</key>
862
+ <string>Remove .DS_Store files</string>
863
+ <key>PROXY_TOOLTIP</key>
864
+ <string>Remove ".DS_Store" files created by the Finder.</string>
865
+ <key>STATE</key>
866
+ <true/>
867
+ </dict>
868
+ <dict>
869
+ <key>PATTERNS_ARRAY</key>
870
+ <array>
871
+ <dict>
872
+ <key>REGULAR_EXPRESSION</key>
873
+ <false/>
874
+ <key>STRING</key>
875
+ <string>.pbdevelopment</string>
876
+ <key>TYPE</key>
877
+ <integer>0</integer>
878
+ </dict>
879
+ </array>
880
+ <key>PROTECTED</key>
881
+ <true/>
882
+ <key>PROXY_NAME</key>
883
+ <string>Remove .pbdevelopment files</string>
884
+ <key>PROXY_TOOLTIP</key>
885
+ <string>Remove ".pbdevelopment" files created by ProjectBuilder or Xcode.</string>
886
+ <key>STATE</key>
887
+ <true/>
888
+ </dict>
889
+ <dict>
890
+ <key>PATTERNS_ARRAY</key>
891
+ <array>
892
+ <dict>
893
+ <key>REGULAR_EXPRESSION</key>
894
+ <false/>
895
+ <key>STRING</key>
896
+ <string>CVS</string>
897
+ <key>TYPE</key>
898
+ <integer>1</integer>
899
+ </dict>
900
+ <dict>
901
+ <key>REGULAR_EXPRESSION</key>
902
+ <false/>
903
+ <key>STRING</key>
904
+ <string>.cvsignore</string>
905
+ <key>TYPE</key>
906
+ <integer>0</integer>
907
+ </dict>
908
+ <dict>
909
+ <key>REGULAR_EXPRESSION</key>
910
+ <false/>
911
+ <key>STRING</key>
912
+ <string>.cvspass</string>
913
+ <key>TYPE</key>
914
+ <integer>0</integer>
915
+ </dict>
916
+ <dict>
917
+ <key>REGULAR_EXPRESSION</key>
918
+ <false/>
919
+ <key>STRING</key>
920
+ <string>.svn</string>
921
+ <key>TYPE</key>
922
+ <integer>1</integer>
923
+ </dict>
924
+ <dict>
925
+ <key>REGULAR_EXPRESSION</key>
926
+ <false/>
927
+ <key>STRING</key>
928
+ <string>.git</string>
929
+ <key>TYPE</key>
930
+ <integer>1</integer>
931
+ </dict>
932
+ <dict>
933
+ <key>REGULAR_EXPRESSION</key>
934
+ <false/>
935
+ <key>STRING</key>
936
+ <string>.gitignore</string>
937
+ <key>TYPE</key>
938
+ <integer>0</integer>
939
+ </dict>
940
+ </array>
941
+ <key>PROTECTED</key>
942
+ <true/>
943
+ <key>PROXY_NAME</key>
944
+ <string>Remove SCM metadata</string>
945
+ <key>PROXY_TOOLTIP</key>
946
+ <string>Remove helper files and folders used by the CVS, SVN or Git Source Code Management systems.</string>
947
+ <key>STATE</key>
948
+ <true/>
949
+ </dict>
950
+ <dict>
951
+ <key>PATTERNS_ARRAY</key>
952
+ <array>
953
+ <dict>
954
+ <key>REGULAR_EXPRESSION</key>
955
+ <false/>
956
+ <key>STRING</key>
957
+ <string>classes.nib</string>
958
+ <key>TYPE</key>
959
+ <integer>0</integer>
960
+ </dict>
961
+ <dict>
962
+ <key>REGULAR_EXPRESSION</key>
963
+ <false/>
964
+ <key>STRING</key>
965
+ <string>designable.db</string>
966
+ <key>TYPE</key>
967
+ <integer>0</integer>
968
+ </dict>
969
+ <dict>
970
+ <key>REGULAR_EXPRESSION</key>
971
+ <false/>
972
+ <key>STRING</key>
973
+ <string>info.nib</string>
974
+ <key>TYPE</key>
975
+ <integer>0</integer>
976
+ </dict>
977
+ </array>
978
+ <key>PROTECTED</key>
979
+ <true/>
980
+ <key>PROXY_NAME</key>
981
+ <string>Optimize nib files</string>
982
+ <key>PROXY_TOOLTIP</key>
983
+ <string>Remove "classes.nib", "info.nib" and "designable.nib" files within .nib bundles.</string>
984
+ <key>STATE</key>
985
+ <true/>
986
+ </dict>
987
+ <dict>
988
+ <key>PATTERNS_ARRAY</key>
989
+ <array>
990
+ <dict>
991
+ <key>REGULAR_EXPRESSION</key>
992
+ <false/>
993
+ <key>STRING</key>
994
+ <string>Resources Disabled</string>
995
+ <key>TYPE</key>
996
+ <integer>1</integer>
997
+ </dict>
998
+ </array>
999
+ <key>PROTECTED</key>
1000
+ <true/>
1001
+ <key>PROXY_NAME</key>
1002
+ <string>Remove Resources Disabled folders</string>
1003
+ <key>PROXY_TOOLTIP</key>
1004
+ <string>Remove "Resources Disabled" folders.</string>
1005
+ <key>STATE</key>
1006
+ <true/>
1007
+ </dict>
1008
+ <dict>
1009
+ <key>SEPARATOR</key>
1010
+ <true/>
1011
+ </dict>
1012
+ </array>
1013
+ <key>NAME</key>
1014
+ <string>OBS</string>
1015
+ </dict>
1016
+ </dict>
1017
+ <key>TYPE</key>
1018
+ <integer>0</integer>
1019
+ <key>VERSION</key>
1020
+ <integer>2</integer>
1021
+</dict>
1022
+</plist>
1023
obs-studio-17.0.1.tar.xz/CI/install/osx/OBSPublicDSAKey.pem
Added
38
1
2
+-----BEGIN PUBLIC KEY-----
3
+MIIGSDCCBDoGByqGSM44BAEwggQtAoICAQDDTtoCl3zVYY4jq2ZvJhY+jZB23BdR
4
+k+oTQH0lIUuIBjJR+S8NZqylr4SIGF2S76sCDdpK5P7Waj1y5WyBIJQDCPA7UI1T
5
+P8UeZgxLazl+oVPnDhUeiEWCNkZIcn746/pPgdoG5KNjb6CUNQ8X+zkUzq6LJ7w9
6
+Sn02g1FPf0HUlR0D9bx8KweetAZrBGYNP2Mv0RvUSE3TS+t1zJadOp7GsMcoRBxD
7
+XnJXirBiTjGu3pUZ5bJSLEw+Jm46DdEj0f+SSMpPjgRAG3Pn8ac7U+CVonGHEIRB
8
+4+yjHTqF9aPtsABIbAeSh63U54yYcmYuF/ioxTNjXXsNGNm5ZAeGq1/o0iT2eesu
9
+nC6yUYggWSBVZEdTD4uI9iYsYnpjbp+fAUoD53MxTRgKqdOESdtZTJ0HSUqTjngH
10
+kwzpvxN7WmCpxISzAjs5bknu90DcdP2R4KrJfiJJzAMFp0hmwuy4OaUX0+BWZzvW
11
+KxCbHsvJL2asHkX4kQpoGVnYmEglH0vOLuK3iJi96jDcGBDGGPO0OXgu6P00iALT
12
+JF1KylJNnyH0K1a7EbS1QJlF50+zW+okc5Da1iy4vktTP7gPxBHZWeFHPMRZOp1H
13
+CZeP6Lipf9NpE5dqzMuHLFmxWeKn/7CQ2T9LyeTIajbeGqRsoSII3qEgQd/nDM3k
14
+NYt6e7dKx6rk6QIhAJ8/wlS8dyJEnvMwVRqn5ER05q7NuHocmGGiX2V/ONLnAoIC
15
+AQCTFu8RESwHSQ4uR3O0CjlvQKwqEM3Vlv+nyEqYvfqJNAfxrncpV0TF05GvUV7M
16
+e31solt3eK31qjK1H3AMaD8ToCinSYMLaoyMt0AfGljGK5cNZKXn/xFVM4mq71id
17
+RzrIfmL2327+kH7wC/8sk7R3FB/mxPV1fRhKuBqG+Y6x9NX7vz57JnIio20OQKCE
18
+Sn7a18QWHgmt+e+n9R6x7JiVOj+ZTwuPPXpomNB6nPVnQftf3lwB7ug1wJyBxAqy
19
+NkIhzkAk4RDn4NzhP70ULD80GdS36swCIOg08uTSsYA6FMgrD6JLpmKC4Uha8vPM
20
+421qxX8Si/Dk3r4one6NUr2WD0sy754MKOCZ5aD8XUB2ylLzfvdSEaGo+G/IyPtC
21
+o71PMnIStEPXH6GkvzxJv17zvhqQcyKBciqxR7GCQhbwMimp96EPIA3/2UDXQ9UE
22
+O+/JulJKVEuu4HhWLW8+s+qKhyTyP1dRd0qzLoLj81JA3FcotB1Lncas8mtv+eET
23
+Z1tKuDy8f4esOh0fuGNrDiMnm3y+cnsa41k4XLDLPrqGbJHxiRTlGwCMLxLEMcFa
24
+0gjYU3UFFiEvNG0vFWr4h57taLBoyKoyBON+Cmn5hsrKs1J1kTBTc1EvDF5mXjoX
25
+RhlrPxd/6b5aa12d3xIYofcp70RyPBM1AZ7jfWeSgKhN6AOCAgYAAoICAQClbOeZ
26
+cnCCsOaZyXp7aiZmDmJ4dtvCRXc+uD+VzRHlg/8X3BYQ01KUMc5/m+fFT7x8w12w
27
+FEN/txOxTB+NzQBlnRFHWjBOioxHWqAnYLuADP4nZM+1bwaMUBCRUX0MHZbaMMSR
28
+/dBa45Y9quc4JTV8rpfIzXdw1NZjDmnKYwKQxQ6eD/WymJFNpWKkaniMda0HQVCU
29
+eBEEpLjW4UE1YUFQgKuIKUdZ1eBxeXHgX6uDpU53reK8gC5ry8xZXryJlcqhKyQ8
30
+TrDarZgmxhzAvAwPbtCutiOpPaVpCQCdgi4PgA3sAgmdGENXDqTxcSCbCcmCYMzl
31
+pJLh+giO74OwZMqWvHwHPY5wgZbx9Tnw4JS+gsjl3K3XUeY1+J6cgrFCK/9iaRUx
32
+7lBroEgQoi+O+yM9ikPeGZYKwgobWslmNuMdYvbZl+hQF+eo7dgnABl+WHLkHogv
33
+O0wfbENlYECAHXJ/ncyRWoiyd3d/HrZBwMfMFv0hv9JdQ1EjVePXGh9+cDxO0W+Y
34
+ZJhXsXEmQ82+Pg9cCVywLKdbNWi4qPgwYEKKagq4ack6JHCcwbLMmNTz/PaDZpfP
35
+wCCxYzVxKksGnV2tb2quAW1/GB+H9FcPSHvE1MMsPhRwAGAm4+aKuL1IvrvLh8fj
36
+0tZk6dhMjtrBOkZMfnBbSKDKQlcHvXM25yIjgA==
37
+-----END PUBLIC KEY-----
38
obs-studio-17.0.1.tar.xz/CI/install/osx/SyphonInject.pkg
Added
obs-studio-17.0.1.tar.xz/CI/install/osx/obs.png
Added
705
1
2
+
3
+
4
+
5
+
6
+<!DOCTYPE html>
7
+<html lang="en" class=" emoji-size-boost is-u2f-enabled">
8
+ <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# object: http://ogp.me/ns/object# article: http://ogp.me/ns/article# profile: http://ogp.me/ns/profile#">
9
+ <meta charset='utf-8'>
10
+
11
+
12
+ <link crossorigin="anonymous" href="https://assets-cdn.github.com/assets/frameworks-c9ae4d373fcb2c40952201451cd449e00d6dbcedc778b79c9dfb2d076d04993b.css" integrity="sha256-ya5NNz/LLECVIgFFHNRJ4A1tvO3HeLecnfstB20EmTs=" media="all" rel="stylesheet" />
13
+ <link crossorigin="anonymous" href="https://assets-cdn.github.com/assets/github-4d14493830801ffc6d6d6363f3fcef8a6e41fd9e74776dce15fa2c18b2a9bb72.css" integrity="sha256-TRRJODCAH/xtbWNj8/zvim5B/Z50d23OFfosGLKpu3I=" media="all" rel="stylesheet" />
14
+
15
+
16
+
17
+
18
+
19
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
20
+ <meta http-equiv="Content-Language" content="en">
21
+ <meta name="viewport" content="width=device-width">
22
+
23
+ <title>obs-studio-utils/obs.png at master · kc5nra/obs-studio-utils</title>
24
+ <link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub">
25
+ <link rel="fluid-icon" href="https://github.com/fluidicon.png" title="GitHub">
26
+ <link rel="apple-touch-icon" href="/apple-touch-icon.png">
27
+ <link rel="apple-touch-icon" sizes="57x57" href="/apple-touch-icon-57x57.png">
28
+ <link rel="apple-touch-icon" sizes="60x60" href="/apple-touch-icon-60x60.png">
29
+ <link rel="apple-touch-icon" sizes="72x72" href="/apple-touch-icon-72x72.png">
30
+ <link rel="apple-touch-icon" sizes="76x76" href="/apple-touch-icon-76x76.png">
31
+ <link rel="apple-touch-icon" sizes="114x114" href="/apple-touch-icon-114x114.png">
32
+ <link rel="apple-touch-icon" sizes="120x120" href="/apple-touch-icon-120x120.png">
33
+ <link rel="apple-touch-icon" sizes="144x144" href="/apple-touch-icon-144x144.png">
34
+ <link rel="apple-touch-icon" sizes="152x152" href="/apple-touch-icon-152x152.png">
35
+ <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon-180x180.png">
36
+ <meta property="fb:app_id" content="1401488693436528">
37
+
38
+ <meta content="https://avatars0.githubusercontent.com/u/231018?v=3&s=400" name="twitter:image:src" /><meta content="@github" name="twitter:site" /><meta content="summary" name="twitter:card" /><meta content="kc5nra/obs-studio-utils" name="twitter:title" /><meta content="Contribute to obs-studio-utils development by creating an account on GitHub." name="twitter:description" />
39
+ <meta content="https://avatars0.githubusercontent.com/u/231018?v=3&s=400" property="og:image" /><meta content="GitHub" property="og:site_name" /><meta content="object" property="og:type" /><meta content="kc5nra/obs-studio-utils" property="og:title" /><meta content="https://github.com/kc5nra/obs-studio-utils" property="og:url" /><meta content="Contribute to obs-studio-utils development by creating an account on GitHub." property="og:description" />
40
+ <meta name="browser-stats-url" content="https://api.github.com/_private/browser/stats">
41
+ <meta name="browser-errors-url" content="https://api.github.com/_private/browser/errors">
42
+ <link rel="assets" href="https://assets-cdn.github.com/">
43
+ <link rel="web-socket" href="wss://live.github.com/_sockets/VjI6NTA0OTIxMTc6ZDJjMjcyYzA1MjZiMGM4MGI5MmU2NzBkMTMyMWNiYWZhMjZiZGQ0MGQxOGY1MWNkYmI1NzA0NjhlZTdjM2E2OA==--561fd74d4042c982502dd897714172236351f238">
44
+ <meta name="pjax-timeout" content="1000">
45
+ <link rel="sudo-modal" href="/sessions/sudo_modal">
46
+ <meta name="request-id" content="683BCFFA:2DABC:EE980D1:587831B3" data-pjax-transient>
47
+
48
+ <meta name="msapplication-TileImage" content="/windows-tile.png">
49
+ <meta name="msapplication-TileColor" content="#ffffff">
50
+ <meta name="selected-link" value="repo_source" data-pjax-transient>
51
+
52
+ <meta name="google-site-verification" content="KT5gs8h0wvaagLKAVWq8bbeNwnZZK1r1XQysX3xurLU">
53
+<meta name="google-site-verification" content="ZzhVyEFwb7w3e0-uOTltm8Jsck2F5StVihD0exw2fsA">
54
+ <meta name="google-analytics" content="UA-3769691-2">
55
+
56
+<meta content="collector.githubapp.com" name="octolytics-host" /><meta content="github" name="octolytics-app-id" /><meta content="683BCFFA:2DABC:EE980D1:587831B3" name="octolytics-dimension-request_id" /><meta content="207897" name="octolytics-actor-id" /><meta content="DDRBoxman" name="octolytics-actor-login" /><meta content="951d1462a992f6b4236b5008d6b11c4331eba4c658fe50ec7c9882e14af522bd" name="octolytics-actor-hash" />
57
+<meta content="/<user-name>/<repo-name>/blob/show" data-pjax-transient="true" name="analytics-location" />
58
+
59
+
60
+
61
+ <meta class="js-ga-set" name="dimension1" content="Logged In">
62
+
63
+
64
+
65
+ <meta name="hostname" content="github.com">
66
+ <meta name="user-login" content="DDRBoxman">
67
+
68
+ <meta name="expected-hostname" content="github.com">
69
+ <meta name="js-proxy-site-detection-payload" content="ZDQzNzZjM2MwNTlmYWFjNzhmNWJlMzY0MzNkMjdiOThhM2U2OTI0ZjlmMzFlYzJmODdjYjMxNDQ5OTBkNjc4NXx7InJlbW90ZV9hZGRyZXNzIjoiMTA0LjU5LjIwNy4yNTAiLCJyZXF1ZXN0X2lkIjoiNjgzQkNGRkE6MkRBQkM6RUU5ODBEMTo1ODc4MzFCMyIsInRpbWVzdGFtcCI6MTQ4NDI3MjA1NiwiaG9zdCI6ImdpdGh1Yi5jb20ifQ==">
70
+
71
+
72
+ <link rel="mask-icon" href="https://assets-cdn.github.com/pinned-octocat.svg" color="#000000">
73
+ <link rel="icon" type="image/x-icon" href="https://assets-cdn.github.com/favicon.ico">
74
+
75
+ <meta name="html-safe-nonce" content="0a420a0a7ff0cff8568da5f27c46880ec53370cf">
76
+
77
+ <meta http-equiv="x-pjax-version" content="f36bd54ef0fdb145d68369e21555ea6f">
78
+
79
+
80
+
81
+ <meta name="description" content="Contribute to obs-studio-utils development by creating an account on GitHub.">
82
+ <meta name="go-import" content="github.com/kc5nra/obs-studio-utils git https://github.com/kc5nra/obs-studio-utils.git">
83
+
84
+ <meta content="231018" name="octolytics-dimension-user_id" /><meta content="kc5nra" name="octolytics-dimension-user_login" /><meta content="24656398" name="octolytics-dimension-repository_id" /><meta content="kc5nra/obs-studio-utils" name="octolytics-dimension-repository_nwo" /><meta content="true" name="octolytics-dimension-repository_public" /><meta content="false" name="octolytics-dimension-repository_is_fork" /><meta content="24656398" name="octolytics-dimension-repository_network_root_id" /><meta content="kc5nra/obs-studio-utils" name="octolytics-dimension-repository_network_root_nwo" />
85
+ <link href="https://github.com/kc5nra/obs-studio-utils/commits/master.atom" rel="alternate" title="Recent Commits to obs-studio-utils:master" type="application/atom+xml">
86
+
87
+
88
+ <link rel="canonical" href="https://github.com/kc5nra/obs-studio-utils/blob/master/install/osx/obs.png" data-pjax-transient>
89
+ </head>
90
+
91
+
92
+ <body class="logged-in env-production macintosh vis-public page-blob">
93
+ <div id="js-pjax-loader-bar" class="pjax-loader-bar"><div class="progress"></div></div>
94
+ <a href="#start-of-content" tabindex="1" class="accessibility-aid js-skip-to-content">Skip to content</a>
95
+
96
+
97
+
98
+
99
+
100
+
101
+
102
+ <div class="header header-logged-in true" role="banner">
103
+ <div class="container clearfix">
104
+
105
+ <a class="header-logo-invertocat" href="https://github.com/" data-hotkey="g d" aria-label="Homepage" data-ga-click="Header, go to dashboard, icon:logo">
106
+ <svg aria-hidden="true" class="octicon octicon-mark-github" height="28" version="1.1" viewBox="0 0 16 16" width="28"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"/></svg>
107
+</a>
108
+
109
+
110
+ <div class="header-search scoped-search site-scoped-search js-site-search" role="search">
111
+ <!-- '"` --><!-- </textarea></xmp> --></option></form><form accept-charset="UTF-8" action="/kc5nra/obs-studio-utils/search" class="js-site-search-form" data-scoped-search-url="/kc5nra/obs-studio-utils/search" data-unscoped-search-url="/search" method="get"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /></div>
112
+ <label class="form-control header-search-wrapper js-chromeless-input-container">
113
+ <div class="header-search-scope">This repository</div>
114
+ <input type="text"
115
+ class="form-control header-search-input js-site-search-focus js-site-search-field is-clearable"
116
+ data-hotkey="s"
117
+ name="q"
118
+ placeholder="Search"
119
+ aria-label="Search this repository"
120
+ data-unscoped-placeholder="Search GitHub"
121
+ data-scoped-placeholder="Search"
122
+ autocapitalize="off">
123
+ </label>
124
+</form></div>
125
+
126
+
127
+ <ul class="header-nav float-left" role="navigation">
128
+ <li class="header-nav-item">
129
+ <a href="/pulls" aria-label="Pull requests you created" class="js-selected-navigation-item header-nav-link" data-ga-click="Header, click, Nav menu - item:pulls context:user" data-hotkey="g p" data-selected-links="/pulls /pulls/assigned /pulls/mentioned /pulls">
130
+ Pull requests
131
+</a> </li>
132
+ <li class="header-nav-item">
133
+ <a href="/issues" aria-label="Issues you created" class="js-selected-navigation-item header-nav-link" data-ga-click="Header, click, Nav menu - item:issues context:user" data-hotkey="g i" data-selected-links="/issues /issues/assigned /issues/mentioned /issues">
134
+ Issues
135
+</a> </li>
136
+ <li class="header-nav-item">
137
+ <a class="header-nav-link" href="https://gist.github.com/" data-ga-click="Header, go to gist, text:gist">Gist</a>
138
+ </li>
139
+ </ul>
140
+
141
+
142
+<ul class="header-nav user-nav float-right" id="user-links">
143
+ <li class="header-nav-item">
144
+
145
+ <a href="/notifications" aria-label="You have no unread notifications" class="header-nav-link notification-indicator tooltipped tooltipped-s js-socket-channel js-notification-indicator" data-channel="tenant:1:notification-changed:207897" data-ga-click="Header, go to notifications, icon:read" data-hotkey="g n">
146
+ <span class="mail-status "></span>
147
+ <svg aria-hidden="true" class="octicon octicon-bell" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path fill-rule="evenodd" d="M14 12v1H0v-1l.73-.58c.77-.77.81-2.55 1.19-4.42C2.69 3.23 6 2 6 2c0-.55.45-1 1-1s1 .45 1 1c0 0 3.39 1.23 4.16 5 .38 1.88.42 3.66 1.19 4.42l.66.58H14zm-7 4c1.11 0 2-.89 2-2H5c0 1.11.89 2 2 2z"/></svg>
148
+</a>
149
+ </li>
150
+
151
+ <li class="header-nav-item dropdown js-menu-container">
152
+ <a class="header-nav-link tooltipped tooltipped-s js-menu-target" href="/new"
153
+ aria-label="Create new…"
154
+ data-ga-click="Header, create new, icon:add">
155
+ <svg aria-hidden="true" class="octicon octicon-plus float-left" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M12 9H7v5H5V9H0V7h5V2h2v5h5z"/></svg>
156
+ <span class="dropdown-caret"></span>
157
+ </a>
158
+
159
+ <div class="dropdown-menu-content js-menu-content">
160
+ <ul class="dropdown-menu dropdown-menu-sw">
161
+
162
+<a class="dropdown-item" href="/new" data-ga-click="Header, create new repository">
163
+ New repository
164
+</a>
165
+
166
+ <a class="dropdown-item" href="/new/import" data-ga-click="Header, import a repository">
167
+ Import repository
168
+ </a>
169
+
170
+<a class="dropdown-item" href="https://gist.github.com/" data-ga-click="Header, create new gist">
171
+ New gist
172
+</a>
173
+
174
+ <a class="dropdown-item" href="/organizations/new" data-ga-click="Header, create new organization">
175
+ New organization
176
+ </a>
177
+
178
+
179
+
180
+ <div class="dropdown-divider"></div>
181
+ <div class="dropdown-header">
182
+ <span title="kc5nra/obs-studio-utils">This repository</span>
183
+ </div>
184
+ <a class="dropdown-item" href="/kc5nra/obs-studio-utils/issues/new" data-ga-click="Header, create new issue">
185
+ New issue
186
+ </a>
187
+
188
+ </ul>
189
+ </div>
190
+ </li>
191
+
192
+ <li class="header-nav-item dropdown js-menu-container">
193
+ <a class="header-nav-link name tooltipped tooltipped-sw js-menu-target" href="/DDRBoxman"
194
+ aria-label="View profile and more"
195
+ data-ga-click="Header, show menu, icon:avatar">
196
+ <img alt="@DDRBoxman" class="avatar" height="20" src="https://avatars3.githubusercontent.com/u/207897?v=3&s=40" width="20" />
197
+ <span class="dropdown-caret"></span>
198
+ </a>
199
+
200
+ <div class="dropdown-menu-content js-menu-content">
201
+ <div class="dropdown-menu dropdown-menu-sw">
202
+ <div class="dropdown-header header-nav-current-user css-truncate">
203
+ Signed in as <strong class="css-truncate-target">DDRBoxman</strong>
204
+ </div>
205
+
206
+ <div class="dropdown-divider"></div>
207
+
208
+ <a class="dropdown-item" href="/DDRBoxman" data-ga-click="Header, go to profile, text:your profile">
209
+ Your profile
210
+ </a>
211
+ <a class="dropdown-item" href="/DDRBoxman?tab=stars" data-ga-click="Header, go to starred repos, text:your stars">
212
+ Your stars
213
+ </a>
214
+ <a class="dropdown-item" href="/explore" data-ga-click="Header, go to explore, text:explore">
215
+ Explore
216
+ </a>
217
+ <a class="dropdown-item" href="/integrations" data-ga-click="Header, go to integrations, text:integrations">
218
+ Integrations
219
+ </a>
220
+ <a class="dropdown-item" href="https://help.github.com" data-ga-click="Header, go to help, text:help">
221
+ Help
222
+ </a>
223
+
224
+ <div class="dropdown-divider"></div>
225
+
226
+ <a class="dropdown-item" href="/settings/profile" data-ga-click="Header, go to settings, icon:settings">
227
+ Settings
228
+ </a>
229
+
230
+ <!-- '"` --><!-- </textarea></xmp> --></option></form><form accept-charset="UTF-8" action="/logout" class="logout-form" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /><input name="authenticity_token" type="hidden" value="mbjQPqcKKO6Yuqt3Dvczikt53JctIh6E47+gkXyZ3vFinTikSLP4X/o4pVzB6UDZReamEALdVHKN3UNUxVdRFQ==" /></div>
231
+ <button type="submit" class="dropdown-item dropdown-signout" data-ga-click="Header, sign out, icon:logout">
232
+ Sign out
233
+ </button>
234
+</form> </div>
235
+ </div>
236
+ </li>
237
+</ul>
238
+
239
+
240
+
241
+ </div>
242
+</div>
243
+
244
+
245
+
246
+
247
+
248
+ <div id="start-of-content" class="accessibility-aid"></div>
249
+
250
+ <div id="js-flash-container">
251
+</div>
252
+
253
+
254
+ <div role="main">
255
+ <div itemscope itemtype="http://schema.org/SoftwareSourceCode">
256
+ <div id="js-repo-pjax-container" data-pjax-container>
257
+
258
+<div class="pagehead repohead instapaper_ignore readability-menu experiment-repo-nav">
259
+ <div class="container repohead-details-container">
260
+
261
+
262
+
263
+<ul class="pagehead-actions">
264
+
265
+ <li>
266
+ <!-- '"` --><!-- </textarea></xmp> --></option></form><form accept-charset="UTF-8" action="/notifications/subscribe" class="js-social-container" data-autosubmit="true" data-remote="true" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /><input name="authenticity_token" type="hidden" value="7woW5zqjJpvg5IbCp+Gf47Op+jJvsrXFlv5u5Cwuwg3CsPTT6eYZ7inxEYqPhx9rxluEnL+P7mYdgOYTMzC6HQ==" /></div> <input class="form-control" id="repository_id" name="repository_id" type="hidden" value="24656398" />
267
+
268
+ <div class="select-menu js-menu-container js-select-menu">
269
+ <a href="/kc5nra/obs-studio-utils/subscription"
270
+ class="btn btn-sm btn-with-count select-menu-button js-menu-target" role="button" tabindex="0" aria-haspopup="true"
271
+ data-ga-click="Repository, click Watch settings, action:blob#show">
272
+ <span class="js-select-button">
273
+ <svg aria-hidden="true" class="octicon octicon-eye" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M8.06 2C3 2 0 8 0 8s3 6 8.06 6C13 14 16 8 16 8s-3-6-7.94-6zM8 12c-2.2 0-4-1.78-4-4 0-2.2 1.8-4 4-4 2.22 0 4 1.8 4 4 0 2.22-1.78 4-4 4zm2-4c0 1.11-.89 2-2 2-1.11 0-2-.89-2-2 0-1.11.89-2 2-2 1.11 0 2 .89 2 2z"/></svg>
274
+ Watch
275
+ </span>
276
+ </a>
277
+ <a class="social-count js-social-count"
278
+ href="/kc5nra/obs-studio-utils/watchers"
279
+ aria-label="6 users are watching this repository">
280
+ 6
281
+ </a>
282
+
283
+ <div class="select-menu-modal-holder">
284
+ <div class="select-menu-modal subscription-menu-modal js-menu-content" aria-hidden="true">
285
+ <div class="select-menu-header js-navigation-enable" tabindex="-1">
286
+ <svg aria-label="Close" class="octicon octicon-x js-menu-close" height="16" role="img" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"/></svg>
287
+ <span class="select-menu-title">Notifications</span>
288
+ </div>
289
+
290
+ <div class="select-menu-list js-navigation-container" role="menu">
291
+
292
+ <div class="select-menu-item js-navigation-item selected" role="menuitem" tabindex="0">
293
+ <svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"/></svg>
294
+ <div class="select-menu-item-text">
295
+ <input checked="checked" id="do_included" name="do" type="radio" value="included" />
296
+ <span class="select-menu-item-heading">Not watching</span>
297
+ <span class="description">Be notified when participating or @mentioned.</span>
298
+ <span class="js-select-button-text hidden-select-button-text">
299
+ <svg aria-hidden="true" class="octicon octicon-eye" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M8.06 2C3 2 0 8 0 8s3 6 8.06 6C13 14 16 8 16 8s-3-6-7.94-6zM8 12c-2.2 0-4-1.78-4-4 0-2.2 1.8-4 4-4 2.22 0 4 1.8 4 4 0 2.22-1.78 4-4 4zm2-4c0 1.11-.89 2-2 2-1.11 0-2-.89-2-2 0-1.11.89-2 2-2 1.11 0 2 .89 2 2z"/></svg>
300
+ Watch
301
+ </span>
302
+ </div>
303
+ </div>
304
+
305
+ <div class="select-menu-item js-navigation-item " role="menuitem" tabindex="0">
306
+ <svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"/></svg>
307
+ <div class="select-menu-item-text">
308
+ <input id="do_subscribed" name="do" type="radio" value="subscribed" />
309
+ <span class="select-menu-item-heading">Watching</span>
310
+ <span class="description">Be notified of all conversations.</span>
311
+ <span class="js-select-button-text hidden-select-button-text">
312
+ <svg aria-hidden="true" class="octicon octicon-eye" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M8.06 2C3 2 0 8 0 8s3 6 8.06 6C13 14 16 8 16 8s-3-6-7.94-6zM8 12c-2.2 0-4-1.78-4-4 0-2.2 1.8-4 4-4 2.22 0 4 1.8 4 4 0 2.22-1.78 4-4 4zm2-4c0 1.11-.89 2-2 2-1.11 0-2-.89-2-2 0-1.11.89-2 2-2 1.11 0 2 .89 2 2z"/></svg>
313
+ Unwatch
314
+ </span>
315
+ </div>
316
+ </div>
317
+
318
+ <div class="select-menu-item js-navigation-item " role="menuitem" tabindex="0">
319
+ <svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"/></svg>
320
+ <div class="select-menu-item-text">
321
+ <input id="do_ignore" name="do" type="radio" value="ignore" />
322
+ <span class="select-menu-item-heading">Ignoring</span>
323
+ <span class="description">Never be notified.</span>
324
+ <span class="js-select-button-text hidden-select-button-text">
325
+ <svg aria-hidden="true" class="octicon octicon-mute" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M8 2.81v10.38c0 .67-.81 1-1.28.53L3 10H1c-.55 0-1-.45-1-1V7c0-.55.45-1 1-1h2l3.72-3.72C7.19 1.81 8 2.14 8 2.81zm7.53 3.22l-1.06-1.06-1.97 1.97-1.97-1.97-1.06 1.06L11.44 8 9.47 9.97l1.06 1.06 1.97-1.97 1.97 1.97 1.06-1.06L13.56 8l1.97-1.97z"/></svg>
326
+ Stop ignoring
327
+ </span>
328
+ </div>
329
+ </div>
330
+
331
+ </div>
332
+
333
+ </div>
334
+ </div>
335
+ </div>
336
+</form>
337
+ </li>
338
+
339
+ <li>
340
+ <div class="js-toggler-container js-social-container starring-container ">
341
+ <!-- '"` --><!-- </textarea></xmp> --></option></form><form accept-charset="UTF-8" action="/kc5nra/obs-studio-utils/unstar" class="starred" data-remote="true" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /><input name="authenticity_token" type="hidden" value="uNPwxvmyPhwAsjUibCbKxZPg+6FNyS0wqv8HPlluJPjUflJmxafLWYbN3BQrvfH8Lc0ZHtLc/rWvAedO7AIezw==" /></div>
342
+ <button
343
+ type="submit"
344
+ class="btn btn-sm btn-with-count js-toggler-target"
345
+ aria-label="Unstar this repository" title="Unstar kc5nra/obs-studio-utils"
346
+ data-ga-click="Repository, click unstar button, action:blob#show; text:Unstar">
347
+ <svg aria-hidden="true" class="octicon octicon-star" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path fill-rule="evenodd" d="M14 6l-4.9-.64L7 1 4.9 5.36 0 6l3.6 3.26L2.67 14 7 11.67 11.33 14l-.93-4.74z"/></svg>
348
+ Unstar
349
+ </button>
350
+ <a class="social-count js-social-count" href="/kc5nra/obs-studio-utils/stargazers"
351
+ aria-label="8 users starred this repository">
352
+ 8
353
+ </a>
354
+</form>
355
+ <!-- '"` --><!-- </textarea></xmp> --></option></form><form accept-charset="UTF-8" action="/kc5nra/obs-studio-utils/star" class="unstarred" data-remote="true" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /><input name="authenticity_token" type="hidden" value="/sSbA/aj/l81g7HuzKrbvT/fZClJWTOY1T6jjNOGbTpB0vtZBytYMlHPt25VUZnhDcnvUHq56bYpHx4cSnYfgA==" /></div>
356
+ <button
357
+ type="submit"
358
+ class="btn btn-sm btn-with-count js-toggler-target"
359
+ aria-label="Star this repository" title="Star kc5nra/obs-studio-utils"
360
+ data-ga-click="Repository, click star button, action:blob#show; text:Star">
361
+ <svg aria-hidden="true" class="octicon octicon-star" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path fill-rule="evenodd" d="M14 6l-4.9-.64L7 1 4.9 5.36 0 6l3.6 3.26L2.67 14 7 11.67 11.33 14l-.93-4.74z"/></svg>
362
+ Star
363
+ </button>
364
+ <a class="social-count js-social-count" href="/kc5nra/obs-studio-utils/stargazers"
365
+ aria-label="8 users starred this repository">
366
+ 8
367
+ </a>
368
+</form> </div>
369
+
370
+ </li>
371
+
372
+ <li>
373
+ <a href="#fork-destination-box" class="btn btn-sm btn-with-count"
374
+ title="Fork your own copy of kc5nra/obs-studio-utils to your account"
375
+ aria-label="Fork your own copy of kc5nra/obs-studio-utils to your account"
376
+ rel="facebox"
377
+ data-ga-click="Repository, show fork modal, action:blob#show; text:Fork">
378
+ <svg aria-hidden="true" class="octicon octicon-repo-forked" height="16" version="1.1" viewBox="0 0 10 16" width="10"><path fill-rule="evenodd" d="M8 1a1.993 1.993 0 0 0-1 3.72V6L5 8 3 6V4.72A1.993 1.993 0 0 0 2 1a1.993 1.993 0 0 0-1 3.72V6.5l3 3v1.78A1.993 1.993 0 0 0 5 15a1.993 1.993 0 0 0 1-3.72V9.5l3-3V4.72A1.993 1.993 0 0 0 8 1zM2 4.2C1.34 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zm3 10c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zm3-10c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"/></svg>
379
+ Fork
380
+ </a>
381
+
382
+ <div id="fork-destination-box" style="display: none;">
383
+ <h2 class="facebox-header" data-facebox-id="facebox-header">Where should we fork this repository?</h2>
384
+ <include-fragment src=""
385
+ class="js-fork-select-fragment fork-select-fragment"
386
+ data-url="/kc5nra/obs-studio-utils/fork?fragment=1">
387
+ <img alt="Loading" height="64" src="https://assets-cdn.github.com/images/spinners/octocat-spinner-128.gif" width="64" />
388
+ </include-fragment>
389
+ </div>
390
+
391
+ <a href="/kc5nra/obs-studio-utils/network" class="social-count"
392
+ aria-label="4 users forked this repository">
393
+ 4
394
+ </a>
395
+ </li>
396
+</ul>
397
+
398
+ <h1 class="public ">
399
+ <svg aria-hidden="true" class="octicon octicon-repo" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M4 9H3V8h1v1zm0-3H3v1h1V6zm0-2H3v1h1V4zm0-2H3v1h1V2zm8-1v12c0 .55-.45 1-1 1H6v2l-1.5-1.5L3 16v-2H1c-.55 0-1-.45-1-1V1c0-.55.45-1 1-1h10c.55 0 1 .45 1 1zm-1 10H1v2h2v-1h3v1h5v-2zm0-10H2v9h9V1z"/></svg>
400
+ <span class="author" itemprop="author"><a href="/kc5nra" class="url fn" rel="author">kc5nra</a></span><!--
401
+--><span class="path-divider">/</span><!--
402
+--><strong itemprop="name"><a href="/kc5nra/obs-studio-utils" data-pjax="#js-repo-pjax-container">obs-studio-utils</a></strong>
403
+
404
+</h1>
405
+
406
+ </div>
407
+ <div class="container">
408
+
409
+<nav class="reponav js-repo-nav js-sidenav-container-pjax"
410
+ itemscope
411
+ itemtype="http://schema.org/BreadcrumbList"
412
+ role="navigation"
413
+ data-pjax="#js-repo-pjax-container">
414
+
415
+ <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement">
416
+ <a href="/kc5nra/obs-studio-utils" class="js-selected-navigation-item selected reponav-item" data-hotkey="g c" data-selected-links="repo_source repo_downloads repo_commits repo_releases repo_tags repo_branches /kc5nra/obs-studio-utils" itemprop="url">
417
+ <svg aria-hidden="true" class="octicon octicon-code" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path fill-rule="evenodd" d="M9.5 3L8 4.5 11.5 8 8 11.5 9.5 13 14 8 9.5 3zm-5 0L0 8l4.5 5L6 11.5 2.5 8 6 4.5 4.5 3z"/></svg>
418
+ <span itemprop="name">Code</span>
419
+ <meta itemprop="position" content="1">
420
+</a> </span>
421
+
422
+ <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement">
423
+ <a href="/kc5nra/obs-studio-utils/issues" class="js-selected-navigation-item reponav-item" data-hotkey="g i" data-selected-links="repo_issues repo_labels repo_milestones /kc5nra/obs-studio-utils/issues" itemprop="url">
424
+ <svg aria-hidden="true" class="octicon octicon-issue-opened" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"/></svg>
425
+ <span itemprop="name">Issues</span>
426
+ <span class="counter">1</span>
427
+ <meta itemprop="position" content="2">
428
+</a> </span>
429
+
430
+ <span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement">
431
+ <a href="/kc5nra/obs-studio-utils/pulls" class="js-selected-navigation-item reponav-item" data-hotkey="g p" data-selected-links="repo_pulls /kc5nra/obs-studio-utils/pulls" itemprop="url">
432
+ <svg aria-hidden="true" class="octicon octicon-git-pull-request" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M11 11.28V5c-.03-.78-.34-1.47-.94-2.06C9.46 2.35 8.78 2.03 8 2H7V0L4 3l3 3V4h1c.27.02.48.11.69.31.21.2.3.42.31.69v6.28A1.993 1.993 0 0 0 10 15a1.993 1.993 0 0 0 1-3.72zm-1 2.92c-.66 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2zM4 3c0-1.11-.89-2-2-2a1.993 1.993 0 0 0-1 3.72v6.56A1.993 1.993 0 0 0 2 15a1.993 1.993 0 0 0 1-3.72V4.72c.59-.34 1-.98 1-1.72zm-.8 10c0 .66-.55 1.2-1.2 1.2-.65 0-1.2-.55-1.2-1.2 0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2zM2 4.2C1.34 4.2.8 3.65.8 3c0-.65.55-1.2 1.2-1.2.65 0 1.2.55 1.2 1.2 0 .65-.55 1.2-1.2 1.2z"/></svg>
433
+ <span itemprop="name">Pull requests</span>
434
+ <span class="counter">0</span>
435
+ <meta itemprop="position" content="3">
436
+</a> </span>
437
+
438
+ <a href="/kc5nra/obs-studio-utils/projects" class="js-selected-navigation-item reponav-item" data-selected-links="repo_projects new_repo_project repo_project /kc5nra/obs-studio-utils/projects">
439
+ <svg aria-hidden="true" class="octicon octicon-project" height="16" version="1.1" viewBox="0 0 15 16" width="15"><path fill-rule="evenodd" d="M10 12h3V2h-3v10zm-4-2h3V2H6v8zm-4 4h3V2H2v12zm-1 1h13V1H1v14zM14 0H1a1 1 0 0 0-1 1v14a1 1 0 0 0 1 1h13a1 1 0 0 0 1-1V1a1 1 0 0 0-1-1z"/></svg>
440
+ Projects
441
+ <span class="counter">0</span>
442
+</a>
443
+ <a href="/kc5nra/obs-studio-utils/wiki" class="js-selected-navigation-item reponav-item" data-hotkey="g w" data-selected-links="repo_wiki /kc5nra/obs-studio-utils/wiki">
444
+ <svg aria-hidden="true" class="octicon octicon-book" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M3 5h4v1H3V5zm0 3h4V7H3v1zm0 2h4V9H3v1zm11-5h-4v1h4V5zm0 2h-4v1h4V7zm0 2h-4v1h4V9zm2-6v9c0 .55-.45 1-1 1H9.5l-1 1-1-1H2c-.55 0-1-.45-1-1V3c0-.55.45-1 1-1h5.5l1 1 1-1H15c.55 0 1 .45 1 1zm-8 .5L7.5 3H2v9h6V3.5zm7-.5H9.5l-.5.5V12h6V3z"/></svg>
445
+ Wiki
446
+</a>
447
+
448
+ <a href="/kc5nra/obs-studio-utils/pulse" class="js-selected-navigation-item reponav-item" data-selected-links="pulse /kc5nra/obs-studio-utils/pulse">
449
+ <svg aria-hidden="true" class="octicon octicon-pulse" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path fill-rule="evenodd" d="M11.5 8L8.8 5.4 6.6 8.5 5.5 1.6 2.38 8H0v2h3.6l.9-1.8.9 5.4L9 8.5l1.6 1.5H14V8z"/></svg>
450
+ Pulse
451
+</a>
452
+ <a href="/kc5nra/obs-studio-utils/graphs" class="js-selected-navigation-item reponav-item" data-selected-links="repo_graphs repo_contributors /kc5nra/obs-studio-utils/graphs">
453
+ <svg aria-hidden="true" class="octicon octicon-graph" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M16 14v1H0V0h1v14h15zM5 13H3V8h2v5zm4 0H7V3h2v10zm4 0h-2V6h2v7z"/></svg>
454
+ Graphs
455
+</a>
456
+
457
+</nav>
458
+
459
+ </div>
460
+</div>
461
+
462
+<div class="container new-discussion-timeline experiment-repo-nav">
463
+ <div class="repository-content">
464
+
465
+
466
+
467
+<a href="/kc5nra/obs-studio-utils/blob/b3ffed1c23a254e44d3dcdd2af3f9b13f63d7939/install/osx/obs.png" class="d-none js-permalink-shortcut" data-hotkey="y">Permalink</a>
468
+
469
+<!-- blob contrib key: blob_contributors:v21:6c7ce207313616b1dc79697595d24fe7 -->
470
+
471
+<div class="file-navigation js-zeroclipboard-container">
472
+
473
+<div class="select-menu branch-select-menu js-menu-container js-select-menu float-left">
474
+ <button class="btn btn-sm select-menu-button js-menu-target css-truncate" data-hotkey="w"
475
+
476
+ type="button" aria-label="Switch branches or tags" tabindex="0" aria-haspopup="true">
477
+ <i>Branch:</i>
478
+ <span class="js-select-button css-truncate-target">master</span>
479
+ </button>
480
+
481
+ <div class="select-menu-modal-holder js-menu-content js-navigation-container" data-pjax aria-hidden="true">
482
+
483
+ <div class="select-menu-modal">
484
+ <div class="select-menu-header">
485
+ <svg aria-label="Close" class="octicon octicon-x js-menu-close" height="16" role="img" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"/></svg>
486
+ <span class="select-menu-title">Switch branches/tags</span>
487
+ </div>
488
+
489
+ <div class="select-menu-filters">
490
+ <div class="select-menu-text-filter">
491
+ <input type="text" aria-label="Filter branches/tags" id="context-commitish-filter-field" class="form-control js-filterable-field js-navigation-enable" placeholder="Filter branches/tags">
492
+ </div>
493
+ <div class="select-menu-tabs">
494
+ <ul>
495
+ <li class="select-menu-tab">
496
+ <a href="#" data-tab-filter="branches" data-filter-placeholder="Filter branches/tags" class="js-select-menu-tab" role="tab">Branches</a>
497
+ </li>
498
+ <li class="select-menu-tab">
499
+ <a href="#" data-tab-filter="tags" data-filter-placeholder="Find a tag…" class="js-select-menu-tab" role="tab">Tags</a>
500
+ </li>
501
+ </ul>
502
+ </div>
503
+ </div>
504
+
505
+ <div class="select-menu-list select-menu-tab-bucket js-select-menu-tab-bucket" data-tab-filter="branches" role="menu">
506
+
507
+ <div data-filterable-for="context-commitish-filter-field" data-filterable-type="substring">
508
+
509
+
510
+ <a class="select-menu-item js-navigation-item js-navigation-open selected"
511
+ href="/kc5nra/obs-studio-utils/blob/master/install/osx/obs.png"
512
+ data-name="master"
513
+ data-skip-pjax="true"
514
+ rel="nofollow">
515
+ <svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M12 5l-8 8-4-4 1.5-1.5L4 10l6.5-6.5z"/></svg>
516
+ <span class="select-menu-item-text css-truncate-target js-select-menu-filter-text">
517
+ master
518
+ </span>
519
+ </a>
520
+ </div>
521
+
522
+ <div class="select-menu-no-results">Nothing to show</div>
523
+ </div>
524
+
525
+ <div class="select-menu-list select-menu-tab-bucket js-select-menu-tab-bucket" data-tab-filter="tags">
526
+ <div data-filterable-for="context-commitish-filter-field" data-filterable-type="substring">
527
+
528
+
529
+ </div>
530
+
531
+ <div class="select-menu-no-results">Nothing to show</div>
532
+ </div>
533
+
534
+ </div>
535
+ </div>
536
+</div>
537
+
538
+ <div class="BtnGroup float-right">
539
+ <a href="/kc5nra/obs-studio-utils/find/master"
540
+ class="js-pjax-capture-input btn btn-sm BtnGroup-item"
541
+ data-pjax
542
+ data-hotkey="t">
543
+ Find file
544
+ </a>
545
+ <button aria-label="Copy file path to clipboard" class="js-zeroclipboard btn btn-sm BtnGroup-item tooltipped tooltipped-s" data-copied-hint="Copied!" type="button">Copy path</button>
546
+ </div>
547
+ <div class="breadcrumb js-zeroclipboard-target">
548
+ <span class="repo-root js-repo-root"><span class="js-path-segment"><a href="/kc5nra/obs-studio-utils"><span>obs-studio-utils</span></a></span></span><span class="separator">/</span><span class="js-path-segment"><a href="/kc5nra/obs-studio-utils/tree/master/install"><span>install</span></a></span><span class="separator">/</span><span class="js-path-segment"><a href="/kc5nra/obs-studio-utils/tree/master/install/osx"><span>osx</span></a></span><span class="separator">/</span><strong class="final-path">obs.png</strong>
549
+ </div>
550
+</div>
551
+
552
+
553
+ <div class="commit-tease">
554
+ <span class="float-right">
555
+ <a class="commit-tease-sha" href="/kc5nra/obs-studio-utils/commit/b83a806a64ffd96f547029d64ed28aad49e20d5b" data-pjax>
556
+ b83a806
557
+ </a>
558
+ <relative-time datetime="2014-10-01T22:46:15Z">Oct 1, 2014</relative-time>
559
+ </span>
560
+ <div>
561
+ <img alt="@kc5nra" class="avatar" height="20" src="https://avatars3.githubusercontent.com/u/231018?v=3&s=40" width="20" />
562
+ <a href="/kc5nra" class="user-mention" rel="author">kc5nra</a>
563
+ <a href="/kc5nra/obs-studio-utils/commit/b83a806a64ffd96f547029d64ed28aad49e20d5b" class="message" data-pjax="true" title="Png more transparent, obs bundle id and img loc">Png more transparent, obs bundle id and img loc</a>
564
+ </div>
565
+
566
+ <div class="commit-tease-contributors">
567
+ <button type="button" class="btn-link muted-link contributors-toggle" data-facebox="#blob_contributors_box">
568
+ <strong>1</strong>
569
+ contributor
570
+ </button>
571
+
572
+ </div>
573
+
574
+ <div id="blob_contributors_box" style="display:none">
575
+ <h2 class="facebox-header" data-facebox-id="facebox-header">Users who have contributed to this file</h2>
576
+ <ul class="facebox-user-list" data-facebox-id="facebox-description">
577
+ <li class="facebox-user-list-item">
578
+ <img alt="@kc5nra" height="24" src="https://avatars1.githubusercontent.com/u/231018?v=3&s=48" width="24" />
579
+ <a href="/kc5nra">kc5nra</a>
580
+ </li>
581
+ </ul>
582
+ </div>
583
+ </div>
584
+
585
+
586
+<div class="file">
587
+ <div class="file-header">
588
+ <div class="file-actions">
589
+
590
+ <div class="BtnGroup">
591
+ <a href="/kc5nra/obs-studio-utils/raw/master/install/osx/obs.png" class="btn btn-sm BtnGroup-item" id="raw-url">Download</a>
592
+ <a href="/kc5nra/obs-studio-utils/commits/master/install/osx/obs.png" class="btn btn-sm BtnGroup-item" rel="nofollow">History</a>
593
+ </div>
594
+
595
+ <a class="btn-octicon tooltipped tooltipped-nw"
596
+ href="github-mac://openRepo/https://github.com/kc5nra/obs-studio-utils?branch=master&filepath=install%2Fosx%2Fobs.png"
597
+ aria-label="Open this file in GitHub Desktop"
598
+ data-ga-click="Repository, open with desktop, type:mac">
599
+ <svg aria-hidden="true" class="octicon octicon-device-desktop" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M15 2H1c-.55 0-1 .45-1 1v9c0 .55.45 1 1 1h5.34c-.25.61-.86 1.39-2.34 2h8c-1.48-.61-2.09-1.39-2.34-2H15c.55 0 1-.45 1-1V3c0-.55-.45-1-1-1zm0 9H1V3h14v8z"/></svg>
600
+ </a>
601
+
602
+ <!-- '"` --><!-- </textarea></xmp> --></option></form><form accept-charset="UTF-8" action="/kc5nra/obs-studio-utils/delete/master/install/osx/obs.png" class="inline-form" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /><input name="authenticity_token" type="hidden" value="uGzTDUGxcZBqCvnvwWvHWxzog35RyhtwqPCf9WmjMskKj0JcMzGgzzfI9Vg2tnJjAjFGp9psbMbIg54+M9+7/A==" /></div>
603
+ <button class="btn-octicon btn-octicon-danger tooltipped tooltipped-nw" type="submit"
604
+ aria-label="Delete the file in your fork of this project" data-disable-with>
605
+ <svg aria-hidden="true" class="octicon octicon-trashcan" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M11 2H9c0-.55-.45-1-1-1H5c-.55 0-1 .45-1 1H2c-.55 0-1 .45-1 1v1c0 .55.45 1 1 1v9c0 .55.45 1 1 1h7c.55 0 1-.45 1-1V5c.55 0 1-.45 1-1V3c0-.55-.45-1-1-1zm-1 12H3V5h1v8h1V5h1v8h1V5h1v8h1V5h1v9zm1-10H2V3h9v1z"/></svg>
606
+ </button>
607
+</form> </div>
608
+
609
+ <div class="file-info">
610
+ 52.8 KB
611
+ </div>
612
+</div>
613
+
614
+
615
+
616
+ <div itemprop="text" class="blob-wrapper data type-text">
617
+ <div class="image">
618
+ <span class="border-wrap"><img src="/kc5nra/obs-studio-utils/blob/master/install/osx/obs.png?raw=true" alt="obs.png"></span>
619
+ </div>
620
+ </div>
621
+
622
+</div>
623
+
624
+<button type="button" data-facebox="#jump-to-line" data-facebox-class="linejump" data-hotkey="l" class="d-none">Jump to Line</button>
625
+<div id="jump-to-line" style="display:none">
626
+ <!-- '"` --><!-- </textarea></xmp> --></option></form><form accept-charset="UTF-8" action="" class="js-jump-to-line-form" method="get"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /></div>
627
+ <input class="form-control linejump-input js-jump-to-line-field" type="text" placeholder="Jump to line…" aria-label="Jump to line" autofocus>
628
+ <button type="submit" class="btn">Go</button>
629
+</form></div>
630
+
631
+ </div>
632
+ <div class="modal-backdrop js-touch-events"></div>
633
+</div>
634
+
635
+
636
+ </div>
637
+ </div>
638
+
639
+ </div>
640
+
641
+ <div class="container site-footer-container">
642
+ <div class="site-footer" role="contentinfo">
643
+ <ul class="site-footer-links float-right">
644
+ <li><a href="https://github.com/contact" data-ga-click="Footer, go to contact, text:contact">Contact GitHub</a></li>
645
+ <li><a href="https://developer.github.com" data-ga-click="Footer, go to api, text:api">API</a></li>
646
+ <li><a href="https://training.github.com" data-ga-click="Footer, go to training, text:training">Training</a></li>
647
+ <li><a href="https://shop.github.com" data-ga-click="Footer, go to shop, text:shop">Shop</a></li>
648
+ <li><a href="https://github.com/blog" data-ga-click="Footer, go to blog, text:blog">Blog</a></li>
649
+ <li><a href="https://github.com/about" data-ga-click="Footer, go to about, text:about">About</a></li>
650
+
651
+ </ul>
652
+
653
+ <a href="https://github.com" aria-label="Homepage" class="site-footer-mark" title="GitHub">
654
+ <svg aria-hidden="true" class="octicon octicon-mark-github" height="24" version="1.1" viewBox="0 0 16 16" width="24"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"/></svg>
655
+</a>
656
+ <ul class="site-footer-links">
657
+ <li>© 2017 <span title="0.13223s from github-fe143-cp1-prd.iad.github.net">GitHub</span>, Inc.</li>
658
+ <li><a href="https://github.com/site/terms" data-ga-click="Footer, go to terms, text:terms">Terms</a></li>
659
+ <li><a href="https://github.com/site/privacy" data-ga-click="Footer, go to privacy, text:privacy">Privacy</a></li>
660
+ <li><a href="https://github.com/security" data-ga-click="Footer, go to security, text:security">Security</a></li>
661
+ <li><a href="https://status.github.com/" data-ga-click="Footer, go to status, text:status">Status</a></li>
662
+ <li><a href="https://help.github.com" data-ga-click="Footer, go to help, text:help">Help</a></li>
663
+ </ul>
664
+ </div>
665
+</div>
666
+
667
+
668
+
669
+
670
+
671
+ <div id="ajax-error-message" class="ajax-error-message flash flash-error">
672
+ <svg aria-hidden="true" class="octicon octicon-alert" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M8.865 1.52c-.18-.31-.51-.5-.87-.5s-.69.19-.87.5L.275 13.5c-.18.31-.18.69 0 1 .19.31.52.5.87.5h13.7c.36 0 .69-.19.86-.5.17-.31.18-.69.01-1L8.865 1.52zM8.995 13h-2v-2h2v2zm0-3h-2V6h2v4z"/></svg>
673
+ <button type="button" class="flash-close js-flash-close js-ajax-error-dismiss" aria-label="Dismiss error">
674
+ <svg aria-hidden="true" class="octicon octicon-x" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"/></svg>
675
+ </button>
676
+ You can't perform that action at this time.
677
+ </div>
678
+
679
+
680
+
681
+ <script crossorigin="anonymous" integrity="sha256-uzmufYSNQNbwHmc1XigpZPVPo5E3wOzJ/E7Dfn1GlQg=" src="https://assets-cdn.github.com/assets/frameworks-bb39ae7d848d40d6f01e67355e282964f54fa39137c0ecc9fc4ec37e7d469508.js"></script>
682
+ <script async="async" crossorigin="anonymous" integrity="sha256-/48DIbQkaCd8FbKJGEm8s5jOpo2/L4j5LZ+RY+umtSU=" src="https://assets-cdn.github.com/assets/github-ff8f0321b42468277c15b2891849bcb398cea68dbf2f88f92d9f9163eba6b525.js"></script>
683
+
684
+
685
+
686
+
687
+ <div class="js-stale-session-flash stale-session-flash flash flash-warn flash-banner d-none">
688
+ <svg aria-hidden="true" class="octicon octicon-alert" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M8.865 1.52c-.18-.31-.51-.5-.87-.5s-.69.19-.87.5L.275 13.5c-.18.31-.18.69 0 1 .19.31.52.5.87.5h13.7c.36 0 .69-.19.86-.5.17-.31.18-.69.01-1L8.865 1.52zM8.995 13h-2v-2h2v2zm0-3h-2V6h2v4z"/></svg>
689
+ <span class="signed-in-tab-flash">You signed in with another tab or window. <a href="">Reload</a> to refresh your session.</span>
690
+ <span class="signed-out-tab-flash">You signed out in another tab or window. <a href="">Reload</a> to refresh your session.</span>
691
+ </div>
692
+ <div class="facebox" id="facebox" style="display:none;">
693
+ <div class="facebox-popup">
694
+ <div class="facebox-content" role="dialog" aria-labelledby="facebox-header" aria-describedby="facebox-description">
695
+ </div>
696
+ <button type="button" class="facebox-close js-facebox-close" aria-label="Close modal">
697
+ <svg aria-hidden="true" class="octicon octicon-x" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path fill-rule="evenodd" d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48z"/></svg>
698
+ </button>
699
+ </div>
700
+</div>
701
+
702
+ </body>
703
+</html>
704
+
705
obs-studio-17.0.1.tar.xz/CI/install/osx/package_util.py
Added
96
1
2
+def cmd(cmd):
3
+ import subprocess
4
+ import shlex
5
+ return subprocess.check_output(shlex.split(cmd)).rstrip('\r\n')
6
+
7
+def get_tag_info(tag):
8
+ rev = cmd('git rev-parse {0}'.format(latest_tag))
9
+ anno = cmd('git cat-file -p {0}'.format(rev))
10
+ tag_info = []
11
+ for i, v in enumerate(anno.splitlines()):
12
+ if i <= 4:
13
+ continue
14
+ tag_info.append(v.lstrip())
15
+
16
+ return tag_info
17
+
18
+def gen_html(github_user, latest_tag):
19
+
20
+ url = 'https://github.com/{0}/obs-studio/commit/%H'.format(github_user)
21
+
22
+ with open('readme.html', 'w') as f:
23
+ f.write("<html><body>")
24
+ log_cmd = """git log {0}...HEAD --pretty=format:'<li>• <a href="{1}">(view)</a> %s</li>'"""
25
+ log_res = cmd(log_cmd.format(latest_tag, url))
26
+ if len(log_res.splitlines()):
27
+ f.write('<p>Changes since {0}: (Newest to oldest)</p>'.format(latest_tag))
28
+ f.write(log_res)
29
+
30
+ ul = False
31
+ f.write('<p>')
32
+ import re
33
+
34
+ for l in get_tag_info(latest_tag):
35
+ if not len(l):
36
+ continue
37
+ if l.startswith('*'):
38
+ ul = True
39
+ if not ul:
40
+ f.write('<ul>')
41
+ f.write('<li>• {0}</li>'.format(re.sub(r'^(\s*)?[*](\s*)?', '', l)))
42
+ else:
43
+ if ul:
44
+ f.write('</ul><p/>')
45
+ ul = False
46
+ f.write('<p>{0}</p>'.format(l))
47
+ if ul:
48
+ f.write('</ul>')
49
+ f.write('</p></body></html>')
50
+
51
+ cmd('textutil -convert rtf readme.html -output readme.rtf')
52
+ cmd("""sed -i '' 's/Times-Roman/Verdana/g' readme.rtf""")
53
+
54
+def save_manifest(latest_tag, user, jenkins_build, branch, stable):
55
+ log = cmd('git log --pretty=oneline {0}...HEAD'.format(latest_tag))
56
+ manifest = {}
57
+ manifest['commits'] = []
58
+ for v in log.splitlines():
59
+ manifest['commits'].append(v)
60
+ manifest['tag'] = {
61
+ 'name': latest_tag,
62
+ 'description': get_tag_info(latest_tag)
63
+ }
64
+
65
+ manifest['version'] = cmd('git rev-list HEAD --count')
66
+ manifest['sha1'] = cmd('git rev-parse HEAD')
67
+ manifest['jenkins_build'] = jenkins_build
68
+
69
+ manifest['user'] = user
70
+ manifest['branch'] = branch
71
+ manifest['stable'] = stable
72
+
73
+ import cPickle
74
+ with open('manifest', 'w') as f:
75
+ cPickle.dump(manifest, f)
76
+
77
+def prepare_pkg(project, package_id):
78
+ cmd('packagesutil --file "{0}" set package-1 identifier {1}'.format(project, package_id))
79
+ cmd('packagesutil --file "{0}" set package-1 version {1}'.format(project, '1.0'))
80
+
81
+
82
+import argparse
83
+parser = argparse.ArgumentParser(description='obs-studio package util')
84
+parser.add_argument('-u', '--user', dest='user', default='jp9000')
85
+parser.add_argument('-p', '--package-id', dest='package_id', default='org.obsproject.pkg.obs-studio')
86
+parser.add_argument('-f', '--project-file', dest='project', default='OBS.pkgproj')
87
+parser.add_argument('-j', '--jenkins-build', dest='jenkins_build', default='0')
88
+parser.add_argument('-b', '--branch', dest='branch', default='master')
89
+parser.add_argument('-s', '--stable', dest='stable', required=False, action='store_true', default=False)
90
+args = parser.parse_args()
91
+
92
+latest_tag = cmd('git describe --tags --abbrev=0')
93
+gen_html(args.user, latest_tag)
94
+prepare_pkg(args.project, args.package_id)
95
+save_manifest(latest_tag, args.user, args.jenkins_build, args.branch, args.stable)
96
obs-studio-17.0.1.tar.xz/CI/util
Added
2
1
+(directory)
2
obs-studio-17.0.1.tar.xz/CI/util/build-package-deps-osx.sh
Added
133
1
2
+#!/usr/bin/env bash
3
+
4
+CURDIR=$(pwd)
5
+
6
+# the temp directory
7
+WORK_DIR=`mktemp -d`
8
+
9
+# deletes the temp directory
10
+function cleanup {
11
+ #rm -rf "$WORK_DIR"
12
+ echo "Deleted temp working directory $WORK_DIR"
13
+}
14
+
15
+# register the cleanup function to be called on the EXIT signal
16
+trap cleanup EXIT
17
+
18
+cd $WORK_DIR
19
+
20
+DEPS_DEST=$WORK_DIR/obsdeps
21
+
22
+# make dest dirs
23
+mkdir $DEPS_DEST
24
+mkdir $DEPS_DEST/bin
25
+mkdir $DEPS_DEST/include
26
+
27
+# OSX COMPAT
28
+export MACOSX_DEPLOYMENT_TARGET=10.9
29
+
30
+# If you need an olders SDK and Xcode won't give it to you
31
+# https://github.com/phracker/MacOSX-SDKs
32
+
33
+# libopus
34
+curl -L -O http://downloads.xiph.org/releases/opus/opus-1.1.3.tar.gz
35
+tar -xf opus-1.1.3.tar.gz
36
+cd ./opus-1.1.3
37
+mkdir build
38
+cd ./build
39
+../configure --disable-shared --enable-static --prefix="/tmp/obsdeps"
40
+make -j 12
41
+make install
42
+
43
+cd $WORK_DIR
44
+
45
+# libogg
46
+curl -L -O http://downloads.xiph.org/releases/ogg/libogg-1.3.2.tar.gz
47
+tar -xf libogg-1.3.2.tar.gz
48
+cd ./libogg-1.3.2
49
+mkdir build
50
+cd ./build
51
+../configure --disable-shared --enable-static --prefix="/tmp/obsdeps"
52
+make -j 12
53
+make install
54
+
55
+cd $WORK_DIR
56
+
57
+# libvorbis
58
+curl -L -O http://downloads.xiph.org/releases/vorbis/libvorbis-1.3.5.tar.gz
59
+tar -xf libvorbis-1.3.5.tar.gz
60
+cd ./libvorbis-1.3.5
61
+mkdir build
62
+cd ./build
63
+../configure --disable-shared --enable-static --prefix="/tmp/obsdeps"
64
+make -j 12
65
+make install
66
+
67
+cd $WORK_DIR
68
+
69
+# libvpx
70
+curl -L -O http://storage.googleapis.com/downloads.webmproject.org/releases/webm/libvpx-1.6.0.tar.bz2
71
+tar -xf libvpx-1.6.0.tar.bz2
72
+cd ./libvpx-1.6.0
73
+mkdir build
74
+cd ./build
75
+../configure --disable-shared --libdir="/tmp/obsdeps/bin"
76
+make -j 12
77
+make install
78
+
79
+cd $WORK_DIR
80
+
81
+# x264
82
+git clone git://git.videolan.org/x264.git
83
+cd ./x264
84
+mkdir build
85
+cd ./build
86
+../configure --extra-ldflags="-mmacosx-version-min=10.9" --enable-static --prefix="/tmp/obsdeps"
87
+make -j 12
88
+make install
89
+../configure --extra-ldflags="-mmacosx-version-min=10.9" --enable-shared --libdir="/tmp/obsdeps/bin" --prefix="/tmp/obsdeps"
90
+make -j 12
91
+ln -f -s libx264.*.dylib libx264.dylib
92
+find . -name \*.dylib -exec cp \{\} $DEPS_DEST/bin/ \;
93
+rsync -avh --include="*/" --include="*.h" --exclude="*" ../* $DEPS_DEST/include/
94
+rsync -avh --include="*/" --include="*.h" --exclude="*" ./* $DEPS_DEST/include/
95
+
96
+cd $WORK_DIR
97
+
98
+# janson
99
+curl -L -O http://www.digip.org/jansson/releases/jansson-2.9.tar.gz
100
+tar -xf jansson-2.9.tar.gz
101
+cd jansson-2.9
102
+mkdir build
103
+cd ./build
104
+../configure --libdir="/tmp/obsdeps/bin" --enable-shared --disable-static
105
+make -j 12
106
+find . -name \*.dylib -exec cp \{\} $DEPS_DEST/bin/ \;
107
+rsync -avh --include="*/" --include="*.h" --exclude="*" ../* $DEPS_DEST/include/
108
+rsync -avh --include="*/" --include="*.h" --exclude="*" ./* $DEPS_DEST/include/
109
+
110
+cd $WORK_DIR
111
+
112
+export LDFLAGS="-L/tmp/obsdeps/lib"
113
+export CFLAGS="-I/tmp/obsdeps/include"
114
+
115
+# FFMPEG
116
+curl -L -O https://github.com/FFmpeg/FFmpeg/archive/n3.2.2.zip
117
+unzip ./n3.2.2.zip
118
+cd ./FFmpeg-n3.2.2
119
+mkdir build
120
+cd ./build
121
+../configure --extra-ldflags="-mmacosx-version-min=10.9" --enable-shared --disable-static --shlibdir="/tmp/obsdeps/bin" --enable-gpl --disable-doc --enable-libx264 --enable-libopus --enable-libvorbis --enable-libvpx
122
+make -j 12
123
+find . -name \*.dylib -exec cp \{\} $DEPS_DEST/bin/ \;
124
+rsync -avh --include="*/" --include="*.h" --exclude="*" ../* $DEPS_DEST/include/
125
+rsync -avh --include="*/" --include="*.h" --exclude="*" ./* $DEPS_DEST/include/
126
+
127
+cd $WORK_DIR
128
+
129
+tar -czf osx-deps.tar.gz obsdeps
130
+
131
+cp ./osx-deps.tar.gz $CURDIR
132
\ No newline at end of file
133
obs-studio-17.0.1.tar.xz/CI/util/win32.sh
Added
71
1
2
+#/bin/bash
3
+
4
+cd x264
5
+make clean
6
+LDFLAGS="-static-libgcc" ./configure --enable-shared --enable-win32thread --disable-avs --disable-ffms --disable-gpac --disable-interlaced --disable-lavf --cross-prefix=i686-w64-mingw32- --host=i686-pc-mingw32 --prefix="/home/jim/packages/win32"
7
+make -j6 fprofiled VIDS="CITY_704x576_60_orig_01.yuv"
8
+make install
9
+i686-w64-mingw32-dlltool -z /home/jim/packages/win32/bin/x264.orig.def --export-all-symbols /home/jim/packages/win32/bin/libx264-148.dll
10
+grep "EXPORTS\|x264" /home/jim/packages/win32/bin/x264.orig.def > /home/jim/packages/win32/bin/x264.def
11
+rm -f /home/jim/packages/win32/bin/x264.org.def
12
+sed -i -e "/\\t.*DATA/d" -e "/\\t\".*/d" -e "s/\s@.*//" /home/jim/packages/win32/bin/x264.def
13
+i686-w64-mingw32-dlltool -m i386 -d /home/jim/packages/win32/bin/x264.def -l /home/jim/packages/win32/bin/x264.lib -D /home/jim/win32/packages/bin/libx264-148.dll
14
+cd ..
15
+
16
+cd opus
17
+make clean
18
+LDFLAGS="-static-libgcc" ./configure -host=i686-w64-mingw32 --prefix="/home/jim/packages/win32" --enable-shared
19
+make -j6
20
+make install
21
+cd ..
22
+
23
+cd zlib/build32
24
+make clean
25
+cmake .. -DCMAKE_SYSTEM_NAME=Windows -DCMAKE_C_COMPILER=i686-w64-mingw32-gcc -DCMAKE_INSTALL_PREFIX=/home/jim/packages/win32 -DINSTALL_PKGCONFIG_DIR=/home/jim/packages/win32/lib/pkgconfig -DCMAKE_RC_COMPILER=i686-w64-mingw32-windres -DCMAKE_SHARED_LINKER_FLAGS="-static-libgcc"
26
+make -j6
27
+make install
28
+mv ../../win32/lib/libzlib.dll.a ../../win32/lib/libz.dll.a
29
+mv ../../win32/lib/libzlibstatic.a ../../win32/lib/libz.a
30
+cp ../win32/zlib.def /home/jim/packages/win32/bin
31
+i686-w64-mingw32-dlltool -m i386 -d ../win32/zlib.def -l /home/jim/packages/win32/bin/zlib.lib -D /home/jim/win32/packages/bin/zlib.dll
32
+cd ../..
33
+
34
+cd libpng
35
+make clean
36
+PKG_CONFIG_PATH="/home/jim/packages/win32/lib/pkgconfig" LDFLAGS="-L/home/jim/packages/win32/lib -static-libgcc" CPPFLAGS="-I/home/jim/packages/win32/include" ./configure -host=i686-w64-mingw32 --prefix="/home/jim/packages/win32" --enable-shared
37
+make -j6
38
+make install
39
+cd ..
40
+
41
+cd libogg
42
+make clean
43
+PKG_CONFIG_PATH="/home/jim/packages/win32/lib/pkgconfig" LDFLAGS="-L/home/jim/packages/win32/lib -static-libgcc" CPPFLAGS="-I/home/jim/packages/win32/include" ./configure -host=i686-w64-mingw32 --prefix="/home/jim/packages/win32" --enable-shared
44
+make -j6
45
+make install
46
+cd ..
47
+
48
+cd libvorbis
49
+make clean
50
+PKG_CONFIG_PATH="/home/jim/packages/win32/lib/pkgconfig" LDFLAGS="-L/home/jim/packages/win32/lib -static-libgcc" CPPFLAGS="-I/home/jim/packages/win32/include" ./configure -host=i686-w64-mingw32 --prefix="/home/jim/packages/win32" --enable-shared --with-ogg="/home/jim/packages/win32"
51
+make -j6
52
+make install
53
+cd ..
54
+
55
+cd libvpxbuild
56
+make clean
57
+PKG_CONFIG_PATH="/home/jim/packages/win32/lib/pkgconfig" CROSS=i686-w64-mingw32- LDFLAGS="-static-libgcc" ../libvpx/configure --prefix=/home/jim/packages/win32 --enable-vp8 --enable-vp9 --disable-docs --disable-examples --enable-shared --disable-static --enable-runtime-cpu-detect --enable-realtime-only --disable-install-bins --disable-install-docs --disable-unit-tests --target=x86-win32-gcc
58
+make -j6
59
+make install
60
+i686-w64-mingw32-dlltool -m i386 -d libvpx.def -l /home/jim/packages/win32/bin/vpx.lib -D /home/jim/win32/packages/bin/libvpx-1.dll
61
+cd ..
62
+
63
+cd ffmpeg
64
+make clean
65
+cp /media/sf_linux/nvEncodeAPI.h /home/jim/packages/win32/include
66
+PKG_CONFIG_PATH="/home/jim/packages/win32/lib/pkgconfig" LDFLAGS="-L/home/jim/packages/win32/lib -static-libgcc" CFLAGS="-I/home/jim/packages/win32/include" ./configure --enable-memalign-hack --enable-gpl --disable-programs --disable-doc --arch=x86 --enable-shared --enable-nvenc --enable-libx264 --enable-libopus --enable-libvorbis --enable-libvpx --disable-debug --cross-prefix=i686-w64-mingw32- --target-os=mingw32 --pkg-config=pkg-config --prefix="/home/jim/packages/win32" --disable-postproc
67
+read -n1 -r -p "Press any key to continue building FFmpeg..." key
68
+make -j6
69
+make install
70
+cd ..
71
obs-studio-17.0.1.tar.xz/CI/util/win64.sh
Added
71
1
2
+#/bin/bash
3
+
4
+cd x264
5
+make clean
6
+LDFLAGS="-static-libgcc" ./configure --enable-shared --enable-win32thread --disable-avs --disable-ffms --disable-gpac --disable-interlaced --disable-lavf --cross-prefix=x86_64-w64-mingw32- --host=x86_64-pc-mingw32 --prefix="/home/jim/packages/win64"
7
+make -j6 fprofiled VIDS="CITY_704x576_60_orig_01.yuv"
8
+make install
9
+x86_64-w64-mingw32-dlltool -z /home/jim/packages/win64/bin/x264.orig.def --export-all-symbols /home/jim/packages/win64/bin/libx264-148.dll
10
+grep "EXPORTS\|x264" /home/jim/packages/win64/bin/x264.orig.def > /home/jim/packages/win64/bin/x264.def
11
+rm -f /home/jim/packages/win64/bin/x264.org.def
12
+sed -i -e "/\\t.*DATA/d" -e "/\\t\".*/d" -e "s/\s@.*//" /home/jim/packages/win64/bin/x264.def
13
+x86_64-w64-mingw32-dlltool -m i386:x86-64 -d /home/jim/packages/win64/bin/x264.def -l /home/jim/packages/win64/bin/x264.lib -D /home/jim/win64/packages/bin/libx264-148.dll
14
+cd ..
15
+
16
+cd opus
17
+make clean
18
+LDFLAGS="-static-libgcc" ./configure -host=x86_64-w64-mingw32 --prefix="/home/jim/packages/win64" --enable-shared
19
+make -j6
20
+make install
21
+cd ..
22
+
23
+cd zlib/build64
24
+make clean
25
+cmake .. -DCMAKE_SYSTEM_NAME=Windows -DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc -DCMAKE_INSTALL_PREFIX=/home/jim/packages/win64 -DCMAKE_RC_COMPILER=x86_64-w64-mingw32-windres -DCMAKE_SHARED_LINKER_FLAGS="-static-libgcc"
26
+make -j6
27
+make install
28
+mv ../../win64/lib/libzlib.dll.a ../../win64/lib/libz.dll.a
29
+mv ../../win64/lib/libzlibstatic.a ../../win64/lib/libz.a
30
+cp ../win64/zlib.def /home/jim/packages/win64/bin
31
+x86_64-w64-mingw32-dlltool -m i386:x86-64 -d ../win32/zlib.def -l /home/jim/packages/win64/bin/zlib.lib -D /home/jim/win64/packages/bin/zlib.dll
32
+cd ../..
33
+
34
+cd libpng
35
+make clean
36
+PKG_CONFIG_PATH="/home/jim/packages/win64/lib/pkgconfig" LDFLAGS="-L/home/jim/packages/win64/lib" CPPFLAGS="-I/home/jim/packages/win64/include" ./configure -host=x86_64-w64-mingw32 --prefix="/home/jim/packages/win64" --enable-shared
37
+make -j6
38
+make install
39
+cd ..
40
+
41
+cd libogg
42
+make clean
43
+PKG_CONFIG_PATH="/home/jim/packages/win64/lib/pkgconfig" LDFLAGS="-L/home/jim/packages/win64/lib -static-libgcc" CPPFLAGS="-I/home/jim/packages/win64/include" ./configure -host=x86_64-w64-mingw32 --prefix="/home/jim/packages/win64" --enable-shared
44
+make -j6
45
+make install
46
+cd ..
47
+
48
+cd libvorbis
49
+make clean
50
+PKG_CONFIG_PATH="/home/jim/packages/win64/lib/pkgconfig" LDFLAGS="-L/home/jim/packages/win64/lib -static-libgcc" CPPFLAGS="-I/home/jim/packages/win64/include" ./configure -host=x86_64-w64-mingw32 --prefix="/home/jim/packages/win64" --enable-shared --with-ogg="/home/jim/packages/win64"
51
+make -j6
52
+make install
53
+cd ..
54
+
55
+cd libvpxbuild
56
+make clean
57
+PKG_CONFIG_PATH="/home/jim/packages/win64/lib/pkgconfig" CROSS=x86_64-w64-mingw32- LDFLAGS="-static-libgcc" ../libvpx/configure --prefix=/home/jim/packages/win64 --enable-vp8 --enable-vp9 --disable-docs --disable-examples --enable-shared --disable-static --enable-runtime-cpu-detect --enable-realtime-only --disable-install-bins --disable-install-docs --disable-unit-tests --target=x86_64-win64-gcc
58
+make -j6
59
+make install
60
+x86_64-w64-mingw32-dlltool -m i386:x86-64 -d libvpx.def -l /home/jim/packages/win64/bin/vpx.lib -D /home/jim/win64/packages/bin/libvpx-1.dll
61
+cd ..
62
+
63
+cd ffmpeg
64
+make clean
65
+cp /media/sf_linux/nvEncodeAPI.h /home/jim/packages/win64/include
66
+PKG_CONFIG_PATH="/home/jim/packages/win64/lib/pkgconfig" LDFLAGS="-L/home/jim/packages/win64/lib" CPPFLAGS="-I/home/jim/packages/win64/include" ./configure --enable-memalign-hack --enable-gpl --disable-doc --arch=x86_64 --enable-shared --enable-nvenc --enable-libx264 --enable-libopus --enable-libvorbis --enable-libvpx --disable-debug --cross-prefix=x86_64-w64-mingw32- --target-os=mingw32 --pkg-config=pkg-config --prefix="/home/jim/packages/win64" --disable-postproc
67
+read -n1 -r -p "Press any key to continue building FFmpeg..." key
68
+make -j6
69
+make install
70
+cd ..
71
obs-studio-0.17.0.tar.xz/UI/data/locale/ca-ES.ini -> obs-studio-17.0.1.tar.xz/UI/data/locale/ca-ES.ini
Changed
96
1
2
Hours="Hores"
3
Minutes="Minuts"
4
Seconds="Segons"
5
+Deprecated="Obsolet"
6
+ReplayBuffer="Memòria intermèdia de reproducció"
7
+Import="Importa"
8
+Export="Exporta"
9
10
QuickTransitions.SwapScenes="Canvia la vista prèvia i sortida d'escenes després de la transició"
11
QuickTransitions.SwapScenesTT="Canvia la vista prèvia i sortida d'escenes després de la transició (si encara existeix l'escena original de la sortida). \nAixò no desfarà qualsevol canvi que pugui haver fet a l'escena original de la sortida."
12
13
Output.RecordNoSpace.Msg="No hi ha prou espai de disc per continuar la gravació."
14
Output.RecordError.Title="Error en l'enregistrament"
15
Output.RecordError.Msg="S'ha produït un error desconegut mentre es gravava."
16
+Output.ReplayBuffer.NoHotkey.Title="Cap tecla d'accés ràpid!"
17
+Output.ReplayBuffer.NoHotkey.Msg="Cap tecla d'accés ràpid establerta per la memòria intermèdia de reproducció. Configureu la tecla d'accés \"Desa\" per desar els enregistraments de reproducció."
18
19
Output.BadPath.Title="Ruta de l'arxiu incorrecta"
20
Output.BadPath.Text="La ruta configurada pel fitxer de sortida no és vàlida. Si us plau, comproveu la configuració per confirmar que s'ha creat una ruta de fitxer vàlida."
21
22
Basic.Main.Sources="Orígens"
23
Basic.Main.Connecting="S'està connectant..."
24
Basic.Main.StartRecording="Inicia l'enregistrament"
25
-Basic.Main.StartStreaming="Inicia l'enregistrament"
26
+Basic.Main.StartReplayBuffer="Inicia la reproducció de la memòria intermèdia"
27
+Basic.Main.StartStreaming="Inicia la transmissió"
28
Basic.Main.StopRecording="Atura l'enregistrament"
29
Basic.Main.StoppingRecording="Aturant l'enregistrament..."
30
+Basic.Main.StopReplayBuffer="Atura la reproducció de la memòria intermèdia"
31
+Basic.Main.StoppingReplayBuffer="S'està aturant la reproducció de la memòria intermèdia..."
32
Basic.Main.StopStreaming="Atura l'enregistrament"
33
Basic.Main.StoppingStreaming="Aturant la transmissió..."
34
Basic.Main.ForceStopStreaming="Atura l'enregistrament (descarta el retard)"
35
36
Basic.MainMenu.File.Import="&Importa"
37
Basic.MainMenu.File.ShowRecordings="Mostra els en®istraments"
38
Basic.MainMenu.File.Remux="Converteix format de gravacions"
39
-Basic.MainMenu.File.Settings="&Paràmetres"
40
+Basic.MainMenu.File.Settings="&Configuració"
41
Basic.MainMenu.File.ShowSettingsFolder="Mostrar carpeta de configuració"
42
Basic.MainMenu.File.ShowProfileFolder="Mostra la carpeta del perfil"
43
Basic.MainMenu.AlwaysOnTop="&Sempre al davant"
44
45
Basic.MainMenu.Edit.UndoAction="&Desfés $1"
46
Basic.MainMenu.Edit.RedoAction="&Refés $1"
47
Basic.MainMenu.Edit.LockPreview="&Bloquejar vista prèvia"
48
+Basic.MainMenu.Edit.Scale="Vista prèvia i escalat"
49
+Basic.MainMenu.Edit.Scale.Window="Ajusta a la finestra"
50
+Basic.MainMenu.Edit.Scale.Canvas="Tela (%1x%2)"
51
+Basic.MainMenu.Edit.Scale.Output="Sortida (%1x%2)"
52
Basic.MainMenu.Edit.Transform="&Transforma"
53
Basic.MainMenu.Edit.Transform.EditTransform="&Editar Transformació..."
54
+Basic.MainMenu.Edit.Transform.CopyTransform="Copia la transformació"
55
+Basic.MainMenu.Edit.Transform.PasteTransform="Enganxa la transformació"
56
Basic.MainMenu.Edit.Transform.ResetTransform="&Reinicialitza Transformació"
57
Basic.MainMenu.Edit.Transform.Rotate90CW="Gira 90 graus a la dreta"
58
Basic.MainMenu.Edit.Transform.Rotate90CCW="Gira 90 graus a l'esquerra"
59
60
61
Basic.MainMenu.SceneCollection="&Col·lecció d'escenes"
62
Basic.MainMenu.Profile="&Perfil"
63
+Basic.MainMenu.Profile.Import="Importació del perfil"
64
+Basic.MainMenu.Profile.Export="Exportació del perfil"
65
+Basic.MainMenu.SceneCollection.Import="Importa col·lecció d'escenes"
66
+Basic.MainMenu.SceneCollection.Export="Exporta la col·lecció d'escenes"
67
+Basic.MainMenu.Profile.Exists="El perfil ja existeix"
68
+Basic.MainMenu.SceneCollection.Exists="La col·lecció d'escenes ja existeix"
69
70
Basic.MainMenu.Tools="&Eines"
71
72
73
Basic.Settings.Output.Mode.Simple="Simple"
74
Basic.Settings.Output.Mode.Adv="Avançat"
75
Basic.Settings.Output.Mode.FFmpeg="Sortida FFmpeg"
76
+Basic.Settings.Output.UseReplayBuffer="Activa la reproducció de la memòria intermèdia"
77
+Basic.Settings.Output.ReplayBuffer.SecondsMax="Temps de reproducció màxim (segons)"
78
+Basic.Settings.Output.ReplayBuffer.MegabytesMax="Memòria màxima (MB)"
79
+Basic.Settings.Output.ReplayBuffer.Estimate="Ús aproximat de memòria: %1 MB"
80
+Basic.Settings.Output.ReplayBuffer.EstimateUnknown="No es pot estimar l'ús de memòria. Establiu el límit màxim de memòria."
81
+Basic.Settings.Output.ReplayBuffer.HotkeyMessage="(Nota: Assegureu-vos d'establir una tecla d'accés ràpid per la memòria intermèdia de reproducció a la secció de tecles ràpides)"
82
+Basic.Settings.Output.ReplayBuffer.Prefix="Prefix del nom del fitxer de la memòria intermèdia"
83
+Basic.Settings.Output.ReplayBuffer.Suffix="Sufix"
84
Basic.Settings.Output.Simple.SavePath="Camí d'enregistrament"
85
Basic.Settings.Output.Simple.RecordingQuality="Qualitat de l'enregistrament"
86
Basic.Settings.Output.Simple.RecordingQuality.Stream="Mateixa que en directe"
87
88
Basic.Settings.Output.Adv.Audio.Track2="Pista 2"
89
Basic.Settings.Output.Adv.Audio.Track3="Pista 3"
90
Basic.Settings.Output.Adv.Audio.Track4="Pista 4"
91
+Basic.Settings.Output.Adv.Audio.Track5="Pista 5"
92
+Basic.Settings.Output.Adv.Audio.Track6="Pista 6"
93
94
Basic.Settings.Output.Adv.Recording="Enregistrament"
95
Basic.Settings.Output.Adv.Recording.Type="Tipus"
96
obs-studio-0.17.0.tar.xz/UI/data/locale/cs-CZ.ini -> obs-studio-17.0.1.tar.xz/UI/data/locale/cs-CZ.ini
Changed
10
1
2
Basic.Settings.Output.Adv.Audio.Track2="Stopa 2"
3
Basic.Settings.Output.Adv.Audio.Track3="Stopa 3"
4
Basic.Settings.Output.Adv.Audio.Track4="Stopa 4"
5
+Basic.Settings.Output.Adv.Audio.Track5="Stopa 5"
6
+Basic.Settings.Output.Adv.Audio.Track6="Stopa 6"
7
8
Basic.Settings.Output.Adv.Recording="Nahrávání"
9
Basic.Settings.Output.Adv.Recording.Type="Typ"
10
obs-studio-0.17.0.tar.xz/UI/data/locale/de-DE.ini -> obs-studio-17.0.1.tar.xz/UI/data/locale/de-DE.ini
Changed
10
1
2
Region="Deutschland"
3
4
OK="OK"
5
-Apply="Anwenden"
6
+Apply="Übernehmen"
7
Cancel="Abbrechen"
8
Close="Schließen"
9
Save="Speichern"
10
obs-studio-0.17.0.tar.xz/UI/data/locale/fi-FI.ini -> obs-studio-17.0.1.tar.xz/UI/data/locale/fi-FI.ini
Changed
10
1
2
Basic.Settings.Output.Adv.Audio.Track2="Raita 2"
3
Basic.Settings.Output.Adv.Audio.Track3="Raita 3"
4
Basic.Settings.Output.Adv.Audio.Track4="Raita 4"
5
+Basic.Settings.Output.Adv.Audio.Track5="Raita 5"
6
+Basic.Settings.Output.Adv.Audio.Track6="Raita 6"
7
8
Basic.Settings.Output.Adv.Recording="Tallennus"
9
Basic.Settings.Output.Adv.Recording.Type="Tyyppi"
10
obs-studio-0.17.0.tar.xz/UI/data/locale/hu-HU.ini -> obs-studio-17.0.1.tar.xz/UI/data/locale/hu-HU.ini
Changed
65
1
2
Basic.MainMenu.File.Export="&Exportálás"
3
Basic.MainMenu.File.Import="&Importálás"
4
Basic.MainMenu.File.ShowRecordings="&Felvételek megjelenítése"
5
-Basic.MainMenu.File.Remux="Re&mux felvételek"
6
+Basic.MainMenu.File.Remux="Felvételek re&muxolása"
7
Basic.MainMenu.File.Settings="&Beállítások"
8
Basic.MainMenu.File.ShowSettingsFolder="Beállítási mappa megjelenítése"
9
Basic.MainMenu.File.ShowProfileFolder="Profilmappa megjelenítése"
10
11
Basic.MainMenu.Edit.RedoAction="&Ismét $1"
12
Basic.MainMenu.Edit.LockPreview="&Előnézet zárolás"
13
Basic.MainMenu.Edit.Scale="Előnézet &méretezés"
14
-Basic.MainMenu.Edit.Scale.Window="Ablakhoz skálázás"
15
+Basic.MainMenu.Edit.Scale.Window="Ablakhoz igazítás"
16
Basic.MainMenu.Edit.Scale.Canvas="Vászon (%1x%2)"
17
Basic.MainMenu.Edit.Scale.Output="Kimenet (%1x%2)"
18
Basic.MainMenu.Edit.Transform="&Alakítás"
19
20
Basic.MainMenu.Tools="&Eszközök"
21
22
Basic.MainMenu.Help="&Segítség"
23
-Basic.MainMenu.Help.Website="Weboldal meglátogatása"
24
+Basic.MainMenu.Help.Website="Weboldal megtekintése"
25
Basic.MainMenu.Help.Logs="&Naplófájlok"
26
Basic.MainMenu.Help.Logs.ShowLogs="&Naplófájlok megjelenítése"
27
Basic.MainMenu.Help.Logs.UploadCurrentLog="&Aktuális Naplófájl feltöltése"
28
Basic.MainMenu.Help.Logs.UploadLastLog="&Utolsó Naplófájl feltöltése"
29
-Basic.MainMenu.Help.Logs.ViewCurrentLog="&Jelenlegi napló megtekintése"
30
+Basic.MainMenu.Help.Logs.ViewCurrentLog="&Jelenlegi Naplófájl megtekintése"
31
Basic.MainMenu.Help.CheckForUpdates="Frissítések ellenőrzése"
32
33
Basic.Settings.ProgramRestart="A beállítások érvénybe lépéséhez a program újraindítása szükséges."
34
35
Basic.Settings.Output.Encoder="Kódoló"
36
Basic.Settings.Output.SelectDirectory="Felvételi könyvtár kiválasztása"
37
Basic.Settings.Output.SelectFile="Felvétel fájljának kiválasztása"
38
-Basic.Settings.Output.EnforceBitrate="Stream kiszolgáló bitráta korlátainak kényszerítése"
39
+Basic.Settings.Output.EnforceBitrate="Stream kiszolgáló bitsebesség korlátainak kényszerítése"
40
Basic.Settings.Output.Mode="Kimeneti mód"
41
Basic.Settings.Output.Mode.Simple="Egyszerű"
42
Basic.Settings.Output.Mode.Adv="Haladó"
43
44
Basic.Settings.Output.Simple.RecordingQuality.Small="Jó minőség, közepes fájlméret"
45
Basic.Settings.Output.Simple.RecordingQuality.HQ="Megkülönböztethetetlen minőség, nagy fájlméret"
46
Basic.Settings.Output.Simple.RecordingQuality.Lossless="Veszteségmentes minőség, hatalmas fájlméret"
47
-Basic.Settings.Output.Simple.Warn.VideoBitrate="Figyelem: Az adás videó bitrátája %1 értéken áll, ami a kiválasztott kiszolgáló felső határértéke. Amennyiben túl kívánja lépni a megadott %1 értéket, úgy engedélyezze a haladó kódolási opciókat és törölje a \"stream kiszolgáló bitráta korlátainak kényszerítése\" opciót."
48
-Basic.Settings.Output.Simple.Warn.AudioBitrate="Figyelem: Az adás audio bitrátája %1 értéken áll, ami a kiválasztott kiszolgáló felső határértéke. Amennyiben túl kívánja lépni a megadott %1 értéket, úgy engedélyezze a haladó kódolási opciókat és törölje a \"stream kiszolgáló bitráta korlátainak kényszerítése\" opciót."
49
+Basic.Settings.Output.Simple.Warn.VideoBitrate="Figyelem: Az adás videó bitsebessége %1 értéken áll, ami a kiválasztott kiszolgáló felső határértéke. Amennyiben túl kívánja lépni a megadott %1 értéket, úgy engedélyezze a haladó kódolási opciókat és törölje a \"stream kiszolgáló bitsebesség korlátainak kényszerítése\" opciót."
50
+Basic.Settings.Output.Simple.Warn.AudioBitrate="Figyelem: Az adás audio bitsebessége %1 értéken áll, ami a kiválasztott kiszolgáló felső határértéke. Amennyiben túl kívánja lépni a megadott %1 értéket, úgy engedélyezze a haladó kódolási opciókat és törölje a \"stream kiszolgáló bitsebesség korlátainak kényszerítése\" opciót."
51
Basic.Settings.Output.Simple.Warn.Encoder="Figyelem: A streamtől eltérő minőséggel történő rögzítés, további CPU erőforrásokat igényel, ha egyidejűleg használja mindkettőt."
52
Basic.Settings.Output.Simple.Warn.Lossless="Figyelem: A veszteségmentes minőséggel történő felvétel hatalmas fájlméretet generál. Ezzel a minőséggel percenként akár 7 gigabájt adatot is generálhat nagy felbontáson és képkockasebességen. Ez az eljárás nem ajánlott hosszú felvételekhez, kivéve ha hatalmas lemezterület áll rendelkezésre."
53
Basic.Settings.Output.Simple.Warn.Lossless.Msg="Biztos benne, hogy veszteségmentes minőséget kíván használni?"
54
55
Basic.Settings.Output.Simple.Encoder.Hardware.AMD="Hardver (AMD)"
56
Basic.Settings.Output.Simple.Encoder.Hardware.NVENC="Hardver (NVENC)"
57
Basic.Settings.Output.Simple.Encoder.SoftwareLowCPU="Szoftveres (x264 alacsony CPU használati készlet, növekvő fájlméret)"
58
-Basic.Settings.Output.VideoBitrate="Videó bitráta"
59
-Basic.Settings.Output.AudioBitrate="Audio bitráta"
60
+Basic.Settings.Output.VideoBitrate="Videó bitsebesség"
61
+Basic.Settings.Output.AudioBitrate="Audio bitsebesség"
62
Basic.Settings.Output.Reconnect="Automatikus újracsatlakozás"
63
Basic.Settings.Output.RetryDelay="Újrapróbálkozás késleltetése (másodperc)"
64
Basic.Settings.Output.MaxRetries="Újrapróbálkozások maximális száma"
65
obs-studio-0.17.0.tar.xz/UI/data/locale/it-IT.ini -> obs-studio-17.0.1.tar.xz/UI/data/locale/it-IT.ini
Changed
226
1
2
MoveUp="Sposta su"
3
MoveDown="Sposta giù"
4
Settings="Impostazioni"
5
-Display="Display"
6
+Display="Schermo"
7
Name="Nome"
8
Exit="Esci"
9
Mixer="Mixer"
10
11
Mono="Mono"
12
Stereo="Stereo"
13
DroppedFrames="Fotogrammi persi %1 (%2%)"
14
-PreviewProjector="Proiettore Schermo intero (Anteprima)"
15
-SceneProjector="Proiettore Schermo intero (Scena)"
16
-SourceProjector="Proiettore Schermo intero (Sorgente)"
17
+PreviewProjector="Proiettore a schermo intero (anteprima)"
18
+SceneProjector="Proiettore a schermo intero (scena)"
19
+SourceProjector="Proiettore a schermo intero (sorgente)"
20
Clear="Svuota"
21
Revert="Ripristina"
22
Show="Mostra"
23
Hide="Nascondi"
24
-Untitled="Senza Titolo"
25
+Untitled="Senza titolo"
26
New="Nuovo"
27
Duplicate="Duplica"
28
Enable="Abilita"
29
-DisableOSXVSync="Disabilita il V-Sync OSX"
30
-ResetOSXVSyncOnExit="Reimpostare V-Sync OSX in uscita"
31
-HighResourceUsage="Codifica in sovraccarico! È consigliabile abbassare le impostazioni video o utilizzare un settaggio predefinito di codifica più veloce."
32
+DisableOSXVSync="Disabilita V-Sync OSX"
33
+ResetOSXVSyncOnExit="Reimposta V-Sync OSX in uscita"
34
+HighResourceUsage="Codifica in sovraccarico! È consigliabile abbassare le impostazioni video o utilizzare una preimpostazione predefinita di codifica più veloce."
35
Transition="Transizione"
36
QuickTransitions="Transizioni rapide"
37
Left="Sinistra"
38
Right="Destra"
39
Top="Alto"
40
Bottom="Basso"
41
-Reset="Reset"
42
+Reset="Ripristina"
43
Hours="Ore"
44
Minutes="Minuti"
45
Seconds="Secondi"
46
Deprecated="Deprecato"
47
-
48
-QuickTransitions.SwapScenes="Scambia Scena Preview/Uscita dopo la Transizione"
49
-QuickTransitions.SwapScenesTT="Scambia la scena in uniscita con quella in preview dopo la transizione (ammesso che la scena in uscita originale ci sia ancora).\nQuesto non modificherà eventuali cambiamenti apportati alla scena di uscita originale."
50
-QuickTransitions.DuplicateScene="Duplica Scena"
51
-QuickTransitions.DuplicateSceneTT="Quando si modifica la stessa scena, permette di modificare la trasformazione/visibilità di source senza modificare l'output. \nPer modificare le proprietà delle source senza modificare l'output, abilità 'Source duplicate'.\nCambiare questo valore resetterà la scena output attuale (se esite ancora)."
52
+ReplayBuffer="Buffer di replay"
53
+Import="Importa"
54
+Export="Esporta"
55
+
56
+QuickTransitions.SwapScenes="Scambia scene di anteprima/uscita dopo la transizione"
57
+QuickTransitions.SwapScenesTT="Scambia le scene di uscita con quella in anteprima dopo la transizione (ammesso che la scena in uscita originale ci sia ancora).\nQuesto non modificherà eventuali cambiamenti apportati alla scena di uscita originale."
58
+QuickTransitions.DuplicateScene="Duplica scena"
59
+QuickTransitions.DuplicateSceneTT="Quando si modifica la stessa scena, permette di modificare la trasformazione/visibilità delle sorgenti senza modificare l'uscita.\nPer modificare le proprietà delle source senza modificare l'uscita, abilità 'Sorgenti duplicate'.\nCambiare questo valore ripristinerà la scena di uscita attuale (se esiste ancora)."
60
QuickTransitions.EditProperties="Duplica Risorsa"
61
QuickTransitions.EditPropertiesTT="Quando si modifica la stessa scena, consente la modifica di risorse senza modificarne l'output. \nQuesto può essere usato solo se 'Scene doppia' è attivo. \nCerte risorse (come media o catture) non lo supportano e devono essere modificate separatamente. \nCambiare questo valore resetterà l'attuale scena di output (se esiste ancora). \n\nAttenzione: Dato che la risorsa verrà duplicata, questo potrebbe richiedere risorse di sistema o video aggiuntive."
62
QuickTransitions.HotkeyName="Transizioni rapide: %1"
63
64
Basic.TransitionDuration="Durata"
65
Basic.TogglePreviewProgramMode="Modalità studio"
66
67
-TransitionNameDlg.Text="Per favore inserisci il nome della transizione"
68
+TransitionNameDlg.Text="Inserisci il nome della transizione"
69
TransitionNameDlg.Title="Nome transizione"
70
71
TitleBar.Profile="Profilo"
72
73
NoNameEntered.Title="Inserisci un nome valido"
74
NoNameEntered.Text="Non è possibile utilizzare nomi vuoti."
75
76
-ConfirmStart.Title="Inizia diretta?"
77
+ConfirmStart.Title="Vuoi iniziare la trasmissione?"
78
ConfirmStart.Text="Sei sicuro di voler iniziare una diretta?"
79
80
-ConfirmStop.Title="Interrompere diretta?"
81
-ConfirmStop.Text="Sei sicuro di voler interrompere questa diretta?"
82
+ConfirmStop.Title="Vuoi fermare la trasmissione?"
83
+ConfirmStop.Text="Sei sicuro di voler interrompere questa trasmissione?"
84
85
-ConfirmExit.Title="Uscire da OBS?"
86
+ConfirmExit.Title="Vuoi uscire da OBS?"
87
ConfirmExit.Text="OBS è attualmente attivo. Tutte le dirette/registrazioni saranno fermate. Sei sicuro di voler uscire?"
88
89
ConfirmRemove.Title="Conferma la rimozione"
90
91
Output.RecordNoSpace.Msg="Non c'è abbastanza spazio su disco per continuazre la registrazione."
92
Output.RecordError.Title="Errore di registrazione"
93
Output.RecordError.Msg="Si è verificato un errore non specificato durante la registrazione."
94
+Output.ReplayBuffer.NoHotkey.Title="Nessuna scorciatoia assegnata!"
95
+Output.ReplayBuffer.NoHotkey.Msg="Nessuna scorciatoia impostata per salvare il buffer di replay. Impostare la scorciatoia \"Salva\" per poter salvare le registrazioni in replay."
96
97
Output.BadPath.Title="Percorso di file invalido"
98
Output.BadPath.Text="Il percorso configurato per il file di output non è valido. Controlla le tue impostazioni per confermare che un percorso di file valido è stato impostato."
99
100
Remux.OBSRecording="Registrazione OBS"
101
Remux.FinishedTitle="Conversione finita"
102
Remux.Finished="Registrazione convertita"
103
-Remux.FinishedError="Registrazione convertita, ma il file potrebbe essere incompleta"
104
-Remux.SelectRecording="Selezionare registrazione OBS …"
105
+Remux.FinishedError="Registrazione convertita, ma il file potrebbe essere incompleto"
106
+Remux.SelectRecording="Selezionare registrazione OBS…"
107
Remux.SelectTarget="Selezionare il file di destinazione…"
108
Remux.FileExistsTitle="Il file di destinazione esiste"
109
Remux.FileExists="Il file di destinazione esiste, si desidera sostituirlo?"
110
111
Basic.Scene="Scena"
112
Basic.DisplayCapture="Mostra cattura"
113
114
-Basic.Main.PreviewConextMenu.Enable="Abilita Anteprima"
115
+Basic.Main.PreviewConextMenu.Enable="Abilita anteprima"
116
117
ScaleFiltering="Scala di filtraggio"
118
ScaleFiltering.Point="Punto"
119
120
Basic.Main.Sources="Origini"
121
Basic.Main.Connecting="Connessione..."
122
Basic.Main.StartRecording="Avvia registrazione"
123
+Basic.Main.StartReplayBuffer="Avvia Buffer di Replay"
124
Basic.Main.StartStreaming="Avvia trasmissione"
125
Basic.Main.StopRecording="Ferma registrazione"
126
Basic.Main.StoppingRecording="Fermando la registrazione..."
127
+Basic.Main.StopReplayBuffer="Termina Buffer di Replay"
128
+Basic.Main.StoppingReplayBuffer="Fermando il Buffer di Replay..."
129
Basic.Main.StopStreaming="Ferma trasmissione"
130
Basic.Main.StoppingStreaming="Arresto diretta..."
131
Basic.Main.ForceStopStreaming="Ferma Diretta (annulla ritardo)"
132
133
Basic.MainMenu.File.ShowSettingsFolder="Visualizza cartella impostazioni"
134
Basic.MainMenu.File.ShowProfileFolder="Mostra la cartella del profilo"
135
Basic.MainMenu.AlwaysOnTop="&Sempre in primo piano"
136
-Basic.MainMenu.File.Exit="Esci (&X)"
137
+Basic.MainMenu.File.Exit="E&sci"
138
139
Basic.MainMenu.Edit="&Modifica"
140
Basic.MainMenu.Edit.Undo="&Annulla"
141
Basic.MainMenu.Edit.Redo="&Ripristina"
142
Basic.MainMenu.Edit.UndoAction="&Ripristina $1"
143
Basic.MainMenu.Edit.RedoAction="&Ripristina $1"
144
-Basic.MainMenu.Edit.LockPreview="&Blocca Anteprima"
145
-Basic.MainMenu.Edit.Scale="Anteprima & ridimensionamento"
146
+Basic.MainMenu.Edit.LockPreview="&Blocca anteprima"
147
+Basic.MainMenu.Edit.Scale="Anteprima ridimen&sionamento"
148
Basic.MainMenu.Edit.Scale.Window="Scala alla finestra"
149
Basic.MainMenu.Edit.Scale.Canvas="Tela (%1x%2)"
150
Basic.MainMenu.Edit.Scale.Output="Uscita (%1x%2)"
151
Basic.MainMenu.Edit.Transform="&Trasforma"
152
Basic.MainMenu.Edit.Transform.EditTransform="&Modifica e trasforma..."
153
+Basic.MainMenu.Edit.Transform.CopyTransform="Copia Trasformazione"
154
+Basic.MainMenu.Edit.Transform.PasteTransform="Incolla Trasformazione"
155
Basic.MainMenu.Edit.Transform.ResetTransform="&Reset e trasforma"
156
Basic.MainMenu.Edit.Transform.Rotate90CW="Ruota di 90 gradi DW"
157
Basic.MainMenu.Edit.Transform.Rotate90CCW="Ruota di 90 gradi CCW"
158
159
Basic.MainMenu.Edit.Order.MoveDown="Sposta in &basso"
160
Basic.MainMenu.Edit.Order.MoveToTop="Sposta in &primo piano"
161
Basic.MainMenu.Edit.Order.MoveToBottom="Sposta in &fondo"
162
-Basic.MainMenu.Edit.AdvAudio="Proprietà Audio &Avanzate"
163
+Basic.MainMenu.Edit.AdvAudio="Proprietà audio &avanzate"
164
165
Basic.MainMenu.View="&Visualizza"
166
Basic.MainMenu.View.Toolbars="&Barre degli strumenti"
167
168
169
Basic.MainMenu.SceneCollection="&Collezione scene"
170
Basic.MainMenu.Profile="&Profilo"
171
+Basic.MainMenu.Profile.Import="Importa profilo"
172
+Basic.MainMenu.Profile.Export="Esporta profilo"
173
+Basic.MainMenu.SceneCollection.Import="Importa collezione scene"
174
+Basic.MainMenu.SceneCollection.Export="Esporta collezione scene"
175
+Basic.MainMenu.Profile.Exists="Il profilo esiste già"
176
+Basic.MainMenu.SceneCollection.Exists="La collezione di scene già esiste"
177
178
Basic.MainMenu.Tools="&Strumenti"
179
180
-Basic.MainMenu.Help="Aiuto (&H)"
181
+Basic.MainMenu.Help="&Aiuto"
182
Basic.MainMenu.Help.Website="Visita il sito"
183
Basic.MainMenu.Help.Logs="File di &log"
184
Basic.MainMenu.Help.Logs.ShowLogs="&Visualizza i file di Log"
185
186
Basic.Settings.Output.Mode.Simple="Semplice"
187
Basic.Settings.Output.Mode.Adv="Avanzate"
188
Basic.Settings.Output.Mode.FFmpeg="Uscita FFmpeg"
189
+Basic.Settings.Output.UseReplayBuffer="Abilita il Buffer di Replay"
190
+Basic.Settings.Output.ReplayBuffer.SecondsMax="Tempo massimo di Replay (Secondi)"
191
+Basic.Settings.Output.ReplayBuffer.MegabytesMax="Memoria Massima (Megabytes)"
192
+Basic.Settings.Output.ReplayBuffer.Estimate="Uso della memoria stimato: %1 MB"
193
+Basic.Settings.Output.ReplayBuffer.EstimateUnknown="Impossibile stimare la memoria utilizzata. Impostare un limite massimo di memoria."
194
+Basic.Settings.Output.ReplayBuffer.HotkeyMessage="(Nota: Assicurati di aver impostato una hotkey per il Buffer di Replay nella sezione delle hotkeys)"
195
+Basic.Settings.Output.ReplayBuffer.Prefix="Prefisso del file per i Buffer di Replay"
196
+Basic.Settings.Output.ReplayBuffer.Suffix="Suffisso"
197
Basic.Settings.Output.Simple.SavePath="Percorso registrazione"
198
Basic.Settings.Output.Simple.RecordingQuality="Qualità della registrazione"
199
Basic.Settings.Output.Simple.RecordingQuality.Stream="Stesso della diretta"
200
201
Basic.Settings.Output.Adv.Audio.Track2="Traccia 2"
202
Basic.Settings.Output.Adv.Audio.Track3="Traccia 3"
203
Basic.Settings.Output.Adv.Audio.Track4="Traccia 4"
204
+Basic.Settings.Output.Adv.Audio.Track5="Traccia 5"
205
+Basic.Settings.Output.Adv.Audio.Track6="Traccia 6"
206
207
Basic.Settings.Output.Adv.Recording="Registrazione"
208
Basic.Settings.Output.Adv.Recording.Type="Tipo"
209
Basic.Settings.Output.Adv.Recording.Type.Standard="Standard"
210
Basic.Settings.Output.Adv.Recording.Type.FFmpegOutput="Output personalizzato (FFmpeg)"
211
Basic.Settings.Output.Adv.Recording.UseStreamEncoder="(Utilizzare il codificatore del flusso)"
212
-Basic.Settings.Output.Adv.Recording.Filename="Formattazione del nome del file"
213
+Basic.Settings.Output.Adv.Recording.Filename="Formattazione nome del file"
214
Basic.Settings.Output.Adv.Recording.OverwriteIfExists="Sovrascrivi il file se già esistente"
215
Basic.Settings.Output.Adv.FFmpeg.Type="Tipo di Output FFmpeg"
216
Basic.Settings.Output.Adv.FFmpeg.Type.URL="Output in URL"
217
218
Basic.Settings.Advanced.Network="Rete"
219
Basic.Settings.Advanced.Network.BindToIP="Associa a IP"
220
221
-Basic.AdvAudio="Proprietà Audio Avanzate"
222
+Basic.AdvAudio="Proprietà audio avanzate"
223
Basic.AdvAudio.Name="Nome"
224
Basic.AdvAudio.Volume="Volume (%)"
225
Basic.AdvAudio.Mono="Downmix to Mono"
226
obs-studio-0.17.0.tar.xz/UI/data/locale/pt-BR.ini -> obs-studio-17.0.1.tar.xz/UI/data/locale/pt-BR.ini
Changed
87
1
2
Hours="Horas"
3
Minutes="Minutos"
4
Seconds="Segundos"
5
+Deprecated="Obsoleto"
6
+ReplayBuffer="Buffer do Replay"
7
+Export="Exportar"
8
9
QuickTransitions.SwapScenes="Trocar Cenas de Prévia/Saída após a Transição"
10
QuickTransitions.SwapScenesTT="Troca a preview e a saída após transicionar (se a a cena original de saída ainda exisitr).\nIsto não irá desfazer nenhuma mudança que foi feita na cena original da saída."
11
12
Output.RecordNoSpace.Msg="Não há espaço em disco suficiente para continuar a gravação."
13
Output.RecordError.Title="Erro de gravação"
14
Output.RecordError.Msg="Ocorreu um erro não especificado durante a gravação."
15
+Output.ReplayBuffer.NoHotkey.Title="Tecla de Atalho não configurada!"
16
+Output.ReplayBuffer.NoHotkey.Msg="Tecla de Atalho para salvar o Buffer do replay não definida. Por favor, configure uma tecla de atalho para salvar gravações de replays."
17
18
Output.BadPath.Title="Caminho de Arquivo Inválido"
19
Output.BadPath.Text="O caminho do arquivo de saída é inválido. Por Favor, certifique-se de que um caminho válido foi informado."
20
21
ScaleFiltering.Point="Ponto"
22
ScaleFiltering.Bilinear="Bilinear"
23
ScaleFiltering.Bicubic="Bicúbico"
24
+ScaleFiltering.Lanczos="Lanczos"
25
26
Deinterlacing="Desentrelaçamento"
27
Deinterlacing.Discard="Descartar"
28
29
Basic.Main.Sources="Fontes"
30
Basic.Main.Connecting="Conectando..."
31
Basic.Main.StartRecording="Iniciar gravação"
32
+Basic.Main.StartReplayBuffer="Iniciar Buffer do Replay"
33
Basic.Main.StartStreaming="Iniciar Transmissão"
34
Basic.Main.StopRecording="Parar Gravação"
35
Basic.Main.StoppingRecording="Parando de Gravar..."
36
+Basic.Main.StopReplayBuffer="Parar Buffer do Replay"
37
+Basic.Main.StoppingReplayBuffer="Parando Buffer do Replay..."
38
Basic.Main.StopStreaming="Parar Transmissão"
39
Basic.Main.StoppingStreaming="Parando Transmissão..."
40
Basic.Main.ForceStopStreaming="Pare de transmitir (descartar atraso)"
41
42
Basic.MainMenu.Edit.Scale.Output="Saída (%1x%2)"
43
Basic.MainMenu.Edit.Transform="&Transformar"
44
Basic.MainMenu.Edit.Transform.EditTransform="&Editar Transformação..."
45
+Basic.MainMenu.Edit.Transform.CopyTransform="Copiar Transformação"
46
+Basic.MainMenu.Edit.Transform.PasteTransform="Colar Transformação"
47
Basic.MainMenu.Edit.Transform.ResetTransform="&Limpar Transformação"
48
Basic.MainMenu.Edit.Transform.Rotate90CW="Girar 90º sentido Horário"
49
Basic.MainMenu.Edit.Transform.Rotate90CCW="Girar 90º sentido Anti-Horário"
50
51
52
Basic.MainMenu.SceneCollection="&Coleção de cena"
53
Basic.MainMenu.Profile="&Perfil"
54
+Basic.MainMenu.Profile.Import="Importar Perfil"
55
+Basic.MainMenu.Profile.Export="Exportar Perfil"
56
+Basic.MainMenu.SceneCollection.Import="Importar Grupo de Cenas"
57
+Basic.MainMenu.SceneCollection.Export="Exportar Grupo de Cenas"
58
+Basic.MainMenu.Profile.Exists="Perfil já existe"
59
+Basic.MainMenu.SceneCollection.Exists="O Grupo de Cenas já existe"
60
61
Basic.MainMenu.Tools="Ferramentas (&T)"
62
63
64
Basic.Settings.Output.Mode.Simple="Simples"
65
Basic.Settings.Output.Mode.Adv="Avançado"
66
Basic.Settings.Output.Mode.FFmpeg="Saída de FFmpeg"
67
+Basic.Settings.Output.UseReplayBuffer="Habilitar Buffer de Repetição"
68
+Basic.Settings.Output.ReplayBuffer.SecondsMax="Tempo de Replay máximo (Segundos)"
69
+Basic.Settings.Output.ReplayBuffer.MegabytesMax="Memória Máxima (Megabytes)"
70
+Basic.Settings.Output.ReplayBuffer.Estimate="Uso de memória estimado: %1 MB"
71
+Basic.Settings.Output.ReplayBuffer.EstimateUnknown="Impossível estimar o uso de memória. Por favor, defina o limite máximo de memória."
72
+Basic.Settings.Output.ReplayBuffer.HotkeyMessage="(Nota: Não se esqueça de configurar uma Tecla de Atalho para o Buffer de Replay na seção Teclas de Atalhos)"
73
+Basic.Settings.Output.ReplayBuffer.Prefix="Prefixo do Buffer de Repetição"
74
+Basic.Settings.Output.ReplayBuffer.Suffix="Sufixo"
75
Basic.Settings.Output.Simple.SavePath="Caminho de gravação"
76
Basic.Settings.Output.Simple.RecordingQuality="Qualidade da gravação"
77
Basic.Settings.Output.Simple.RecordingQuality.Stream="Mesmo que a stream"
78
79
Basic.Settings.Output.Adv.Audio.Track2="Faixa 2"
80
Basic.Settings.Output.Adv.Audio.Track3="Faixa 3"
81
Basic.Settings.Output.Adv.Audio.Track4="Faixa 4"
82
+Basic.Settings.Output.Adv.Audio.Track5="Faixa 5"
83
+Basic.Settings.Output.Adv.Audio.Track6="Faixa 6"
84
85
Basic.Settings.Output.Adv.Recording="Gravação"
86
Basic.Settings.Output.Adv.Recording.Type="Tipo"
87
obs-studio-0.17.0.tar.xz/UI/data/locale/ru-RU.ini -> obs-studio-17.0.1.tar.xz/UI/data/locale/ru-RU.ini
Changed
83
1
2
Hours="Часов"
3
Minutes="Минут"
4
Seconds="Секунд"
5
+Deprecated="Устаревшее"
6
+ReplayBuffer="Буфер повтора"
7
+Import="Импорт"
8
+Export="Экспорт"
9
10
QuickTransitions.SwapScenes="Замена Просмотра/Вывода Сцены После Перехода"
11
QuickTransitions.SwapScenesTT="Замена просмотра и вывода сцены после перехода (если выходная оригинальная сцена до сих пор существует).\nЭто будет не отмена каких-либо изменений, что, возможно, было сделано в выходной оригинальной сцены."
12
13
Output.RecordError.Title="Ошибка записи"
14
Output.RecordError.Msg="Во время записи произошла неопознанная ошибка."
15
Output.ReplayBuffer.NoHotkey.Title="Нет набора горячих клавиш!"
16
+Output.ReplayBuffer.NoHotkey.Msg="Не установлено клавиши для сохранения повтора. Пожалуйста, установите горячую клавишу для сохранения записей повторов."
17
18
Output.BadPath.Title="Неправильный путь к файлу"
19
Output.BadPath.Text="Некорректный путь к файлу. Пожалуйста, проверьте настройки, чтобы убедиться в корректности установленного пути."
20
21
Basic.Main.Sources="Источники"
22
Basic.Main.Connecting="Соединение..."
23
Basic.Main.StartRecording="Начать запись"
24
+Basic.Main.StartReplayBuffer="Запустить повтор"
25
Basic.Main.StartStreaming="Запустить трансляцию"
26
Basic.Main.StopRecording="Остановить запись"
27
Basic.Main.StoppingRecording="Остановка Записи..."
28
+Basic.Main.StopReplayBuffer="Остановить повтор"
29
+Basic.Main.StoppingReplayBuffer="Остановка повтора..."
30
Basic.Main.StopStreaming="Остановить трансляцию"
31
Basic.Main.StoppingStreaming="Остановка вещания..."
32
Basic.Main.ForceStopStreaming="Остановить передачу (отменить задержку)"
33
34
Basic.MainMenu.Edit.LockPreview="&Заблокировать предпросмотр"
35
Basic.MainMenu.Edit.Scale="Просмотр и масштабирование"
36
Basic.MainMenu.Edit.Scale.Window="Масштаб окна"
37
+Basic.MainMenu.Edit.Scale.Canvas="Холст (%1x%2)"
38
+Basic.MainMenu.Edit.Scale.Output="Вывод (%1x%2)"
39
Basic.MainMenu.Edit.Transform="&Преобразовать"
40
Basic.MainMenu.Edit.Transform.EditTransform="&Изменить преобразование..."
41
+Basic.MainMenu.Edit.Transform.CopyTransform="Копировать преобразование"
42
+Basic.MainMenu.Edit.Transform.PasteTransform="Вставить преобразование"
43
Basic.MainMenu.Edit.Transform.ResetTransform="&Сбросить преобразование"
44
Basic.MainMenu.Edit.Transform.Rotate90CW="Повернуть на 90 градусов по часовой"
45
Basic.MainMenu.Edit.Transform.Rotate90CCW="Повернуть на 90 градусов против часовой"
46
47
48
Basic.MainMenu.SceneCollection="Коллекция сцен"
49
Basic.MainMenu.Profile="Профиль"
50
+Basic.MainMenu.Profile.Import="Импортировать профиль"
51
+Basic.MainMenu.Profile.Export="Экспортировать профиль"
52
+Basic.MainMenu.SceneCollection.Import="Импортировать коллекцию сцен"
53
+Basic.MainMenu.SceneCollection.Export="Экспортировать коллекцию сцен"
54
+Basic.MainMenu.Profile.Exists="Профиль уже существует"
55
+Basic.MainMenu.SceneCollection.Exists="Коллекция сцен уже существует"
56
57
Basic.MainMenu.Tools="&Инструменты"
58
59
60
Basic.Settings.Output.Mode.Simple="Простой"
61
Basic.Settings.Output.Mode.Adv="Расширенные"
62
Basic.Settings.Output.Mode.FFmpeg="Вывод FFmpeg"
63
+Basic.Settings.Output.UseReplayBuffer="Включить Буфер повтора"
64
+Basic.Settings.Output.ReplayBuffer.SecondsMax="Максимальное время повтора (секунд)"
65
+Basic.Settings.Output.ReplayBuffer.MegabytesMax="Максимальный объем памяти (МБ)"
66
Basic.Settings.Output.ReplayBuffer.Estimate="Предполагаемое использование памяти: %1 МБ"
67
Basic.Settings.Output.ReplayBuffer.EstimateUnknown="Невозможно оценить использование памяти. Пожалуйста, установите максимальный объем памяти."
68
+Basic.Settings.Output.ReplayBuffer.HotkeyMessage="(Примечание: Убедитесь, что установили горячую клавишу для воспроизведения буфера в разделе горячие клавиши)"
69
+Basic.Settings.Output.ReplayBuffer.Prefix="Префикс имени файла повтора"
70
+Basic.Settings.Output.ReplayBuffer.Suffix="Суффикс"
71
Basic.Settings.Output.Simple.SavePath="Путь к записи"
72
Basic.Settings.Output.Simple.RecordingQuality="Качество записи"
73
Basic.Settings.Output.Simple.RecordingQuality.Stream="То же, что у трансляции"
74
75
Basic.Settings.Output.Adv.Audio.Track2="Дорожка 2"
76
Basic.Settings.Output.Adv.Audio.Track3="Дорожка 3"
77
Basic.Settings.Output.Adv.Audio.Track4="Дорожка 4"
78
+Basic.Settings.Output.Adv.Audio.Track5="Дорожка 5"
79
+Basic.Settings.Output.Adv.Audio.Track6="Дорожка 6"
80
81
Basic.Settings.Output.Adv.Recording="Запись"
82
Basic.Settings.Output.Adv.Recording.Type="Тип"
83
obs-studio-0.17.0.tar.xz/UI/data/locale/sv-SE.ini -> obs-studio-17.0.1.tar.xz/UI/data/locale/sv-SE.ini
Changed
78
1
2
Minutes="minuter"
3
Seconds="sekunder"
4
Deprecated="Föråldrat"
5
+ReplayBuffer="Reprisbuffert"
6
+Import="Importera"
7
+Export="Exportera"
8
9
QuickTransitions.SwapScenes="Byt plats på Förhandsvisnings-/utdatascenerna efter skifte"
10
QuickTransitions.SwapScenesTT="Byter plats på förhandsvisnings- och utdatascenerna efter övergång (om utdatans originalscen fortfarande finns). \nDet här kommer inte att ångra några förändringar i utdatans originalscen."
11
12
Output.RecordError.Title="Inspelningsfel"
13
Output.RecordError.Msg="Ett okänt fel uppstod vid inspelning."
14
Output.ReplayBuffer.NoHotkey.Title="Ingen angivet kortkommando!"
15
+Output.ReplayBuffer.NoHotkey.Msg="Inget kortkommando för att spara reprisbufferten har angivits. Ange kortkommandot \"Spara\" för att kunna spara reprisinspelningar."
16
17
Output.BadPath.Title="Ogiltig sökväg"
18
Output.BadPath.Text="Den angivna sökvägen för utmatningsfil är ogiltig. Kontrollera att dina inställningar är korrekta och att en giltig sökväg har angetts."
19
20
Basic.Main.Sources="Källor"
21
Basic.Main.Connecting="Ansluter..."
22
Basic.Main.StartRecording="Starta inspelning"
23
+Basic.Main.StartReplayBuffer="Starta reprisbuffert"
24
Basic.Main.StartStreaming="Börja strömma"
25
Basic.Main.StopRecording="Stoppa inspelning"
26
Basic.Main.StoppingRecording="Stoppar inspelning..."
27
+Basic.Main.StopReplayBuffer="Stoppa reprisbuffert"
28
+Basic.Main.StoppingReplayBuffer="Stoppar reprisbuffert..."
29
Basic.Main.StopStreaming="Sluta strömma"
30
Basic.Main.StoppingStreaming="Stoppar ström..."
31
Basic.Main.ForceStopStreaming="Sluta strömma (ignorera fördröjning)"
32
33
Basic.MainMenu.Edit.Scale.Output="Utmatning (%1x%2)"
34
Basic.MainMenu.Edit.Transform="&Omvandla"
35
Basic.MainMenu.Edit.Transform.EditTransform="&Redigera omvandling..."
36
+Basic.MainMenu.Edit.Transform.CopyTransform="Kopiera transformering"
37
+Basic.MainMenu.Edit.Transform.PasteTransform="Klistra in transformering"
38
Basic.MainMenu.Edit.Transform.ResetTransform="&Återställ omvandling"
39
Basic.MainMenu.Edit.Transform.Rotate90CW="Rotera 90 grader medsols &>"
40
Basic.MainMenu.Edit.Transform.Rotate90CCW="Rotera 90 grader motsols &<"
41
42
43
Basic.MainMenu.SceneCollection="&Scensamling"
44
Basic.MainMenu.Profile="&Profil"
45
+Basic.MainMenu.Profile.Import="Importera profil"
46
+Basic.MainMenu.Profile.Export="Exportera profil"
47
+Basic.MainMenu.SceneCollection.Import="Importera scensamling"
48
+Basic.MainMenu.SceneCollection.Export="Exportera scensamling"
49
+Basic.MainMenu.Profile.Exists="Profilen finns redan"
50
+Basic.MainMenu.SceneCollection.Exists="Scensamlingen finns redan"
51
52
Basic.MainMenu.Tools="&Verktyg"
53
54
55
Basic.Settings.Output.Mode.Simple="Simpel"
56
Basic.Settings.Output.Mode.Adv="Avancerat"
57
Basic.Settings.Output.Mode.FFmpeg="FFmpeg-utmatning"
58
+Basic.Settings.Output.UseReplayBuffer="Aktivera reprisbuffert"
59
+Basic.Settings.Output.ReplayBuffer.SecondsMax="Maximal repristid (sekunder)"
60
Basic.Settings.Output.ReplayBuffer.MegabytesMax="Maximalt minne (Megabyte)"
61
Basic.Settings.Output.ReplayBuffer.Estimate="Uppskattad minnesanvändning: %1 MB"
62
+Basic.Settings.Output.ReplayBuffer.EstimateUnknown="Kan inte uppskatta minnesanvändningen. Ange maximal minnesgräns."
63
+Basic.Settings.Output.ReplayBuffer.HotkeyMessage="(OBS: Se till att ange ett kortkommando för reprisbufferten i avsnittet för kortkommandon)"
64
+Basic.Settings.Output.ReplayBuffer.Prefix="Filnamnsprefix för reprisbuffert"
65
+Basic.Settings.Output.ReplayBuffer.Suffix="Suffix"
66
Basic.Settings.Output.Simple.SavePath="Inspelningssökväg"
67
Basic.Settings.Output.Simple.RecordingQuality="Inspelningskvalitet"
68
Basic.Settings.Output.Simple.RecordingQuality.Stream="Samma som ström"
69
70
Basic.Settings.Output.Adv.Audio.Track2="Spår 2"
71
Basic.Settings.Output.Adv.Audio.Track3="Spår 3"
72
Basic.Settings.Output.Adv.Audio.Track4="Spår 4"
73
+Basic.Settings.Output.Adv.Audio.Track5="Spår 5"
74
+Basic.Settings.Output.Adv.Audio.Track6="Spår 6"
75
76
Basic.Settings.Output.Adv.Recording="Inspelning"
77
Basic.Settings.Output.Adv.Recording.Type="Typ"
78
obs-studio-0.17.0.tar.xz/UI/data/locale/tr-TR.ini -> obs-studio-17.0.1.tar.xz/UI/data/locale/tr-TR.ini
Changed
36
1
2
Duplicate="Çoğalt"
3
Enable="Etkinleştir"
4
DisableOSXVSync="OSX V-Sync Devre Dışı Bırakma"
5
+ResetOSXVSyncOnExit="OSX V-Sync'i Çıkışta Sıfırla"
6
HighResourceUsage="Kodlama aşırı yüklendi! Video ayarlarını kapatmayı veya daha hızlı bir kodlama ön ayarını kullanmayı düşünün."
7
Transition="Geçiş"
8
QuickTransitions="Hızlı Geçiş"
9
10
Basic.Main.AddSceneDlg.Title="Sahne Ekle"
11
Basic.Main.AddSceneDlg.Text="Lütfen sahne adını giriniz"
12
13
-Basic.Main.DefaultSceneName.Text="%1 Sahnesi"
14
+Basic.Main.DefaultSceneName.Text="Sahne %1"
15
16
Basic.Main.AddSceneCollection.Title="Sahne Koleksiyonu Ekle"
17
Basic.Main.AddSceneCollection.Text="Sahne koleksiyonunun isimini giriniz"
18
19
Basic.Settings.Video.CurrentlyActive="Video çıkışı şu anda etkin durumda. Video ayarlarını değiştirmek için lütfen bütün çıkışları kapalı duruma getirin."
20
Basic.Settings.Video.DisableAero="Aero'yu Devre Dışı Bırak"
21
22
+Basic.Settings.Video.DownscaleFilter.Bilinear="Bilinear (En hızlı, ancak boyutlandırmada bulanık görüntü)"
23
+Basic.Settings.Video.DownscaleFilter.Bicubic="Bicubic (Keskinleştirilmiş boyutlandırma, 16 örnek)"
24
+Basic.Settings.Video.DownscaleFilter.Lanczos="Lanczos (Keskinleştirilmiş boyutlandırma, 32 örnek)"
25
26
Basic.Settings.Audio="Ses"
27
Basic.Settings.Audio.SampleRate="Örnekleme Sıklığı"
28
29
30
Mute="Sesi Kapat"
31
Unmute="Sesi Aç"
32
+Push-to-mute="Bas-Sessize Al"
33
Push-to-talk="Bas konuş"
34
35
SceneItemShow="'%1' Göster"
36
obs-studio-0.17.0.tar.xz/UI/data/locale/uk-UA.ini -> obs-studio-17.0.1.tar.xz/UI/data/locale/uk-UA.ini
Changed
32
1
2
Basic.MainMenu.Edit.Scale.Output="Як Вивід (%1x%2)"
3
Basic.MainMenu.Edit.Transform="&Розміри"
4
Basic.MainMenu.Edit.Transform.EditTransform="Редагуват&и Розміри..."
5
+Basic.MainMenu.Edit.Transform.CopyTransform="Копіювати Розміри"
6
+Basic.MainMenu.Edit.Transform.PasteTransform="Вставити Розміри"
7
Basic.MainMenu.Edit.Transform.ResetTransform="Розміри за &замовчуванням"
8
Basic.MainMenu.Edit.Transform.Rotate90CW="Повернути на 90 За годинниковою стрілкою"
9
Basic.MainMenu.Edit.Transform.Rotate90CCW="Повернути на 90 Проти годинникової стрілки"
10
11
12
Basic.MainMenu.SceneCollection="&Набір Сцен"
13
Basic.MainMenu.Profile="&Профіль"
14
+Basic.MainMenu.Profile.Import="Імпорт Профілю"
15
+Basic.MainMenu.Profile.Export="Експорт Профілю"
16
+Basic.MainMenu.SceneCollection.Import="Імпорт Набору Сцен"
17
+Basic.MainMenu.SceneCollection.Export="Експорт Набору Сцен"
18
+Basic.MainMenu.Profile.Exists="Профіль вже існує"
19
+Basic.MainMenu.SceneCollection.Exists="Набір Сцен вже існує"
20
21
Basic.MainMenu.Tools="Додаткові &засоби"
22
23
24
Basic.Settings.Output.Adv.Audio.Track2="Доріжка 2"
25
Basic.Settings.Output.Adv.Audio.Track3="Доріжка 3"
26
Basic.Settings.Output.Adv.Audio.Track4="Доріжка 4"
27
+Basic.Settings.Output.Adv.Audio.Track5="Доріжка 5"
28
+Basic.Settings.Output.Adv.Audio.Track6="Доріжка 6"
29
30
Basic.Settings.Output.Adv.Recording="Запис"
31
Basic.Settings.Output.Adv.Recording.Type="Тип"
32
obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/ca-ES.ini -> obs-studio-17.0.1.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/ca-ES.ini
Changed
17
1
2
Start="Inicia"
3
Stop="Atura"
4
5
+Captions="Subtítols (Experimental)"
6
+Captions.AudioSource="Font d'àudio"
7
+Captions.CurrentSystemLanguage="Idioma actual del sistema (%1)"
8
9
OutputTimer="Temporitzador de sortida"
10
OutputTimer.Stream="Atura la transmissió després de:"
11
OutputTimer.Record="Atura la gravació després de:"
12
OutputTimer.Stream.StoppingIn="La transmissió s'aturarà en:"
13
OutputTimer.Record.StoppingIn="La gravació s'aturarà en:"
14
+OutputTimer.Stream.EnableEverytime="Activa el temporitzador en cada transmissió"
15
+OutputTimer.Record.EnableEverytime="Activa el temporitzador en cada enregistrament"
16
17
obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/cs-CZ.ini -> obs-studio-17.0.1.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/cs-CZ.ini
Changed
11
1
2
Start="Spustit"
3
Stop="Zastavit"
4
5
+Captions="Titulky (experiment.)"
6
+Captions.AudioSource="Zdroj zvuku"
7
+Captions.CurrentSystemLanguage="Aktuální systémový jazyk (%1)"
8
9
OutputTimer="Časovač"
10
OutputTimer.Stream="Přestat vysílat po:"
11
obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/de-DE.ini -> obs-studio-17.0.1.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/de-DE.ini
Changed
11
1
2
Stop="Stop"
3
4
Captions="Untertitel (experimentell)"
5
-Captions.AudioSource="Audioquelle:"
6
+Captions.AudioSource="Audioquelle"
7
+Captions.CurrentSystemLanguage="Aktuelle Systemsprache (%1)"
8
9
OutputTimer="Ausgabetimer"
10
OutputTimer.Stream="Stoppe Stream nach:"
11
obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/es-ES.ini -> obs-studio-17.0.1.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/es-ES.ini
Changed
11
1
2
Start="Iniciar"
3
Stop="Detener"
4
5
+Captions="Subtítulos (Experimental)"
6
+Captions.AudioSource="Fuente de audio"
7
+Captions.CurrentSystemLanguage="Idioma actual del sistema (%1)"
8
9
OutputTimer="Temporizador de salida"
10
OutputTimer.Stream="Detener la transmisión después de:"
11
obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/eu-ES.ini -> obs-studio-17.0.1.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/eu-ES.ini
Changed
11
1
2
Start="Hasi"
3
Stop="Gelditu"
4
5
+Captions="Epigrafeak (esperimentala)"
6
+Captions.AudioSource="Audio-iturburua"
7
+Captions.CurrentSystemLanguage="Sistemaren hizkuntza (%1)"
8
9
OutputTimer="Irteera tenporizadorea"
10
OutputTimer.Stream="Gelditu transmisioa hau pasata:"
11
obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/fi-FI.ini -> obs-studio-17.0.1.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/fi-FI.ini
Changed
11
1
2
Start="Käynnistä"
3
Stop="Pysäytä"
4
5
+Captions="Kuvatekstit (Experimental)"
6
+Captions.AudioSource="Äänilähde"
7
+Captions.CurrentSystemLanguage="Järjestelmän kieli (%1)"
8
9
OutputTimer="Ulostulo-ajastin"
10
OutputTimer.Stream="Pysäyttää lähetyksen:"
11
obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/fr-FR.ini -> obs-studio-17.0.1.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/fr-FR.ini
Changed
11
1
2
Start="Démarrer"
3
Stop="Arrêter"
4
5
+Captions="Sous-titres (expérimental)"
6
+Captions.AudioSource="Source audio"
7
+Captions.CurrentSystemLanguage="Langue du système (%1)"
8
9
OutputTimer="Minuterie des sorties"
10
OutputTimer.Stream="Arrêter le streaming dans :"
11
obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/hu-HU.ini -> obs-studio-17.0.1.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/hu-HU.ini
Changed
11
1
2
Start="Start"
3
Stop="Stop"
4
5
+Captions="Feliratok (Kísérleti)"
6
+Captions.AudioSource="Audio forrás"
7
+Captions.CurrentSystemLanguage="Rendszer aktuális nyelve (%1)"
8
9
OutputTimer="Kimeneti időzítő"
10
OutputTimer.Stream="Stream leállítása:"
11
obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/it-IT.ini -> obs-studio-17.0.1.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/it-IT.ini
Changed
17
1
2
Start="Inizio"
3
Stop="Stop"
4
5
+Captions="Sottotitoli (Sperimentale)"
6
+Captions.AudioSource="Fonte audio"
7
+Captions.CurrentSystemLanguage="Lingua del sistema in uso (%1)"
8
9
OutputTimer="Timer Output"
10
OutputTimer.Stream="Termina diretta dopo:"
11
OutputTimer.Record="Termina registrazione dopo:"
12
OutputTimer.Stream.StoppingIn="La diretta terminerà in:"
13
OutputTimer.Record.StoppingIn="La registrazione terminerà in:"
14
+OutputTimer.Stream.EnableEverytime="Abilita il timer per lo streaming ogni volta"
15
+OutputTimer.Record.EnableEverytime="Abilita il timer per la registrazione ogni volta"
16
17
obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/ja-JP.ini -> obs-studio-17.0.1.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/ja-JP.ini
Changed
11
1
2
Start="開始"
3
Stop="停止"
4
5
+Captions="見出し (実験的)"
6
+Captions.AudioSource="音声ソース"
7
+Captions.CurrentSystemLanguage="現在のシステム言語 (%1)"
8
9
OutputTimer="出力タイマー"
10
OutputTimer.Stream="配信停止の時間設定:"
11
obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/ko-KR.ini -> obs-studio-17.0.1.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/ko-KR.ini
Changed
11
1
2
Start="시작"
3
Stop="중단"
4
5
+Captions="자막 (실험적 기능)"
6
+Captions.AudioSource="오디오 소스"
7
+Captions.CurrentSystemLanguage="현재 시스템 언어 (%1)"
8
9
OutputTimer="출력 시간 설정"
10
OutputTimer.Stream="이 시간 이후 방송 중단:"
11
obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/nl-NL.ini -> obs-studio-17.0.1.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/nl-NL.ini
Changed
11
1
2
Start="Start"
3
Stop="Stop"
4
5
+Captions="Ondertiteling (Experimenteel)"
6
+Captions.AudioSource="Audiobron"
7
+Captions.CurrentSystemLanguage="Huidige Systeemtaal (%1)"
8
9
OutputTimer="Uitvoertimer"
10
OutputTimer.Stream="Stop met streamen na:"
11
obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/pl-PL.ini -> obs-studio-17.0.1.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/pl-PL.ini
Changed
11
1
2
Start="Start"
3
Stop="Stop"
4
5
+Captions="Podpisy (eksperymentalne)"
6
+Captions.AudioSource="Źródła dźwięku"
7
+Captions.CurrentSystemLanguage="Obecny język systemu (%1)"
8
9
OutputTimer="Wyłącznik czasowy"
10
OutputTimer.Stream="Zatrzymaj stream po:"
11
obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/ru-RU.ini -> obs-studio-17.0.1.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/ru-RU.ini
Changed
11
1
2
Start="Запустить"
3
Stop="Остановить"
4
5
+Captions="Субтитры (экспериментально)"
6
+Captions.AudioSource="Источник звука"
7
+Captions.CurrentSystemLanguage="Текущий язык системы (%1)"
8
9
OutputTimer="Таймер записи и стрима"
10
OutputTimer.Stream="Завершить стрим через:"
11
obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/sv-SE.ini -> obs-studio-17.0.1.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/sv-SE.ini
Changed
11
1
2
Start="Starta"
3
Stop="Stoppa"
4
5
+Captions="Undertexter (experimentell)"
6
+Captions.AudioSource="Ljudkälla"
7
+Captions.CurrentSystemLanguage="Aktuellt systemspråk (%1)"
8
9
OutputTimer="Utdatatimer"
10
OutputTimer.Stream="Sluta streama efter:"
11
obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/tr-TR.ini -> obs-studio-17.0.1.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/tr-TR.ini
Changed
27
1
2
SceneSwitcher="Otomatik Sahne Değiştirici"
3
+SceneSwitcher.OnNoMatch="Hiçbir pencere ile eşleşmez ise:"
4
SceneSwitcher.OnNoMatch.DontSwitch="Geçiş yapma"
5
SceneSwitcher.OnNoMatch.SwitchTo="Şuna geç:"
6
SceneSwitcher.CheckInterval="Etkin pencere başlığını kontrol et:"
7
SceneSwitcher.ActiveOrNotActive="Sahne Değiştirici:"
8
+InvalidRegex.Title="Geçersiz Kurallı İfade"
9
+InvalidRegex.Text="Girdiğiniz kurallı ifade geçersiz."
10
Active="Etkin"
11
Inactive="Devre Dışı"
12
Start="Başlat"
13
Stop="Durdur"
14
15
+Captions="Altyazı (Deneysel)"
16
+Captions.AudioSource="Ses kaynağı"
17
+Captions.CurrentSystemLanguage="Geçerli Sistem Dili (%1)"
18
19
OutputTimer="Çıkış Zamanlayıcısı"
20
OutputTimer.Stream="Şuradan sonra yayını durdur:"
21
OutputTimer.Record="Şuradan sonra kaydı durdur:"
22
+OutputTimer.Stream.StoppingIn="Yayın durduruluyor:"
23
+OutputTimer.Record.StoppingIn="Kayıt durduruluyor:"
24
OutputTimer.Stream.EnableEverytime="Her zaman yayın zamanlayıcıyı etkinleştir"
25
OutputTimer.Record.EnableEverytime="Her zaman kayıt zamanlayıcıyı etkinleştir"
26
27
obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/uk-UA.ini -> obs-studio-17.0.1.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/uk-UA.ini
Changed
11
1
2
Start="Запустити"
3
Stop="Зупинити"
4
5
+Captions="Субтитри (експериментально)"
6
+Captions.AudioSource="Джерело Аудіо"
7
+Captions.CurrentSystemLanguage="Поточна мова Системи (%1)"
8
9
OutputTimer="Таймер для Виводу"
10
OutputTimer.Stream="Закінчити трансляцію за:"
11
obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/zh-CN.ini -> obs-studio-17.0.1.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/zh-CN.ini
Changed
11
1
2
Start="开始"
3
Stop="停止"
4
5
+Captions="标题(实验)"
6
+Captions.AudioSource="音频源"
7
+Captions.CurrentSystemLanguage="当前系统语言 (%1)"
8
9
OutputTimer="输出计时器"
10
OutputTimer.Stream="停止流处理后:"
11
obs-studio-0.17.0.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/zh-TW.ini -> obs-studio-17.0.1.tar.xz/UI/frontend-plugins/frontend-tools/data/locale/zh-TW.ini
Changed
11
1
2
Start="開始"
3
Stop="停止"
4
5
+Captions="標題 (實驗)"
6
+Captions.AudioSource="音訊源"
7
+Captions.CurrentSystemLanguage="目前系統語言 (%1)"
8
9
OutputTimer="輸出計時器"
10
OutputTimer.Stream="在下面時間後停止串流:"
11
obs-studio-0.17.0.tar.xz/UI/window-basic-main-profiles.cpp -> obs-studio-17.0.1.tar.xz/UI/window-basic-main-profiles.cpp
Changed
23
1
2
profileDir + "/basic.ini");
3
QFile::copy(dir + "/service.json",
4
profileDir + "/service.json");
5
+ QFile::copy(dir + "/streamEncoder.json",
6
+ profileDir + "/streamEncoder.json");
7
+ QFile::copy(dir + "/recordEncoder.json",
8
+ profileDir + "/recordEncoder.json");
9
RefreshProfiles();
10
} else {
11
QMessageBox::information(this,
12
13
outputDir + "/basic.ini");
14
QFile::copy(inputPath + currentProfile + "/service.json",
15
outputDir + "/service.json");
16
+ QFile::copy(inputPath + currentProfile + "/streamEncoder.json",
17
+ outputDir + "/streamEncoder.json");
18
+ QFile::copy(inputPath + currentProfile + "/recordEncoder.json",
19
+ outputDir + "/recordEncoder.json");
20
}
21
}
22
}
23
obs-studio-0.17.0.tar.xz/cmake/Modules/CopyMSVCBins.cmake -> obs-studio-17.0.1.tar.xz/cmake/Modules/CopyMSVCBins.cmake
Changed
14
1
2
set(_bin_suffix 32)
3
endif()
4
5
-find_package(Libavcodec QUIET)
6
-find_package(Libx264 QUIET)
7
-find_package(Libfdk QUIET)
8
-find_package(ssl QUIET)
9
-find_package(Qt5Core QUIET)
10
-
11
file(GLOB FFMPEG_BIN_FILES
12
"${FFMPEG_avcodec_INCLUDE_DIR}/../bin/avcodec-*.dll"
13
"${FFMPEG_avcodec_INCLUDE_DIR}/../bin${_bin_suffix}/avcodec-*.dll"
14
obs-studio-0.17.0.tar.xz/deps/libff/libff/ff-demuxer.c -> obs-studio-17.0.1.tar.xz/deps/libff/libff/ff-demuxer.c
Changed
16
1
2
}
3
4
if (codec == NULL) {
5
- codec = avcodec_find_decoder(codec_context->codec_id);
6
+ if (codec_context->codec_id == AV_CODEC_ID_VP8)
7
+ codec = avcodec_find_decoder_by_name("libvpx");
8
+ else if (codec_context->codec_id == AV_CODEC_ID_VP9)
9
+ codec = avcodec_find_decoder_by_name("libvpx-vp9");
10
+
11
+ if (!codec)
12
+ codec = avcodec_find_decoder(codec_context->codec_id);
13
if (codec == NULL) {
14
av_log(NULL, AV_LOG_WARNING, "no decoder found for"
15
" codec with id %d",
16
obs-studio-0.17.0.tar.xz/libobs/obs-config.h -> obs-studio-17.0.1.tar.xz/libobs/obs-config.h
Changed
10
1
2
*
3
* Reset to zero each major or minor version
4
*/
5
-#define LIBOBS_API_PATCH_VER 0
6
+#define LIBOBS_API_PATCH_VER 1
7
8
#define MAKE_SEMANTIC_VERSION(major, minor, patch) \
9
((major << 24) | \
10
obs-studio-0.17.0.tar.xz/libobs/obs-scene.c -> obs-studio-17.0.1.tar.xz/libobs/obs-scene.c
Changed
59
1
2
3
static void scene_enum_sources(void *data,
4
obs_source_enum_proc_t enum_callback,
5
- void *param)
6
+ void *param, bool active)
7
{
8
struct obs_scene *scene = data;
9
struct obs_scene_item *item;
10
11
next = item->next;
12
13
obs_sceneitem_addref(item);
14
- if (os_atomic_load_long(&item->active_refs) > 0)
15
+ if (!active || os_atomic_load_long(&item->active_refs) > 0)
16
enum_callback(scene->source, item->source, param);
17
obs_sceneitem_release(item);
18
19
20
full_unlock(scene);
21
}
22
23
+static void scene_enum_active_sources(void *data,
24
+ obs_source_enum_proc_t enum_callback,
25
+ void *param)
26
+{
27
+ scene_enum_sources(data, enum_callback, param, true);
28
+}
29
+
30
+static void scene_enum_all_sources(void *data,
31
+ obs_source_enum_proc_t enum_callback,
32
+ void *param)
33
+{
34
+ scene_enum_sources(data, enum_callback, param, false);
35
+}
36
+
37
static inline void detach_sceneitem(struct obs_scene_item *item)
38
{
39
if (item->prev)
40
41
.get_height = scene_getheight,
42
.load = scene_load,
43
.save = scene_save,
44
- .enum_active_sources = scene_enum_sources
45
+ .enum_active_sources = scene_enum_active_sources,
46
+ .enum_all_sources = scene_enum_all_sources
47
};
48
49
obs_scene_t *obs_scene_create(const char *name)
50
51
new_item->align = item->align;
52
new_item->last_width = item->last_width;
53
new_item->last_height = item->last_height;
54
+ new_item->output_scale = item->output_scale;
55
+ new_item->scale_filter = item->scale_filter;
56
new_item->box_transform = item->box_transform;
57
new_item->draw_transform = item->draw_transform;
58
new_item->bounds_type = item->bounds_type;
59
obs-studio-0.17.0.tar.xz/libobs/obs-source.c -> obs-studio-17.0.1.tar.xz/libobs/obs-source.c
Changed
105
1
2
void *param;
3
};
4
5
-static void enum_source_tree_callback(obs_source_t *parent, obs_source_t *child,
6
- void *param)
7
+static void enum_source_active_tree_callback(obs_source_t *parent,
8
+ obs_source_t *child, void *param)
9
{
10
struct source_enum_data *data = param;
11
bool is_transition = child->info.type == OBS_SOURCE_TYPE_TRANSITION;
12
13
if (is_transition)
14
obs_transition_enum_sources(child,
15
- enum_source_tree_callback, param);
16
+ enum_source_active_tree_callback, param);
17
if (child->info.enum_active_sources) {
18
if (child->context.data) {
19
child->info.enum_active_sources(child->context.data,
20
- enum_source_tree_callback, data);
21
+ enum_source_active_tree_callback, data);
22
}
23
}
24
25
26
obs_source_addref(source);
27
28
if (source->info.type == OBS_SOURCE_TYPE_TRANSITION)
29
- obs_transition_enum_sources(source, enum_source_tree_callback,
30
- &data);
31
+ obs_transition_enum_sources(source,
32
+ enum_source_active_tree_callback, &data);
33
if (source->info.enum_active_sources)
34
source->info.enum_active_sources(source->context.data,
35
- enum_source_tree_callback, &data);
36
+ enum_source_active_tree_callback, &data);
37
+
38
+ obs_source_release(source);
39
+}
40
+
41
+static void enum_source_full_tree_callback(obs_source_t *parent,
42
+ obs_source_t *child, void *param)
43
+{
44
+ struct source_enum_data *data = param;
45
+ bool is_transition = child->info.type == OBS_SOURCE_TYPE_TRANSITION;
46
+
47
+ if (is_transition)
48
+ obs_transition_enum_sources(child,
49
+ enum_source_full_tree_callback, param);
50
+ if (child->info.enum_all_sources) {
51
+ if (child->context.data) {
52
+ child->info.enum_active_sources(child->context.data,
53
+ enum_source_full_tree_callback, data);
54
+ }
55
+ } else if (child->info.enum_active_sources) {
56
+ if (child->context.data) {
57
+ child->info.enum_active_sources(child->context.data,
58
+ enum_source_full_tree_callback, data);
59
+ }
60
+ }
61
+
62
+ data->enum_callback(parent, child, data->param);
63
+}
64
+
65
+static void obs_source_enum_full_tree(obs_source_t *source,
66
+ obs_source_enum_proc_t enum_callback,
67
+ void *param)
68
+{
69
+ struct source_enum_data data = {enum_callback, param};
70
+ bool is_transition;
71
+
72
+ if (!data_valid(source, "obs_source_enum_active_tree"))
73
+ return;
74
+
75
+ is_transition = source->info.type == OBS_SOURCE_TYPE_TRANSITION;
76
+ if (!is_transition && !source->info.enum_active_sources)
77
+ return;
78
+
79
+ obs_source_addref(source);
80
+
81
+ if (source->info.type == OBS_SOURCE_TYPE_TRANSITION)
82
+ obs_transition_enum_sources(source,
83
+ enum_source_full_tree_callback, &data);
84
+
85
+ if (source->info.enum_all_sources) {
86
+ source->info.enum_all_sources(source->context.data,
87
+ enum_source_full_tree_callback, &data);
88
+
89
+ } else if (source->info.enum_active_sources) {
90
+ source->info.enum_active_sources(source->context.data,
91
+ enum_source_full_tree_callback, &data);
92
+ }
93
94
obs_source_release(source);
95
}
96
97
return false;
98
}
99
100
- obs_source_enum_active_tree(child, check_descendant, &info);
101
+ obs_source_enum_full_tree(child, check_descendant, &info);
102
if (info.exists)
103
return false;
104
105
obs-studio-0.17.0.tar.xz/libobs/obs-source.h -> obs-studio-17.0.1.tar.xz/libobs/obs-source.h
Changed
23
1
2
bool (*audio_render)(void *data, uint64_t *ts_out,
3
struct obs_source_audio_mix *audio_output,
4
uint32_t mixers, size_t channels, size_t sample_rate);
5
+
6
+ /**
7
+ * Called to enumerate all active and inactive sources being used
8
+ * within this source. If this callback isn't implemented,
9
+ * enum_active_sources will be called instead.
10
+ *
11
+ * This is typically used if a source can have inactive child sources.
12
+ *
13
+ * @param data Filter data
14
+ * @param enum_callback Enumeration callback
15
+ * @param param User data to pass to callback
16
+ */
17
+ void (*enum_all_sources)(void *data,
18
+ obs_source_enum_proc_t enum_callback,
19
+ void *param);
20
};
21
22
EXPORT void obs_register_source_s(const struct obs_source_info *info,
23
obs-studio-0.17.0.tar.xz/plugins/coreaudio-encoder/data/locale/hu-HU.ini -> obs-studio-17.0.1.tar.xz/plugins/coreaudio-encoder/data/locale/hu-HU.ini
Changed
10
1
2
CoreAudioAAC="CoreAudio AAC kódoló"
3
-Bitrate="Bitráta"
4
+Bitrate="Bitsebesség"
5
AllowHEAAC="HE-AAC engedélyezése"
6
OutputSamplerate="Kimeneti mintavételráta"
7
-UseInputSampleRate="Beviteli (OBS) mintaráta használata (kilistázza a nem támogatott bitrátákat)"
8
+UseInputSampleRate="Beviteli (OBS) mintaráta használata (kilistázza a nem támogatott bitsebességeket)"
9
10
obs-studio-0.17.0.tar.xz/plugins/coreaudio-encoder/data/locale/tr-TR.ini -> obs-studio-17.0.1.tar.xz/plugins/coreaudio-encoder/data/locale/tr-TR.ini
Changed
7
1
2
Bitrate="Bit hızı"
3
AllowHEAAC="HE-ACC'ye izin ver"
4
OutputSamplerate="Çıkış örnek hızı"
5
+UseInputSampleRate="Giriş (OBS) Örnekleme Hızını Kullan (desteklenmeyen bit hızları listelenebilir)"
6
7
obs-studio-0.17.0.tar.xz/plugins/enc-amf/#Resources/PATCH_NOTES.md -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/#Resources/PATCH_NOTES.md
Changed
29
1
2
-# 1.4.3.4 - Crimson ReLive Compatibility Update (Hotfix 1)
3
-Crimson ReLive changed how the Full Range flag is applied, which caused the plugin to break since it expected another property there. This has been fixed and some log messages have been changed to also result in better readability for users and support.
4
+# 1.4.3.8 - Settings Transfer, Automatic VBV Buffer adjustment and Fixes (Hotfix 2)
5
+Another day, another new feature: this time it is transferring settings between versions, so that you will no longer use settings when a change to a setting is made. Since it only just now started tracking the config version, it will only work with settings created between 1.4.3.0 and 1.4.3.5, any other version might end up with broken settings.
6
7
-Hotfix 1: The Driver update also broke VBAQ, but it caused less issues than the Full Range flag. This has been fixed.
8
+Another change has been done to the Automatic VBV Buffer Size, which will now behave much more predictable. A value of 0% is completely unrestricted, 50% matches the calculated bitrate and 100% matches the calculated strict bitrate.
9
+
10
+Presets will also now use the proper minimum and maximum QP values and the minimum QP default value has been increased to 11.
11
+
12
+Hotfix 1: Fix enumeration based properties not working correctly due to a programming error.
13
+Hotfix 2: Actually fix the enumeration based properties for real this time.
14
15
## Changelog
16
-* Hotfix 1: Experimental Property VBAQ would not be properly set.
17
-* Hotfix 1: Runtime and Compiled Against version numbers were switched around.
18
-* Fixed: Experimental Full Range Color mode no longer causes encoding to fail. (Fixes #175)
19
-* Changed: Queue status log messages have been reduced to once per second instead of once per frame.
20
-* Changed: First submission log message now show the time in seconds instead of nanoseconds.
21
+* Added: Version-specific setting transfer code which should reduce the lost settings between updates.
22
+* Changed: VBV Buffer Strictness is now linear with three steps: 100000 (0%), Target Bitrate (50%) and Strict Target Bitrate (100%).
23
+* Changed: Default for Minimum QP is now 11.
24
+* Fixed: Presets not using the proper QP Minimum and Maximum.
25
+* Fixed: Startup log messages not showing proper error codes.
26
+* Hotfix: Fix enumeration based properties not using the correct values.
27
+* Hotfix: Fix the default value for B-Frame Pattern being '-1' due to an oversight in code.
28
\ No newline at end of file
29
obs-studio-0.17.0.tar.xz/plugins/enc-amf/CMakeLists.txt -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/CMakeLists.txt
Changed
10
1
2
SET(enc-amf_VERSION_MAJOR 1)
3
SET(enc-amf_VERSION_MINOR 4)
4
SET(enc-amf_VERSION_PATCH 3)
5
-SET(enc-amf_VERSION_BUILD 4)
6
+SET(enc-amf_VERSION_BUILD 8)
7
configure_file(
8
"${PROJECT_SOURCE_DIR}/#Resources/package.in.bat"
9
"${PROJECT_SOURCE_DIR}/#Resources/package.bat"
10
obs-studio-0.17.0.tar.xz/plugins/enc-amf/CONTRIBUTING.md -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/CONTRIBUTING.md
Changed
20
1
2
The plugin itself is made up of several sub-modules:
3
4
* AMF: amf.cpp, amf.h, amf-capabilities.cpp, amf-capabilities.h
5
+* Encoder: amf-encoder.cpp, amf-encoder.h
6
* H264: amf-h264.cpp, amf-h264.h, enc-h264.cpp, enc-h264.h
7
-* H265: amf-h265.cpp, amf-h265.h, enc-h265.cpp, enc-h265.h
8
* API: api-base.cpp, api-base.h
9
-* API-OGL: api-opengl.cpp, api-opengl.h
10
-* API-D3D9: api-d3d9.cpp, api-d3d9.h
11
-* API-D3D11: api-d3d11.cpp, api-d3d11.h
12
+* API-OpenGL: api-opengl.cpp, api-opengl.h
13
+* API-Direct3D9: api-d3d9.cpp, api-d3d9.h
14
+* API-Direct3D11: api-d3d11.cpp, api-d3d11.h
15
* API-Host: api-host.cpp, api-host.h
16
+* Plugin: plugin.cpp, plugin.h, CMakeLists.txt
17
* Utilities: misc-util.cpp
18
* Locale: Any locale files
19
* Resources: Any resource files
20
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Include/amf-capabilities.h -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Include/amf-capabilities.h
Changed
32
1
2
Plugin::API::Adapter adapter);
3
static void ReportAdapterTypeCapabilities(std::shared_ptr<Plugin::API::Base> api,
4
Plugin::API::Adapter adapter,
5
- VCEEncoderType type);
6
+ H264EncoderType type);
7
static void ReportAdapterTypeIOCapabilities(std::shared_ptr<Plugin::API::Base> api,
8
Plugin::API::Adapter adapter,
9
- VCEEncoderType type,
10
+ H264EncoderType type,
11
bool output);
12
13
//////////////////////////////////////////////////////////////////////////
14
15
~VCECapabilities();
16
17
bool Refresh();
18
- std::vector<std::pair<VCEEncoderType, VCEDeviceCapabilities>>
19
+ std::vector<std::pair<H264EncoderType, VCEDeviceCapabilities>>
20
GetAllAdapterCapabilities(std::shared_ptr<Plugin::API::Base> api, Plugin::API::Adapter adapter);
21
VCEDeviceCapabilities
22
- GetAdapterCapabilities(std::shared_ptr<Plugin::API::Base> api, Plugin::API::Adapter adapter, VCEEncoderType type);
23
+ GetAdapterCapabilities(std::shared_ptr<Plugin::API::Base> api, Plugin::API::Adapter adapter, H264EncoderType type);
24
25
private:
26
- std::map<std::tuple<std::string, Plugin::API::Adapter, Plugin::AMD::VCEEncoderType>, VCEDeviceCapabilities> capabilityMap;
27
+ std::map<std::tuple<std::string, Plugin::API::Adapter, Plugin::AMD::H264EncoderType>, VCEDeviceCapabilities> capabilityMap;
28
};
29
}
30
}
31
\ No newline at end of file
32
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Include/amf-h264.h -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Include/amf-h264.h
Changed
349
1
2
namespace Plugin {
3
namespace AMD {
4
// Internal Properties
5
- enum VCEEncoderType {
6
- VCEEncoderType_AVC, // Advanced Video Coding
7
- VCEEncoderType_SVC, // Scalable Video Coding
8
- VCEEncoderType_HEVC, // High-Efficiency Video Coding (Discovered in amfrt64.dll)
9
+ enum class H264EncoderType : uint8_t {
10
+ AVC = 0, // Advanced Video Coding
11
+ SVC, // Scalable Video Coding
12
+ HEVC, // High-Efficiency Video Coding (Discovered in amfrt64.dll)
13
};
14
- enum VCEMemoryType {
15
- VCEMemoryType_Host, // Host-Managed Memory
16
- VCEMemoryType_DirectX9, // DirectX9
17
- VCEMemoryType_DirectX11, // DirectX11
18
- VCEMemoryType_OpenGL, // OpenGL
19
+ enum class H264MemoryType : uint8_t {
20
+ Host = 0, // Host-Managed Memory
21
+ DirectX9, // DirectX9
22
+ DirectX11, // DirectX11
23
+ OpenGL, // OpenGL
24
};
25
- enum VCEColorFormat {
26
+ enum class H264ColorFormat : uint8_t {
27
// 4:2:0 Formats
28
- VCEColorFormat_NV12, // NV12
29
- VCEColorFormat_I420, // YUV 4:2:0
30
+ NV12 = 0, // NV12
31
+ I420, // YUV 4:2:0
32
// 4:2:2 Formats
33
- VCEColorFormat_YUY2,
34
+ YUY2,
35
// Uncompressed
36
- VCEColorFormat_BGRA, // ARGB
37
- VCEColorFormat_RGBA, // RGBA
38
+ BGRA, // ARGB
39
+ RGBA, // RGBA
40
// Other
41
- VCEColorFormat_GRAY,
42
+ GRAY, // Y 4:0:0
43
};
44
- enum VCEColorProfile {
45
- VCEColorProfile_601,
46
- VCEColorProfile_709,
47
- VCEColorProfile_2020, // HDR
48
+ enum class H264ColorProfile : uint8_t {
49
+ Rec601 = 0,
50
+ Rec709,
51
+ Rec2020, // Truer to world color, used for HDR
52
};
53
54
// Static Properties
55
- enum VCEUsage {
56
- VCEUsage_Transcoding,
57
- VCEUsage_UltraLowLatency,
58
- VCEUsage_LowLatency,
59
- VCEUsage_Webcam, // For SVC
60
+ enum class H264Usage : uint8_t {
61
+ Transcoding = 0, // Only one capable of streaming to services.
62
+ UltraLowLatency, // Low Latency Recording or Network Streaming
63
+ LowLatency, // Low Latency Recording or Network Streaming
64
+ Webcam, // For SVC Recording and Streaming
65
};
66
- enum VCEQualityPreset {
67
- VCEQualityPreset_Speed,
68
- VCEQualityPreset_Balanced,
69
- VCEQualityPreset_Quality,
70
+ enum class H264QualityPreset : uint8_t {
71
+ Speed = 0,
72
+ Balanced,
73
+ Quality,
74
};
75
- enum VCEProfile {
76
- VCEProfile_Baseline = 66,
77
- VCEProfile_Main = 77,
78
- VCEProfile_High = 100,
79
- VCEProfile_ConstrainedBaseline = 256,
80
- VCEProfile_ConstrainedHigh = 257
81
+ enum class H264Profile : uint16_t {
82
+ Baseline = 66,
83
+ Main = 77,
84
+ High = 100,
85
+ ConstrainedBaseline = 256,
86
+ ConstrainedHigh = 257
87
};
88
- enum VCEProfileLevel {
89
- VCEProfileLevel_Automatic = 0,
90
- VCEProfileLevel_10 = 10,
91
- VCEProfileLevel_11,
92
- VCEProfileLevel_12,
93
- VCEProfileLevel_13,
94
- VCEProfileLevel_20 = 20,
95
- VCEProfileLevel_21,
96
- VCEProfileLevel_22,
97
- VCEProfileLevel_30 = 30,
98
- VCEProfileLevel_31,
99
- VCEProfileLevel_32,
100
- VCEProfileLevel_40 = 40,
101
- VCEProfileLevel_41,
102
- VCEProfileLevel_42,
103
- VCEProfileLevel_50 = 50,
104
- VCEProfileLevel_51,
105
- VCEProfileLevel_52,
106
- VCEProfileLevel_60 = 60,
107
- VCEProfileLevel_61,
108
- VCEProfileLevel_62,
109
+ enum class H264ProfileLevel : uint8_t {
110
+ Automatic = 0,
111
+ L10 = 10,
112
+ L11,
113
+ L12,
114
+ L13,
115
+ L20 = 20,
116
+ L21,
117
+ L22,
118
+ L30 = 30,
119
+ L31,
120
+ L32,
121
+ L40 = 40,
122
+ L41,
123
+ L42,
124
+ L50 = 50,
125
+ L51,
126
+ L52,
127
};
128
- enum VCEScanType {
129
- VCEScanType_Progressive,
130
- VCEScanType_Interlaced,
131
+ enum class H264ScanType : uint8_t {
132
+ Progressive = 0,
133
+ Interlaced,
134
};
135
- enum VCECodingType {
136
- VCECodingType_Default = 0,
137
- VCECodingType_CABAC = 1,
138
- VCECodingType_CALVC = 2,
139
+ enum class H264CodingType : uint8_t {
140
+ Default = 0,
141
+ CABAC = 1,
142
+ CALVC = 2,
143
};
144
145
// Dynamic Properties
146
- enum VCERateControlMethod {
147
- VCERateControlMethod_ConstantQP,
148
- VCERateControlMethod_ConstantBitrate,
149
- VCERateControlMethod_VariableBitrate_PeakConstrained,
150
- VCERateControlMethod_VariableBitrate_LatencyConstrained,
151
+ enum class H264RateControlMethod : uint8_t {
152
+ ConstantQP = 0,
153
+ ConstantBitrate,
154
+ VariableBitrate_PeakConstrained,
155
+ VariableBitrate_LatencyConstrained = 3,
156
};
157
- enum VCEBFramePattern {
158
- VCEBFramePattern_None,
159
- VCEBFramePattern_One,
160
- VCEBFramePattern_Two,
161
- VCEBFramePattern_Three,
162
+ enum class H264BFramePattern : uint8_t {
163
+ None = 0,
164
+ One,
165
+ Two,
166
+ Three,
167
};
168
169
// Experimental
170
- enum VCESliceMode {
171
- VCESliceMode_Horizontal = 1,
172
- VCESliceMode_Vertical = 2
173
+ enum class H264SliceMode : uint8_t {
174
+ Horizontal = 1,
175
+ Vertical = 2
176
};
177
- enum VCESliceControlMode {
178
- VCESliceControlMode_Off,
179
- VCESliceControlMode_Macroblock = 1, // AMF_VIDEO_ENCODER_SLICE_CTRL_MODE_MB
180
- VCESliceControlMode_Invalid,
181
- VCESliceControlMode_Macroblock_Row = 3 // AMF_VIDEO_ENCODER_SLICE_CTRL_MODE_MB_ROW
182
+ enum class H264SliceControlMode : uint8_t {
183
+ Off = 0,
184
+ Macroblock = 1, // AMF_VIDEO_ENCODER_SLICE_CTRL_MODE_MB
185
+ Invalid,
186
+ Macroblock_Row = 3 // AMF_VIDEO_ENCODER_SLICE_CTRL_MODE_MB_ROW
187
};
188
-
189
-
190
-
191
- class VCEEncoder {
192
+
193
+ class H264Encoder {
194
#pragma region Initializer & Finalizer
195
public:
196
- VCEEncoder(
197
- VCEEncoderType p_Type,
198
+ H264Encoder(
199
+ H264EncoderType p_Type,
200
std::string p_VideoAPI,
201
uint64_t p_VideoAdapterId,
202
bool p_OpenCL,
203
- VCEColorFormat p_SurfaceFormat = VCEColorFormat_NV12
204
+ H264ColorFormat p_SurfaceFormat = H264ColorFormat::NV12
205
);
206
- ~VCEEncoder();
207
+ ~H264Encoder();
208
#pragma endregion Initializer & Finalizer
209
210
public:
211
212
#pragma region Startup Properties
213
// Set which Usage preset to use.
214
// Changing this will also change a lot of other properties.
215
- void SetUsage(VCEUsage usage);
216
- VCEUsage GetUsage();
217
+ void SetUsage(H264Usage usage);
218
+ H264Usage GetUsage();
219
220
// Set which Quality Preset AMF should use.
221
// Affects the quality of the output.
222
- void SetQualityPreset(VCEQualityPreset preset);
223
- VCEQualityPreset GetQualityPreset();
224
+ void SetQualityPreset(H264QualityPreset preset);
225
+ H264QualityPreset GetQualityPreset();
226
227
// Set the Profile the output should have.
228
- void SetProfile(VCEProfile profile);
229
- VCEProfile GetProfile();
230
+ void SetProfile(H264Profile profile);
231
+ H264Profile GetProfile();
232
233
// Set the Profile Level the output should have.
234
- void SetProfileLevel(VCEProfileLevel level);
235
- VCEProfileLevel GetProfileLevel();
236
+ void SetProfileLevel(H264ProfileLevel level);
237
+ H264ProfileLevel GetProfileLevel();
238
#pragma endregion Startup Properties
239
240
#pragma region Frame Properties
241
// Set which Color Profile the input frame is.
242
- void SetColorProfile(VCEColorProfile profile);
243
- VCEColorProfile GetColorProfile();
244
+ void SetColorProfile(H264ColorProfile profile);
245
+ H264ColorProfile GetColorProfile();
246
247
// Set if the input frame is in full color range.
248
void SetFullRangeColorEnabled(bool enabled);
249
250
std::pair<uint32_t, uint32_t> GetFrameRate();
251
252
// Scanning method for input (and output?).
253
- void SetScanType(VCEScanType scanType);
254
- VCEScanType GetScanType();
255
+ void SetScanType(H264ScanType scanType);
256
+ H264ScanType GetScanType();
257
#pragma endregion Frame Properties
258
259
// Dynamic
260
261
* - When SVC encoding is enabled, all Rate-control parameters (with some restrictions) can be configured differently for a particular SVC-layer. An SVC-layer is denoted by an index pair [SVC-Temporal Layer index][SVC-Quality Layer index]. E.g. The bitrate may be configured differently for SVC-layers [0][0] and [1][0].
262
* - We restrict all SVC layers to have the same Rate Control method. Some RC parameters are not enabled with SVC encoding (e.g. all parameters related to B-Frames).
263
**/
264
- void SetRateControlMethod(VCERateControlMethod method);
265
- VCERateControlMethod GetRateControlMethod();
266
+ void SetRateControlMethod(H264RateControlMethod method);
267
+ H264RateControlMethod GetRateControlMethod();
268
269
/* Sets the target bitrate */
270
void SetTargetBitrate(uint32_t bitrate);
271
272
273
#pragma region B-Frames
274
/* Sets the number of consecutive B-Frames. BFramesPattern = 0 indicates that B-Frames are not used */
275
- void SetBFramePattern(VCEBFramePattern pattern);
276
- VCEBFramePattern GetBFramePattern();
277
+ void SetBFramePattern(H264BFramePattern pattern);
278
+ H264BFramePattern GetBFramePattern();
279
280
/* Selects the delta QP of non-reference B-Frames with respect to the last non-B-Frame */
281
void SetBFrameDeltaQP(int8_t qp);
282
283
uint32_t GetMaxMBPerSec();
284
285
/* Coding Type */
286
- void SetCodingType(VCECodingType type);
287
- VCECodingType GetCodingType();
288
+ void SetCodingType(H264CodingType type);
289
+ H264CodingType GetCodingType();
290
291
void SetWaitForTaskEnabled(bool enabled);
292
bool IsWaitForTaskEnabled();
293
294
uint32_t GetSlicesPerFrame();
295
296
// - SliceMode (1 - 2, Default is 1)
297
- void SetSliceMode(VCESliceMode mode);
298
- VCESliceMode GetSliceMode();
299
+ void SetSliceMode(H264SliceMode mode);
300
+ H264SliceMode GetSliceMode();
301
302
// - MaxSliceSize (1 - INT_MAX)
303
void SetMaximumSliceSize(uint32_t size);
304
uint32_t GetMaximumSliceSize();
305
306
// - SliceControlMode (0 - 3)
307
- void SetSliceControlMode(VCESliceControlMode mode);
308
- VCESliceControlMode GetSliceControlMode();
309
+ void SetSliceControlMode(H264SliceControlMode mode);
310
+ H264SliceControlMode GetSliceControlMode();
311
312
// - SliceControlSize (0 - INT_MAX)
313
void SetSliceControlSize(uint32_t size);
314
315
316
// Threading
317
private:
318
- static void InputThreadMain(Plugin::AMD::VCEEncoder* p_this);
319
+ static void InputThreadMain(Plugin::AMD::H264Encoder* p_this);
320
void InputThreadLogic();
321
- static void OutputThreadMain(Plugin::AMD::VCEEncoder* p_this);
322
+ static void OutputThreadMain(Plugin::AMD::H264Encoder* p_this);
323
void OutputThreadLogic();
324
inline amf::AMFSurfacePtr CreateSurfaceFromFrame(struct encoder_frame*& frame);
325
326
327
} m_Output;
328
329
// Internal Properties
330
- VCEEncoderType m_EncoderType;
331
- VCEMemoryType m_MemoryType;
332
+ H264EncoderType m_EncoderType;
333
+ H264MemoryType m_MemoryType;
334
bool m_OpenCL;
335
- VCEColorFormat m_ColorFormat;
336
+ H264ColorFormat m_ColorFormat;
337
bool m_Flag_IsStarted,
338
m_Flag_FirstFrameSubmitted,
339
m_Flag_FirstFrameReceived;
340
341
size_t m_InputQueueLimit,
342
m_InputQueueLastSize;
343
uint32_t m_TimerPeriod;
344
- VCEColorProfile m_ColorProfile;
345
+ H264ColorProfile m_ColorProfile;
346
std::chrono::time_point<std::chrono::high_resolution_clock> m_LastQueueWarnMessageTime;
347
348
#pragma endregion Members
349
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Include/amf.h -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Include/amf.h
Changed
10
1
2
amf::AMFFactory* m_AMFFactory;
3
amf::AMFTrace* m_AMFTrace;
4
amf::AMFDebug* m_AMFDebug;
5
+ amf::AMFTraceWriter* m_TraceWriter;
6
};
7
}
8
}
9
\ No newline at end of file
10
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Include/api-base.h -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Include/api-base.h
Changed
27
1
2
//////////////////////////////////////////////////////////////////////////
3
namespace Plugin {
4
namespace API {
5
- enum APIType {
6
- APIType_Host,
7
- APIType_Direct3D9,
8
- APIType_Direct3D11,
9
- APIType_OpenGL,
10
+ enum class Type {
11
+ Host,
12
+ Direct3D9,
13
+ Direct3D11,
14
+ OpenGL,
15
};
16
17
struct Adapter {
18
19
//////////////////////////////////////////////////////////////////////////
20
public:
21
virtual std::string GetName() = 0;
22
- virtual APIType GetType() = 0;
23
+ virtual Type GetType() = 0;
24
25
virtual std::vector<Adapter> EnumerateAdapters() = 0;
26
virtual Adapter GetAdapterById(uint32_t idLow, uint32_t idHigh) = 0;
27
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Include/api-d3d11.h -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Include/api-d3d11.h
Changed
10
1
2
namespace API {
3
class Direct3D11 : public Base {
4
virtual std::string GetName() override;
5
- virtual APIType GetType() override;
6
+ virtual Type GetType() override;
7
8
virtual std::vector<Adapter> EnumerateAdapters() override;
9
virtual Adapter GetAdapterById(uint32_t idLow, uint32_t idHigh) override;
10
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Include/api-d3d9.h -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Include/api-d3d9.h
Changed
10
1
2
namespace API {
3
class Direct3D9 : public Base {
4
virtual std::string GetName() override;
5
- virtual APIType GetType() override;
6
+ virtual Type GetType() override;
7
8
virtual std::vector<Adapter> EnumerateAdapters() override;
9
virtual Adapter GetAdapterById(uint32_t idLow, uint32_t idHigh);
10
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Include/api-host.h -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Include/api-host.h
Changed
10
1
2
namespace API {
3
class Host : public Base {
4
virtual std::string GetName() override;
5
- virtual APIType GetType() override;
6
+ virtual Type GetType() override;
7
8
virtual std::vector<Adapter> EnumerateAdapters() override;
9
virtual Adapter GetAdapterById(uint32_t idLow, uint32_t idHigh);
10
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Include/api-opengl.h -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Include/api-opengl.h
Changed
10
1
2
namespace API {
3
class OpenGL : public Base {
4
virtual std::string GetName() override;
5
- virtual APIType GetType() override;
6
+ virtual Type GetType() override;
7
8
virtual std::vector<Adapter> EnumerateAdapters() override;
9
virtual Adapter GetAdapterById(uint32_t idLow, uint32_t idHigh);
10
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Include/enc-h264.h -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Include/enc-h264.h
Changed
19
1
2
#define AMF_H264_VIEW_MASTER TEXT_AMF_H264("View.Master")
3
#define AMF_H264_DEBUG TEXT_AMF_H264("Debug")
4
#define AMF_H264_DEBUG_DESCRIPTION TEXT_AMF_H264("Debug.Description")
5
+#define AMF_H264_VERSION TEXT_AMF_H264("Version")
6
7
//////////////////////////////////////////////////////////////////////////
8
// Code
9
10
// Storage
11
//////////////////////////////////////////////////////////////////////////
12
private:
13
- Plugin::AMD::VCEEncoder* m_VideoEncoder;
14
+ Plugin::AMD::H264Encoder* m_VideoEncoder;
15
};
16
}
17
}
18
\ No newline at end of file
19
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Include/plugin.h -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Include/plugin.h
Changed
18
1
2
//////////////////////////////////////////////////////////////////////////
3
// Includes
4
//////////////////////////////////////////////////////////////////////////
5
-#include <stdint.h>
6
+
7
+// Microsoft as always does not follow the standard and declares safe functions unsafe.
8
+// Or even straight up marks them as deprecated, what the fuck Microsoft?
9
+#ifdef _MSC_VER
10
+#define _CRT_SECURE_NO_WARNINGS
11
+#pragma warning(disable : 4996)
12
+#endif
13
+
14
+#include <cstdint>
15
#include <inttypes.h>
16
#include <exception>
17
#include <stdexcept>
18
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/ca-ES.ini -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Resources/locale/ca-ES.ini
Changed
122
1
2
AMF.Util.Toggle.Disabled="Desactivat"
3
AMF.Util.Toggle.Enabled="Activat"
4
AMF.H264.Preset="Configuració preestablerta"
5
+AMF.H264.Preset.ResetToDefaults="Restableix als valors per defecte"
6
AMF.H264.Preset.Recording="S'està enregistrant"
7
AMF.H264.Preset.HighQuality="Alta qualitat"
8
AMF.H264.Preset.Indistinguishable="Indistinguible"
9
10
AMF.H264.Usage.UltraLowLatency="Latència ultra baixa"
11
AMF.H264.Usage.LowLatency="Latència baixa"
12
AMF.H264.QualityPreset="Qualitat del perfil"
13
+AMF.H264.QualityPreset.Description="Quina qualitat del perfil d'AMD s'ha d'intentar aconseguir:\n- 'Velocitat' és la més ràpida però la que pitjor qualitat obté,\n- 'Equilibrat' està entre 'Velocitat' i 'Qualitat' oferint un balanç entre els dos,\n- 'Qualitat' ofereix la millor qualitat possible per una determinada tassa de marcs."
14
AMF.H264.QualityPreset.Speed="Velocitat"
15
AMF.H264.QualityPreset.Balanced="Equilibrat"
16
AMF.H264.QualityPreset.Quality="Qualitat"
17
AMF.H264.Profile="Perfil"
18
+AMF.H264.Profile.Description="Quin perfil H.264 s'ha d'utilitzar per la codificació, ordenats de major qualitat al més suportat."
19
AMF.H264.ProfileLevel="Nivell de perfil"
20
+AMF.H264.ProfileLevel.Description="Nivell de perfil H.264 a utilitzar per la codificació:\n- 'Automàtic' calcula el millor nivell de perfil per certa velocitat i mida de marcs,\n- '4.1' suporta 1920x1080 30FPS, 1280x720 60FPS, 960x540 90FPS\n- '4.2' suporta 1920x1080 60FPS, 1280x720 120FPS, 960x540 172FPS\n- '5.0' suporta 1920x1080 60FPS, 1280x720 144FPS, 960x540 172FPS\n- '5.1' suporta 3840x2160 30FPS, 1920x1080 120FPS, 1280x720 172FPS, 960x540 172FPS\n- '5.2' suporta 3840x2160 60FPS, 1920x1080 172FPS, 1280x720 172FPS, 960x540 172FPS"
21
AMF.H264.RateControlMethod="Mètode de control del flux"
22
+AMF.H264.RateControlMethod.Description="Quin mètode de control de flux s'ha d'utilitzar:\n- '\@AMF.H264.RateControlMethod.CQP\@' assigna valors fixos de QP a I-/P-/B-Frames (Paràmetre de quantització),\n- '\@AMF.H264.RateControlMethod.CBR\@' es manté en la tassa de marcs objectiu (utilitzant dades de farciment) (recomanat per transmissions en directe),\n- '\@AMF.H264.RateControlMethod.VBR\@' es manté per sota d'un pic de tassa de marcs,\n- '\@AMF.H264.RateControlMethod.VBR_LAT\@' es manté prop de la tassa de marcs desitjada si la latència i carrega de la GPU ho permet, si no s'augmentarà la taxa de marcs (recomanat per a enregistraments)."
23
AMF.H264.RateControlMethod.CQP="QP constant (CQP)"
24
AMF.H264.RateControlMethod.CBR="Flux constant (CBR)"
25
AMF.H264.RateControlMethod.VBR.Peak="Flux variable (pic restringit)(VBR)"
26
AMF.H264.RateControlMethod.VBR.Latency="Flux variable (latència restringida) (VBR_LAT)"
27
AMF.H264.Bitrate.Target="Tassa de bits desitjada"
28
+AMF.H264.Bitrate.Target.Description="Tassa de marcs a intentar arribar a la seqüència general."
29
AMF.H264.Bitrate.Peak="Pic de tassa de bits"
30
+AMF.H264.Bitrate.Peak.Description="Tassa de marcs a intentar aconseguir com pic màxim en la seqüència general."
31
AMF.H264.QP.Minimum="QP mínim"
32
+AMF.H264.QP.Minimum.Description="Valor mínim de QP (paràmetre de quantització) a utilitzar en un fotograma."
33
AMF.H264.QP.Maximum="QP màxim"
34
+AMF.H264.QP.Maximum.Description="Valor màxim de QP (paràmetre de quantització) a utilitzar en un fotograma."
35
AMF.H264.QP.IFrame="I-Frame QP"
36
+AMF.H264.QP.IFrame.Description="Valor fix de QP per I-Frames."
37
AMF.H264.QP.PFrame="P-Frame QP"
38
+AMF.H264.QP.PFrame.Description="Valor fix de QP per P-Frames."
39
AMF.H264.QP.BFrame="B-Frame QP"
40
+AMF.H264.QP.BFrame.Description="Valor de QP fix (paràmetre de quantització) a utilitzar per B-Frames."
41
+AMF.H264.VBVBuffer="Memòria intermèdia VBV"
42
+AMF.H264.VBVBuffer.Description="Quin mètode s'ha d'utilitzar per determinar la mida de la memòria intermèdia VBV:\n- 'Automàtic' calcula la mida utilitzant una restricció estricta,\n- 'Manual' permet a l'usuari controlar la mida.\nLa memòria intermèdia VBV (Verificador de la memòria intermèdia del vídeo) és usat per certs mètodes de control del flux per mantenir la taxa de bits dins dels paràmetres establerts."
43
+AMF.H264.VBVBuffer.Strictness="Rigorositat de la memòria intermèdia VBV"
44
+AMF.H264.VBVBuffer.Strictness.Description="Determina la rigidesa de la memòria intermèdia VBV, con 100% essent tant estricte com sigui possible i 0% sense restricció."
45
+AMF.H264.VBVBuffer.Size="Mida de la memòria intermèdia VBV"
46
+AMF.H264.VBVBuffer.Size.Description="La mida de la memòria intermèdia VBV que s'utilitza per al control de la tassa de marcs en una seqüencia."
47
+AMF.H264.VBVBuffer.Fullness="Amplitud de la memòria intermèdia VBV"
48
+AMF.H264.VBVBuffer.Fullness.Description="Com de ple és la memòria intermèdia VMV inicialment, només afectarà la seqüència inicial de la codificació."
49
AMF.H264.FillerData="Dades a omplir"
50
+AMF.H264.FillerData.Description="En activar les dades de farciment es permet al codificador mantenir almenys la tassa de marcs desitjada omplint l'espai que falta amb informació sense valor."
51
AMF.H264.FrameSkipping="Omissió de fotogrames"
52
+AMF.H264.FrameSkipping.Description="L'omissió de fotogrames permet al codificador saltar fotogrames per complir amb el requeriment de la tassa de marcs objectiu.\nQuan el codificador salta un fotograma inserirà una NAL que repetirà el darrer fotograma codificat a la transmissió.\nPot ajudar amb tassa de bits objectiu molt baixes."
53
AMF.H264.EnforceHRDCompatibility="Força la compatibilitat amb HRD"
54
+AMF.H264.EnforceHRDCompatibility.Description="Força les restriccions del descodificador hipotètic de referència que limiten el canvi de valor màxim de QP dins d'un fotograma."
55
+AMF.H264.KeyframeInterval="Interval de fotogrames clau"
56
+AMF.H264.KeyframeInterval.Description="Quants segons han d'haver entre fotogrames que no es poden descartar.\nTambé controla la mida de la seqüència (GOP)."
57
+AMF.H264.IDRPeriod="Període IDR"
58
+AMF.H264.IDRPeriod.Description="Defineix la distància entre Instantaneous Decoding Refreshes (IDR) en fotogrames. També controla la mida de la seqüència del GOP."
59
+AMF.H264.BFrame.Pattern="B-Frames"
60
+AMF.H264.BFrame.Pattern.Description="La quantitat de B-Frames a utilitzar mestre es codifica.\nCompatible amb targetes de 2ª i 3ª generació VCE. Impacte negatiu en el rendiment de codificació."
61
+AMF.H264.BFrame.DeltaQP="Delta QP per B-Frames"
62
+AMF.H264.BFrame.DeltaQP.Description="Valor Delta QP per al darrer I- o P-Frame per B-Frames no referenciables."
63
+AMF.H264.BFrame.Reference="B-Frames referenciables"
64
+AMF.H264.BFrame.Reference.Description="Permet a un B-Frames utilitzar també B-Frames com referència, enlloc de P- i I-Frames."
65
+AMF.H264.BFrame.ReferenceDeltaQP="Delta QP per als fotogrames referenciables"
66
+AMF.H264.BFrame.ReferenceDeltaQP.Description="Valor Delta QP per al darrer I- o P-Frame per B-Frames referenciables."
67
AMF.H264.DeblockingFilter="Filtre d'eliminació de blocs"
68
+AMF.H264.DeblockingFilter.Description="Estableix l'indicador que el descodificador està permès a utilitzar el Filtre d'eliminació de blocs per a la transmissió codificada."
69
AMF.H264.ScanType="Tipus d'exploració"
70
+AMF.H264.ScanType.Description="Quin mètode de escaneig utilitzar, deixeu-lo sempre a '\@AMF.H264.ScanType.Progressive\@'."
71
AMF.H264.ScanType.Progressive="Progressiu"
72
AMF.H264.ScanType.Interlaced="Entrellaçat"
73
+AMF.H264.MotionEstimation="Estimació del moviment"
74
+AMF.H264.MotionEstimation.Description="L'estimació del moviment permet al codificador reduir el flux de dades necessari calculant d'on vénen els píxels."
75
AMF.H264.MotionEstimation.None="Cap"
76
AMF.H264.MotionEstimation.Half="Meitat de píxel"
77
AMF.H264.MotionEstimation.Quarter="Quart de Píxel"
78
+AMF.H264.MotionEstimation.Both="Meitat i quart de píxel"
79
+AMF.H264.CodingType="Tipus de codificació"
80
+AMF.H264.CodingType.Description="Quin tipus de codificació utilitzar:\n* \@AMF.Util.Default\@ deixeu que AMF ho decideixi (recomanat).\n* CALVC (Context-Adaptive Variable-Length Coding) és més ràpid, però mes gran.\n* CABAC (Context-Adaptive Binary Arithmetic Coding) es més lent, però més petit."
81
AMF.H264.MaximumLTRFrames="Fotogrames màxims LTR"
82
+AMF.H264.MaximumLTRFrames.Description="Fotogrames de referència a llarg plaç (LTR) és una característica que permet al codificador marcar certs marcs en una seqüencia com referents per un llarg temps.\nEls fotogrames LTR no poden ser utilitzats amb B-Pictures i el codificador desactivarà B-Pictures si s'utilitza."
83
+AMF.H264.MaximumAccessUnitSize="Mida màxima de la unitat d'accés"
84
+AMF.H264.MaximumAccessUnitSize.Description="Mida d'una unitat d'accés per a una NAL."
85
+AMF.H264.HeaderInsertionSpacing="Espaiat d'inserció de capçaleres"
86
+AMF.H264.HeaderInsertionSpacing.Description="Quants fotogrames han d'haver entre capçaleres NAL."
87
+AMF.H264.WaitForTask="Espera per la tasca"
88
+AMF.H264.WaitForTask.Description="Desconegut, Experimental"
89
+AMF.H264.PreAnalysisPass="Passada d'anàlisi previ"
90
+AMF.H264.PreAnalysisPass.Description="Desconegut, Experimental"
91
+AMF.H264.VBAQ="VBAQ"
92
+AMF.H264.VBAQ.Description="Desconegut, Experimental"
93
+AMF.H264.GOPSize="Mida del GOP"
94
+AMF.H264.GOPSize.Description="Desconegut, Experimental"
95
+AMF.H264.GOPAlignment="Alineació del GOP"
96
+AMF.H264.GOPAlignment.Description="Desconegut, Experimental"
97
+AMF.H264.MaximumReferenceFrames="Fotogrames de referència màxims"
98
+AMF.H264.MaximumReferenceFrames.Description="Desconegut, Experimental"
99
+AMF.H264.SlicesPerFrame="Porcions per fotograma"
100
+AMF.H264.SlicesPerFrame.Description="Quantes porcions I-Frame han de ser emmagatzemats en cada fotograma?\nUn valor de 0 permet al codificador decidir sobre la marxa.\nLa codificació Intra-Refresh és usada per a una reproducció i exploració més fluïda."
101
+AMF.H264.SliceMode="Mode de porcions"
102
+AMF.H264.SliceMode.Description="Desconegut, Experimental"
103
+AMF.H264.MaximumSliceSize="Mida màxima de la porció"
104
+AMF.H264.MaximumSliceSize.Description="Desconegut, Experimental"
105
+AMF.H264.SliceControlMode="Mode de control de la porció"
106
+AMF.H264.SliceControlMode.Description="Desconegut, Experimental"
107
+AMF.H264.SliceControlSize="Control de mida de la porció"
108
+AMF.H264.SliceControlSize.Description="Desconegut, Experimental"
109
+AMF.H264.IntraRefresh.NumberOfStripes="Numero de línies Intra-Refresh"
110
+AMF.H264.IntraRefresh.NumberOfStripes.Description="Desconegut, Experimental"
111
+AMF.H264.IntraRefresh.MacroblocksPerSlot="Macroblocs intra-refresh per Slot"
112
+AMF.H264.IntraRefresh.MacroblocksPerSlot.Description="Quants macroblocs han de ser emmagatzemats en cada slot?\nUn valor de 0 desactiva aquesta funció.\nLa codificació Intra-Refresh és usada per a una reproducció i exploració més fluïda."
113
+AMF.H264.VideoAPI="API de vídeo"
114
+AMF.H264.VideoAPI.Description="Quina API utilitzar per la codificació."
115
+AMF.H264.VideoAdapter="Adaptador de vídeo"
116
+AMF.H264.VideoAdapter.Description="Quin adaptador utilitzar per la codificació."
117
+AMF.H264.OpenCL="OpenCL"
118
+AMF.H264.OpenCL.Description="El codificador hauria d'utilitzar OpenCL per presentar els fotogrames individuals?"
119
AMF.H264.View="Mode de visualització"
120
AMF.H264.View.Description="Quines propietats han de ser visibles. No rebreu suport si feu servir el mode de vista 'Expert' o 'Màster'."
121
AMF.H264.View.Basic="Bàsic"
122
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/da-DK.ini -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Resources/locale/da-DK.ini
Changed
31
1
2
AMF.Util.Default="Standard"
3
+AMF.Util.Automatic="Automatisk"
4
+AMF.Util.Manual="Manuelt"
5
AMF.Util.Toggle.Disabled="Deaktiveret"
6
AMF.Util.Toggle.Enabled="Aktiveret"
7
+AMF.H264.Preset="Forudindstillinger"
8
+AMF.H264.Preset.ResetToDefaults="Nulstil til standarder"
9
+AMF.H264.Preset.Recording="Optagelse"
10
+AMF.H264.Preset.HighQuality="Højkvalitet"
11
+AMF.H264.Preset.Indistinguishable="Indistingverbar"
12
+AMF.H264.Preset.Lossless="Tabsfri"
13
+AMF.H264.Preset.YouTube="YouTube"
14
+AMF.H264.Usage="Anvendelse"
15
+AMF.H264.Usage.Description="Hvilken anvendelse AMF bør indstilles til:\n- '\@AMF.H264.Usage.Transcoding\@' er omkodning til generelle formål (anbefalet),\n - '\@AMF.H264.Usage.UltraLowLatency\@' er til virkelig lav-forsinkelseskodning,\n- '\@AMF.H264.Usage.LowLatency\@' er tilsvarende ovennævnte med en lidt større forsinkelse.\nStreaming understøtter kun '\@AMF.H264.Usage.Transcoding\@', alle andre værdier kan benyttes til optagelse."
16
AMF.H264.Usage.Transcoding="Transcoding"
17
AMF.H264.Usage.UltraLowLatency="Ekstrem Lav Ventetid"
18
AMF.H264.Usage.LowLatency="Lav Ventetid"
19
AMF.H264.QualityPreset="Kvalitets profiler"
20
+AMF.H264.QualityPreset.Description="Hvilken Kvalitetsforudindstilling AMF bør forsøges målrettet imod:\n- '\@AMF. H264. QualityPreset.Speed\@' er den hurtigste, men har den ringeste kvalitet,\n- '\@AMF. H264. QualityPreset.Balanced\@' er en balanceret blanding af begge,\n- '\@AMF. H264. QualityPreset.Quality\@' giver den bedste kvalitet for en given bithastighed."
21
AMF.H264.QualityPreset.Speed="Hastighed (Dårligste kvalitet)"
22
AMF.H264.QualityPreset.Balanced="Balanceret (Mellem Kvalitet)"
23
AMF.H264.QualityPreset.Quality="Kvalitet (Bedste Kvalitet)"
24
AMF.H264.Profile="Profil"
25
+AMF.H264.Profile.Description="Hvilken H.264-profil at benytte til kodning, sorteret fra højeste kvalitet til mest udbredte understøttelse."
26
AMF.H264.ProfileLevel="Profil Niveau"
27
+AMF.H264.ProfileLevel.Description="Hvilket H.264-profilniveau at benytte til kodning:\n- ' \@AMF. Util.Automatic\@' beregner det best profilniveau for en given billedhastighed og -størrelse,\n- '4.1' understøtter 1920x1080 30FPS, 1280x720 60FPS, 960x540 90FPS\n- '4.2' understøtter 1920x1080 60FPS, 1280x720 120FPS, 960x540 172FPS\n- '5.0' understøtter 1920x1080 60FPS, 1280x720 144FPS, 960x540 172FPS\n- '5.1' understøtter 3840x2160 30FPS, 1920x1080 120FPS, 1280x720 172FPS, 960x540 172FPS\n- '5.2' understøtter 3840x2160 60FPS, 1920x1080 172FPS, 1280x720 172FPS, 960 x 540 172 FPS"
28
AMF.H264.RateControlMethod="Rate Control Method"
29
AMF.H264.RateControlMethod.CQP="Constant QP (CQP)"
30
AMF.H264.RateControlMethod.CBR="Constant Bitrate (CBR)"
31
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/eu-ES.ini -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Resources/locale/eu-ES.ini
Changed
14
1
2
AMF.H264.SliceControlMode.Description="Ezezaguna, esperimentala"
3
AMF.H264.SliceControlSize.Description="Ezezaguna, esperimentala"
4
AMF.H264.IntraRefresh.NumberOfStripes.Description="Ezezaguna, esperimentala"
5
+AMF.H264.VideoAPI="Bideo APIa"
6
+AMF.H264.VideoAPI.Description="Zein API erabili kodeketarako."
7
+AMF.H264.VideoAdapter="Bideo egokigailua"
8
+AMF.H264.VideoAdapter.Description="Zein egokigailu erabili kodeketarako."
9
AMF.H264.OpenCL="OpenCL"
10
+AMF.H264.OpenCL.Description="Kodetzaileak OpenCL erabili behar du banakako fotogramak bidaltzeko?"
11
AMF.H264.View="Ikuspegia"
12
AMF.H264.View.Description="Zein propietate ikusi behar dira. Ez duzu laguntzarik jasoko 'Aditu' edo 'Maisu' ikuspegian."
13
AMF.H264.View.Basic="Oinarrizkoa"
14
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/hu-HU.ini -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Resources/locale/hu-HU.ini
Changed
79
1
2
AMF.H264.ProfileLevel="Profil szint"
3
AMF.H264.RateControlMethod="Bitráta vezérlés"
4
AMF.H264.RateControlMethod.CQP="Erőltetett QP (CQP)"
5
-AMF.H264.RateControlMethod.CBR="Konstans bitráta (CBR)"
6
-AMF.H264.RateControlMethod.VBR.Peak="Változó bitráta (Csúcsértéket betartva) (VBR)"
7
-AMF.H264.RateControlMethod.VBR.Latency="Változó bitráta (Késleltetés kényszerítése) (VBR_LAT)"
8
-AMF.H264.Bitrate.Target="Bitráta (Bitben)"
9
+AMF.H264.RateControlMethod.CBR="Konstans bitsebesség (CBR)"
10
+AMF.H264.RateControlMethod.VBR.Peak="Változó bitsebesség (Csúcsértéket betartva) (VBR)"
11
+AMF.H264.RateControlMethod.VBR.Latency="Változó bitsebesség (Késleltetés kényszerítése) (VBR_LAT)"
12
+AMF.H264.Bitrate.Target="Célbitsebesség"
13
AMF.H264.Bitrate.Target.Description="Bitráta amelyet szeretne elérni a konvertálás során."
14
-AMF.H264.Bitrate.Peak="Csúcs bitráta (Bitben)"
15
-AMF.H264.Bitrate.Peak.Description="Bitráta amelyet maximálisan elérhet a konvertálás során."
16
+AMF.H264.Bitrate.Peak="Csúcs bitsebesség"
17
+AMF.H264.Bitrate.Peak.Description="Bitsebesség amelyet maximálisan elérhet a konvertálás során."
18
AMF.H264.QP.Minimum="Minimum QP"
19
AMF.H264.QP.Minimum.Description="Legalacsonyabb QP (Quantization Parameter) képkockában használható érték."
20
AMF.H264.QP.Maximum="Maximum QP"
21
22
AMF.H264.KeyframeInterval="Kulcsképkocka időköze"
23
AMF.H264.IDRPeriod="IDR időköz"
24
AMF.H264.BFrame.Pattern="B képkocka"
25
+AMF.H264.BFrame.Pattern.Description="A B képkockák száma kódolás közben.\nA második és harmadik generációjú VCE kártyák támogatják. Hátráltató hatása van a kódolás teljesítményére."
26
AMF.H264.BFrame.DeltaQP="B képkocka Delta QP"
27
+AMF.H264.BFrame.DeltaQP.Description="Delta QP érték az utolsó I vagy P képkocka nem referenciálható B képkockáihoz."
28
AMF.H264.BFrame.Reference="Referenciálható B képkockák"
29
AMF.H264.BFrame.Reference.Description="Lehetővé teszi a B képkockák számára, hogy B képkockát referenciaként használjon, P és I képkockák helyett."
30
AMF.H264.BFrame.ReferenceDeltaQP="Delta QP a referenciálható B kockákhoz"
31
32
AMF.H264.ScanType.Progressive="Progresszív"
33
AMF.H264.ScanType.Interlaced="Váltottsoros (Kísérleti)"
34
AMF.H264.MotionEstimation="Mozgásbecslés"
35
+AMF.H264.MotionEstimation.Description="Mozdulat becslés lehetővé teszi a kódolónak, hogy csökkentse a bitsebesség követelményt a pixel elmozdulásának a felbecsülésével."
36
AMF.H264.MotionEstimation.None="Semmi"
37
AMF.H264.MotionEstimation.Half="Fél-pixel"
38
AMF.H264.MotionEstimation.Quarter="Negyed-pixel"
39
40
AMF.H264.CodingType="Kódolás típusa"
41
AMF.H264.MaximumLTRFrames="Maximális LTR képkocka"
42
AMF.H264.MaximumAccessUnitSize="Hozzáférési egység maximális mérete"
43
+AMF.H264.MaximumAccessUnitSize.Description="NAL számára a legnagyobb elérési egység."
44
+AMF.H264.HeaderInsertionSpacing.Description="NAL fejlécek közötti képkockák száma."
45
+AMF.H264.WaitForTask="Feladatra várakozás"
46
+AMF.H264.WaitForTask.Description="Ismeretlen, kísérleti"
47
AMF.H264.PreAnalysisPass="Elemzés előtti fázis"
48
+AMF.H264.PreAnalysisPass.Description="Ismeretlen, kísérleti"
49
AMF.H264.VBAQ="VBAQ"
50
+AMF.H264.VBAQ.Description="Ismeretlen, kísérleti"
51
AMF.H264.GOPSize="GOP méret"
52
+AMF.H264.GOPSize.Description="Ismeretlen, kísérleti"
53
AMF.H264.GOPAlignment="GOP igazítás"
54
+AMF.H264.GOPAlignment.Description="Ismeretlen, kísérleti"
55
AMF.H264.MaximumReferenceFrames="Maximális referencia képkockák"
56
+AMF.H264.MaximumReferenceFrames.Description="Ismeretlen, kísérleti"
57
AMF.H264.SlicesPerFrame="Szeletelés képkockánként"
58
AMF.H264.SliceMode="Szelet mód"
59
+AMF.H264.SliceMode.Description="Ismeretlen, kísérleti"
60
AMF.H264.MaximumSliceSize="Maximális szeletméret"
61
+AMF.H264.MaximumSliceSize.Description="Ismeretlen, kísérleti"
62
+AMF.H264.SliceControlMode="Szelet ellenőrzési mód"
63
+AMF.H264.SliceControlMode.Description="Ismeretlen, kísérleti"
64
+AMF.H264.SliceControlSize="Szeletméret ellenőrzés"
65
+AMF.H264.SliceControlSize.Description="Ismeretlen, kísérleti"
66
+AMF.H264.IntraRefresh.NumberOfStripes.Description="Ismeretlen, kísérleti"
67
+AMF.H264.IntraRefresh.MacroblocksPerSlot.Description="Hány makroblokkot tároljon céllánként?\nA 0 érték kikapcsolja a funkciót.\nIntra-Refresh kódolás a gyorsabb lejátszáshoz és kereséshez használható."
68
AMF.H264.VideoAPI="Videó API"
69
AMF.H264.VideoAPI.Description="Melyik API használható kódoláshoz."
70
AMF.H264.VideoAdapter="Videó adapter"
71
AMF.H264.VideoAdapter.Description="Melyik adapter használható kódoláshoz."
72
AMF.H264.OpenCL="OpenCL"
73
+AMF.H264.OpenCL.Description="A kódolós használhat OpenCL-t az egyes képkockák elkészítéséhez?"
74
AMF.H264.View="Nézet mód"
75
+AMF.H264.View.Description="Milyen tulajdonságok jelenjenek meg?\nA '\@AMF.H264.View.Master\@' használata kizárja a támogatásban való részesülésből."
76
AMF.H264.View.Basic="Alap"
77
AMF.H264.View.Advanced="Haladó"
78
AMF.H264.View.Expert="Szakértő"
79
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/it-IT.ini -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Resources/locale/it-IT.ini
Changed
25
1
2
AMF.H264.MaximumAccessUnitSize="Massima dimensione di unità d'accesso"
3
AMF.H264.HeaderInsertionSpacing="Spaziatura di inserimento di intestazione"
4
AMF.H264.WaitForTask="Attendere per attività"
5
+AMF.H264.WaitForTask.Description="Sconosciuto, sperimentale"
6
+AMF.H264.PreAnalysisPass="Analisi pre-pass"
7
+AMF.H264.PreAnalysisPass.Description="Sconosciuto, sperimentale"
8
+AMF.H264.VBAQ="VBAQ"
9
+AMF.H264.VBAQ.Description="Sconosciuto, sperimentale"
10
+AMF.H264.GOPSize="Dimensione del GOP"
11
+AMF.H264.GOPSize.Description="Sconosciuto, sperimentale"
12
+AMF.H264.GOPAlignment="Allineamento del GOP"
13
+AMF.H264.GOPAlignment.Description="Sconosciuto, sperimentale"
14
+AMF.H264.MaximumReferenceFrames="Numero massimo di frames di riferimento"
15
+AMF.H264.MaximumReferenceFrames.Description="Sconosciuto, sperimentale"
16
AMF.H264.SlicesPerFrame="Slices Per Frame"
17
+AMF.H264.SliceMode="Modalità Slice"
18
+AMF.H264.SliceMode.Description="Sconosciuto, sperimentale"
19
+AMF.H264.MaximumSliceSize="Dimensione massima frame"
20
+AMF.H264.MaximumSliceSize.Description="Sconosciuto, sperimentale"
21
+AMF.H264.SliceControlMode="Modalità di controllo Slice"
22
AMF.H264.View="Modalità di visualizzazione"
23
AMF.H264.View.Basic="Basico"
24
AMF.H264.View.Advanced="Avanzate"
25
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/ko-KR.ini -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Resources/locale/ko-KR.ini
Changed
18
1
2
AMF.H264.KeyframeInterval.Description="손실이 불가능한 프레임 사이에 얼마나 많은 시간(초)이 필요한지 설정합니다.\n또한 영상(GOP) 크기도 제어합니다."
3
AMF.H264.IDRPeriod="IDR 주기"
4
AMF.H264.IDRPeriod.Description="프레임 내에서 순간 복호 갱신(nstantaneous Decoding Refreshes) 사이의 거리를 설정합니다. 또한, GOP-장면 크기를 제어합니다."
5
+AMF.H264.BFrame.Pattern="B-화면"
6
AMF.H264.BFrame.Pattern.Description="인코딩에 얼마나 많은 B-화면을 사용할지 설정합니다.\n2, 3세대 VCE카드에서 지원합니다. 인코딩 성능에 부정적인 영향을 줍니다."
7
AMF.H264.BFrame.DeltaQP="B-화면 델타 QP"
8
AMF.H264.BFrame.DeltaQP.Description="비참조 B-화면에 쓰이는 마지막 I- 혹은P-화면의 델타 QP 값"
9
10
AMF.H264.HeaderInsertionSpacing.Description="NAL 헤더 사이에 얼마나 많은 프레임이 필요한지 설정합니다. 0(자동)에서 바꾸는 것은 추천하지 않습니다."
11
AMF.H264.WaitForTask="작업을 대기"
12
AMF.H264.WaitForTask.Description="알수 없음, 실험적인 기능"
13
+AMF.H264.PreAnalysisPass="사전분석 처리"
14
+AMF.H264.PreAnalysisPass.Description="알수 없음, 실험적인 기능"
15
AMF.H264.VBAQ="VBAQ"
16
AMF.H264.VBAQ.Description="알수 없음, 실험적인 기능"
17
AMF.H264.GOPSize="GOP 크기"
18
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/nl-NL.ini -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Resources/locale/nl-NL.ini
Changed
131
1
2
AMF.Util.Default="Standaard"
3
AMF.Util.Automatic="Automatisch"
4
+AMF.Util.Manual="Handmatig"
5
AMF.Util.Toggle.Disabled="Uitgeschakeld"
6
AMF.Util.Toggle.Enabled="Ingeschakeld"
7
AMF.H264.Preset="Voorkeursinstelling"
8
+AMF.H264.Preset.ResetToDefaults="Standaardinstellingen herstellen"
9
AMF.H264.Preset.Recording="Opname"
10
AMF.H264.Preset.HighQuality="Hoge kwaliteit"
11
AMF.H264.Preset.Indistinguishable="Ononderscheidbaar"
12
13
AMF.H264.Usage.UltraLowLatency="Ultra Low Latency"
14
AMF.H264.Usage.LowLatency="Low Latency"
15
AMF.H264.QualityPreset="Kwaliteitsinstelling"
16
+AMF.H264.QualityPreset.Description="Welke kwaliteitsinstelling AMF moet proberen te halen:\n- '\@AMF.H264.QualityPreset.Speed\@' is de snelste maar heeft de slechtste kwaliteit,\n- '\@AMF.H264.QualityPreset.Balanced\@' is een gebalanceerde mix van beide,\n- '\@AMF.H264.QualityPreset.Quality\@' geeft de beste kwaliteit voor een gekozen bitrate."
17
AMF.H264.QualityPreset.Speed="Snelheid"
18
AMF.H264.QualityPreset.Balanced="Gebalanceerd"
19
AMF.H264.QualityPreset.Quality="Kwaliteit"
20
AMF.H264.Profile="Profiel"
21
+AMF.H264.Profile.Description="Welk h.264 profiel gebruikt moet worden, gesorteerd van beste kwaliteit tot breedste ondersteuning."
22
AMF.H264.ProfileLevel="Profielniveau"
23
AMF.H264.ProfileLevel.Description="Welk H.264 profielniveau moet worden gebruikt voor encoden:\n- 'Automatisch' berekent het beste profielniveau voor de gebruikte framerate en framegrootte.\n- '4.1' ondersteunt 1920x1080 30FPS, 1280x720 60FPS, 960x540 90FPS\n- '4.2' ondersteunt 1920x1080 60FPS, 1280x720 120FPS, 960x540 172FPS\n- '5.0' ondersteunt1920x1080 60FPS, 1280x720 144FPS, 960x540 172FPS\n- '5.1' ondersteunt3840x2160 30FPS, 1920x1080 120FPS, 1280x720 172FPS, 960x540 172FPS\n- '5.2' ondersteunt 3840x2160 60FPS, 1920x1080 172FPS, 1280x720 172FPS, 960x540 172FPS"
24
AMF.H264.RateControlMethod="Rate control methode"
25
+AMF.H264.RateControlMethod.Description="Welke rate control methode gebruikt moet worden:\n- '\@AMF.H264.RateControlMethod.CQP\@' kent vaste I-/P-/B-Frame QP waardes toe,\n- '\@AMF.H264.RateControlMethod.CBR\@' blijft op de insgestelde doelbitrate (met opvuldata) (aanbevolen voor streamen),\n- '\@AMF.H264.RateControlMethod.VBR\@' blijft onder de ingestelde piek bitrate,\n- '\@AMF.H264.RateControlMethod.VBR_LAT\@' blijft in de buurt van de doelbitrate als de GPU latency en belasting het toestaan, anders zal er een hogere bitrate worden gebruikt (aanbevolen voor opnames)."
26
AMF.H264.RateControlMethod.CQP="Constant QP (CQP)"
27
AMF.H264.RateControlMethod.CBR="Constant Bitrate (CBR)"
28
AMF.H264.RateControlMethod.VBR.Peak="Variable Bitrate (Peak Constrained) (VBR)"
29
AMF.H264.RateControlMethod.VBR.Latency="Variable Bitrate (Latency Constrained) (VBR_LAT)"
30
AMF.H264.Bitrate.Target="Doelbitrate"
31
+AMF.H264.Bitrate.Target.Description="Bitrate om te proberen aan te houden in de gehele reeks."
32
AMF.H264.Bitrate.Peak="Maximale bitrate"
33
+AMF.H264.Bitrate.Peak.Description="Bitrate om in de gehele reeks maximaal naartoe te pieken."
34
AMF.H264.QP.Minimum="Minimale QP"
35
+AMF.H264.QP.Minimum.Description="Laagste QP waarde om te gebruiken in een frame."
36
AMF.H264.QP.Maximum="Maximale QP"
37
+AMF.H264.QP.Maximum.Description="Hoogste QP waarde om te gebruiken in een frame."
38
AMF.H264.QP.IFrame="I-Frame QP"
39
+AMF.H264.QP.IFrame.Description="Vaste QP waarde om te gebruiken voor I-frames."
40
AMF.H264.QP.PFrame="P-Frame QP"
41
+AMF.H264.QP.PFrame.Description="Vaste QP waarde om te gebruiken voor P-frames."
42
AMF.H264.QP.BFrame="B-Frame QP"
43
+AMF.H264.QP.BFrame.Description="Vaste QP waarde om te gebruiken voor B-frames."
44
AMF.H264.VBVBuffer="VBV Buffer"
45
+AMF.H264.VBVBuffer.Description="Welke methode moet worden gebruikt om de VBV buffergrootte te bepalen:\n- '\@AMF.Util.Automatic\@' berekent de grootte met een strengheid-instelling.\n- '\@AMF.Util.Manual\@' laat de gebruiker de grootte bepalen.\nVBV (Video Buffering Verifier) buffer wordt gebruikt door bepaalde Rate Control methodes om de algehele bitrate binnen de aangegeven perken te houden."
46
+AMF.H264.VBVBuffer.Strictness="VBV Buffer-strengheid"
47
+AMF.H264.VBVBuffer.Strictness.Description="Bepaalt de strengheid van de VBV buffer, waar 100% zo streng mogelijk is, en 0% geen restricties oplegt."
48
+AMF.H264.VBVBuffer.Size="VBV Buffergrootte"
49
+AMF.H264.VBVBuffer.Size.Description="De grootte van de VBV Buffer welke wordt gebruikt voor bitrate controle in een reeks."
50
+AMF.H264.VBVBuffer.Fullness="VBV Buffervulling"
51
+AMF.H264.VBVBuffer.Fullness.Description="Hoe vol de VBV Buffer initieel is, beïnvloedt alleen de initiële reeks van encoden."
52
AMF.H264.FillerData="Opvuldata"
53
+AMF.H264.FillerData.Description="Inschakelen van opvuldata laat de encoder tenminste de doelbitrate aanhouden door de overtollige ruimte in een reeks te vullen met lege informatie."
54
AMF.H264.FrameSkipping="Frames overslaan"
55
+AMF.H264.FrameSkipping.Description="Frame Skipping laat een encoder frames droppen om de doelbitrate te halen.\nAls de encoder een frame dropt vult het een herhaal-laatste-frame NAL in de stream.\nKan helpen bij erg lage doelbitrates."
56
AMF.H264.EnforceHRDCompatibility="Forceer HDR compatibiliteit"
57
+AMF.H264.EnforceHRDCompatibility.Description="Forceer hypothetische referentiedecoder-restricties welke de maximale QP waarde veranderen binnen een frame."
58
+AMF.H264.KeyframeInterval="Keyframe-Interval"
59
+AMF.H264.KeyframeInterval.Description="Bepaalt de afstand tussen keyframes in seconden. Bepaalt ook de GOP-sequence size."
60
+AMF.H264.IDRPeriod="IDR Periode"
61
+AMF.H264.IDRPeriod.Description="Bepaalt de afstand tussen Instantaneous Decoding Refreshes (IDR) in frames. Bepaalt ook de GOP-sequence size."
62
+AMF.H264.BFrame.Pattern="B-frames"
63
+AMF.H264.BFrame.Pattern.Description="Het aantal B-frames om te gebruiken tijdens het encoden.\nOndersteund door 2e en 3e generatie VCE-kaarten. Negatieve invloed op encodingprestaties."
64
+AMF.H264.BFrame.DeltaQP="Delta QP voor B-frames"
65
+AMF.H264.BFrame.DeltaQP.Description="Delta QP waarde tot de laatste I- of P-frame voor niet-refereerbare B-frames."
66
+AMF.H264.BFrame.Reference="Refereerbare B-frames"
67
+AMF.H264.BFrame.Reference.Description="Laat een B-frame ook B-frames gebruiken als referentie, in plaats van enkel P- en I-frames."
68
+AMF.H264.BFrame.ReferenceDeltaQP="Delta QP voor refereerbare B-frames"
69
+AMF.H264.BFrame.ReferenceDeltaQP.Description="Delta QP waarde tot de laatste I- of P-frame voor refereerbare B-frames."
70
AMF.H264.DeblockingFilter="Deblocking Filter"
71
+AMF.H264.DeblockingFilter.Description="Staat de encoder toe om een Deblocking Filter te gebruiken voor de gecodeerde stream."
72
AMF.H264.ScanType="Scantype"
73
+AMF.H264.ScanType.Description="Welke scanmethode gebruikt moet worden, laat dit altijd op '\@AMF.H264.ScanType.Progressive\@'."
74
AMF.H264.ScanType.Progressive="Progressive"
75
AMF.H264.ScanType.Interlaced="Interlaced"
76
+AMF.H264.MotionEstimation="Bewegingsschatting"
77
+AMF.H264.MotionEstimation.Description="Bewigingsschatting laat de encoder de benodigde bitrate verlagen door te schatten waar een pixel heen ging."
78
+AMF.H264.MotionEstimation.None="Geen"
79
+AMF.H264.MotionEstimation.Half="Halve pixel"
80
+AMF.H264.MotionEstimation.Quarter="Kwartpixel"
81
+AMF.H264.MotionEstimation.Both="Halve en kwartpixel"
82
+AMF.H264.CodingType="Codeertype"
83
+AMF.H264.CodingType.Description="Welk codeertype gebruikt moet worden:\n* \@AMF.Util.Default\@ laat AMF bepalen (aanbevolen).\n* CALVC (Context-Adaptive Variable-Length Coding) is sneller, maar groter.\n* CABAC (Context-Adaptive Binary Arithmetic Coding) is langzamer, maar kleiner."
84
AMF.H264.MaximumLTRFrames="Maximale LTR Frames"
85
+AMF.H264.MaximumLTRFrames.Description="Long Term Reference (LTR) frames zijn een functie waarmee de encoder bepaalde frames in een reeks kan aanmerken als refereerbaar gedurende een lange tijd.\nLTR frames kunnen niet met B-frames gebruikt worden, en de encoder zal B-frames ook uitzetten als deze gebruikt worden."
86
+AMF.H264.MaximumAccessUnitSize="Maximale Access Unit grootte"
87
+AMF.H264.MaximumAccessUnitSize.Description="De maximale grootte voor een Access Unit voor een NAL."
88
+AMF.H264.HeaderInsertionSpacing="Header Insertion Spacing"
89
+AMF.H264.HeaderInsertionSpacing.Description="Hoeveel frames er tussen NAL headers moeten zitten."
90
+AMF.H264.WaitForTask="Wacht op taak"
91
+AMF.H264.WaitForTask.Description="Onbekend, experimenteel"
92
+AMF.H264.PreAnalysisPass="Pre-analyse pass"
93
+AMF.H264.PreAnalysisPass.Description="Onbekend, experimenteel"
94
+AMF.H264.VBAQ="VBAQ"
95
+AMF.H264.VBAQ.Description="Onbekend, experimenteel"
96
+AMF.H264.GOPSize="GOP-grootte"
97
+AMF.H264.GOPSize.Description="Onbekend, experimenteel"
98
+AMF.H264.GOPAlignment="GOP-uitlijning"
99
+AMF.H264.GOPAlignment.Description="Onbekend, experimenteel"
100
+AMF.H264.MaximumReferenceFrames="Maximale referentieframes"
101
+AMF.H264.MaximumReferenceFrames.Description="Onbekend, experimenteel"
102
+AMF.H264.SlicesPerFrame="Segmenten per frame"
103
+AMF.H264.SlicesPerFrame.Description="Hoeveel I-frame segmenten moeten er worden opgeslagen bij elke frame?\nEen waarde van nul laat de encoder bepalen.\nIntra-refresh encoding wordt gebruikt voor snellere weergave van en zoeken door video."
104
+AMF.H264.SliceMode="Slice-modus"
105
+AMF.H264.SliceMode.Description="Onbekend, experimenteel"
106
+AMF.H264.MaximumSliceSize="Maximale Segmentgrootte"
107
+AMF.H264.MaximumSliceSize.Description="Onbekend, experimenteel"
108
+AMF.H264.SliceControlMode="Slice Control Mode"
109
+AMF.H264.SliceControlMode.Description="Onbekend, experimenteel"
110
+AMF.H264.SliceControlSize="Slice Control Size"
111
+AMF.H264.SliceControlSize.Description="Onbekend, experimenteel"
112
+AMF.H264.IntraRefresh.NumberOfStripes="Intra-Refresh Number of Stripes"
113
+AMF.H264.IntraRefresh.NumberOfStripes.Description="Onbekend, experimenteel"
114
+AMF.H264.IntraRefresh.MacroblocksPerSlot="Intra-Refresh Macroblocks per Slot"
115
+AMF.H264.IntraRefresh.MacroblocksPerSlot.Description="Hoeveel Macroblocks moeten er in elk slot worden opgeslagen?\nEen waarde van 0 schakelt deze functie uit.\nIntra-Refresh encoding wordt gebruikt voor snellere weergave van en zoeken door video."
116
+AMF.H264.VideoAPI="Video API"
117
+AMF.H264.VideoAPI.Description="Welke API gebruikt moet worden voor encoden."
118
+AMF.H264.VideoAdapter="Videoadapter"
119
+AMF.H264.VideoAdapter.Description="Welke apter gebruikt moet worden voor encoding."
120
+AMF.H264.OpenCL="OpenCL"
121
+AMF.H264.OpenCL.Description="Moet de encoder OpenCL gebruiken om de individuele frames te leveren?"
122
+AMF.H264.View="Weergavemodus"
123
+AMF.H264.View.Description="Welke eigenschappen moeten getoond worden?\nHet gebruiken van '\@AMF.H264.View.Master\@' diskwalificeert je voor het ontvangen van ondersteuning."
124
+AMF.H264.View.Basic="Simpel"
125
+AMF.H264.View.Advanced="Geavanceerd"
126
+AMF.H264.View.Expert="Expert"
127
+AMF.H264.View.Master="Meester"
128
+AMF.H264.Debug="Debug"
129
+AMF.H264.Debug.Description="Schakel extra debug-logging in, dit moet actief zijn als je ondersteuning nodig hebt met deze encoder."
130
131
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/pl-PL.ini -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Resources/locale/pl-PL.ini
Changed
13
1
2
AMF.H264.ScanType="Metoda skanowania"
3
AMF.H264.ScanType.Progressive="Progresywne"
4
AMF.H264.ScanType.Interlaced="Z przeplotem"
5
+AMF.H264.MotionEstimation="Szacowania ruchu"
6
+AMF.H264.MotionEstimation.None="Żaden"
7
+AMF.H264.MotionEstimation.Half="Pół piksela"
8
+AMF.H264.MotionEstimation.Quarter="Kwartał piksela"
9
+AMF.H264.MotionEstimation.Both="Pół i kwartał piksela"
10
AMF.H264.CodingType="Typ kodowania"
11
AMF.H264.MaximumAccessUnitSize="Maksymalny rozmiar Access Unit"
12
AMF.H264.MaximumAccessUnitSize.Description="Maksymalny rozmiar Access Unit. Wartość 0 umożliwia enkoderowi wybranie najlepszej wartości."
13
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/ru-RU.ini -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Resources/locale/ru-RU.ini
Changed
98
1
2
AMF.H264.QualityPreset.Balanced="Баланс"
3
AMF.H264.QualityPreset.Quality="Качество"
4
AMF.H264.Profile="Профиль кодирования"
5
+AMF.H264.Profile.Description="Какой профиль формата H.264, использовать для кодирования, отсортированный от высочайшего качества для самой широкой поддержки."
6
AMF.H264.ProfileLevel="Уровень профиля"
7
AMF.H264.ProfileLevel.Description="Какой уровень профиля H.264 использовать для кодирования:\n- 'Автоматически' выбирает наиболее подходящий уровень под выбранную частоту и размер кадра,\n- '4.1' поддерживает 1920x1080 30FPS, 1280x720 60FPS, 960x540 90FPS\n- '4.2' поддерживает 1920x1080 60FPS, 1280x720 120FPS, 960x540 172FPS\n- '5.0' поддерживает 1920x1080 60FPS, 1280x720 144FPS, 960x540 172FPS\n- '5.1' поддерживает 3840x2160 30FPS, 1920x1080 120FPS, 1280x720 172FPS, 960x540 172FPS\n- '5.2' поддерживает 3840x2160 60FPS, 1920x1080 172FPS, 1280x720 172FPS, 960x540 172FPS"
8
AMF.H264.RateControlMethod="Метод кодирования"
9
+AMF.H264.RateControlMethod.Description="Как оценить способ контроля должны быть использованы:\n- '\@AMF.H264.RateControlMethod.CQP\@' назначает фиксированные I-/P-/B-Значения кадра QP,\n- '\@AMF.H264.RateControlMethod.CBR\@' остается в данном целевом Битрейте (используя данные заполнителя) (рекомендуется для стрима),\n-'\@AMF.H264.RateControlMethod.VBR\@' остается ниже пика Битрейта,\n-'\@AMF.H264.RateControlMethod.VBR_LAT\@' остается близко к целевому Битрейту, если задержка GPU и нагрузки позволяют, в противном случае будут использовать более высокий Битрейт (рекомендуется для стрима)."
10
AMF.H264.RateControlMethod.CQP="CQP: постоянное качество"
11
AMF.H264.RateControlMethod.CBR="CBR: постоянный битрейт"
12
AMF.H264.RateControlMethod.VBR.Peak="VBR: переменный битрейт (Ограничение пиков)"
13
14
AMF.H264.QP.Maximum="Максимальное QP"
15
AMF.H264.QP.Maximum.Description="Наибольшее значение QP (Параметр квантования) для использования в кадре."
16
AMF.H264.QP.IFrame="I-кадр QP"
17
+AMF.H264.QP.IFrame.Description="Фиксированное значение QP используемое для I-Кадров."
18
AMF.H264.QP.PFrame="P-кадр QP"
19
+AMF.H264.QP.PFrame.Description="Фиксированное значение QP используемое для P-Кадров."
20
AMF.H264.QP.BFrame="B-кадр QP"
21
AMF.H264.QP.BFrame.Description="Фиксированное значение QP (Параметр квантования) для использования в B-Кадрах."
22
AMF.H264.VBVBuffer="Буфер VBV"
23
AMF.H264.VBVBuffer.Description="Какой метод следует использовать для определения Размера буфера VBV:\n- '\@AMF.Util.Automatic\@' рассчитывает размер ограничивающийся строгостью,\n- '\@AMF.Util.Manual\@' позволяет пользователю контролировать размер буфера.\nVBV (Верификатор буферизации видео) буфер используется некоторыми Методами управления скоростью, чтобы сохранить общий битрейт в пределах заданных ограничений."
24
AMF.H264.VBVBuffer.Strictness="Строгость буфера VBV"
25
+AMF.H264.VBVBuffer.Strictness.Description="Определяет жесткость буфера vbv, при 100% будет максимально жестким и 0% будет неограниченным."
26
AMF.H264.VBVBuffer.Size="Размер буфера VBV"
27
+AMF.H264.VBVBuffer.Size.Description="Размер буфера vbv, которая используется для управления скорости передачи данных в последовательности."
28
AMF.H264.VBVBuffer.Fullness="Заполнение буфера VBV"
29
AMF.H264.VBVBuffer.Fullness.Description="Изначальная степень заполнения VBV буфера, будет влиять только на первоначальную последовательность кодирования."
30
AMF.H264.FillerData="Данные наполнителя"
31
+AMF.H264.FillerData.Description="Включение данных наполнителей позволяет кодировщику сохранять, по крайней мере, целевой Битрейт, заполняя оставшееся пространство в последовательности с пустой информации."
32
AMF.H264.FrameSkipping="Пропуск кадров"
33
+AMF.H264.FrameSkipping.Description="Пропуск кадров позволяет кодировщику падение кадров в целях соответствия требованиям целевого битрейта.\nКогда в энкодере пропадает рамка вместо этого вставьте повторять-последний кадр NAL в стрим.\nМожет помочь с очень низким битрейтом."
34
AMF.H264.EnforceHRDCompatibility="Принудительная HRD совместимость"
35
+AMF.H264.EnforceHRDCompatibility.Description="Соблюдение гипотетическому эталону Декодера ограничения, которые ограничивают максимальное значение QP изменения в кадре."
36
AMF.H264.KeyframeInterval="Интервал ключевых кадров"
37
AMF.H264.KeyframeInterval.Description="Сколько секунд должен быть просадок кадров.\nТакже контролирует GOP Size."
38
AMF.H264.IDRPeriod="Период IDR"
39
AMF.H264.IDRPeriod.Description="Определяет расстояние между Мгновенными обновлениями декодирования (IDR) в кадрах. Так же контролирует размер последовательности GOP."
40
+AMF.H264.BFrame.Pattern="B-Кадры"
41
+AMF.H264.BFrame.Pattern.Description="Количество B-кадров использованное при кодировании.\nПоддерживается 2-й и 3-й VCE карт поколения. Негативно влияет на производительность кодирования."
42
+AMF.H264.BFrame.DeltaQP="QP дельта для B-Кадров"
43
+AMF.H264.BFrame.DeltaQP.Description="Значение дельты QP в последних I- или P-Кадров для нессылаемых B-Кадров."
44
+AMF.H264.BFrame.Reference="Ссылаемые B-Кадры"
45
+AMF.H264.BFrame.Reference.Description="Разрешить B-Кадру так же использовать B-Кадры как ссылки, вместо просто P- и I-Кадров."
46
+AMF.H264.BFrame.ReferenceDeltaQP="Дельта QP для ссылаемых B-кадров"
47
+AMF.H264.BFrame.ReferenceDeltaQP.Description="Значение дельты QP в последних I- или P-Кадров для ссылаемых B-Кадров."
48
AMF.H264.DeblockingFilter="Фильтр деблокинга"
49
AMF.H264.DeblockingFilter.Description="Устанавливает флаг, что декодер может использовать фильтр удаления блочности для прямой трансляции."
50
AMF.H264.ScanType="Развертка"
51
52
AMF.H264.MotionEstimation.Half="Пол-пиксельная"
53
AMF.H264.MotionEstimation.Quarter="Четверть-пиксельная"
54
AMF.H264.MotionEstimation.Both="Пол- & Четверть-пиксельная"
55
+AMF.H264.CodingType="Тип кодирования"
56
+AMF.H264.CodingType.Description="Какой тип кодирования использовать:\n* \@AMF.Util.Default\@ позволяет решать AMF (рекомендуется).\n* CALVC (контекстно-Адаптивное с переменной длинной кодирования) - это быстрее, но больше.\n* CABAC (контекстно-Адаптивное Двоичное арифметическое кодирование) - это медленнее, но меньше."
57
AMF.H264.MaximumLTRFrames="Максимум LTR-кадров"
58
+AMF.H264.MaximumLTRFrames.Description="Long Term Reference (LTR) Frames - функция позволяющая кодировщику помечать определенные кадры в последовательности как ссылаемые.\nLTR Frames не может использоваться B-кадры и энкодер будет отключать B-кадры, если они используются."
59
AMF.H264.MaximumAccessUnitSize="Максимальный Размер Блока Доступа"
60
AMF.H264.MaximumAccessUnitSize.Description="Большой размер блока доступа для NAL. Значение 0 позволяет регулировать, чтобы выбрать лучший."
61
AMF.H264.HeaderInsertionSpacing="Расстояние вставки заголовка"
62
AMF.H264.HeaderInsertionSpacing.Description="Сколько кадров должно быть между заголовками NAL. Не рекомендуется менять значение с 0 (автоматически)."
63
+AMF.H264.WaitForTask="Дождитесь Задач"
64
+AMF.H264.WaitForTask.Description="Неизвестно, Экспериментально"
65
+AMF.H264.PreAnalysisPass="Проход пред-анализа"
66
+AMF.H264.PreAnalysisPass.Description="Неизвестно, Экспериментально"
67
+AMF.H264.VBAQ="VBAQ"
68
+AMF.H264.VBAQ.Description="Неизвестно, Экспериментально"
69
+AMF.H264.GOPSize="Размер GOP"
70
+AMF.H264.GOPSize.Description="Неизвестно, Экспериментально"
71
+AMF.H264.GOPAlignment="Выравнивание GOP"
72
+AMF.H264.GOPAlignment.Description="Неизвестно, Экспериментально"
73
+AMF.H264.MaximumReferenceFrames="Максимум кадров-ссылок"
74
+AMF.H264.MaximumReferenceFrames.Description="Неизвестно, Экспериментально"
75
AMF.H264.SlicesPerFrame="Количество частей на кадр"
76
AMF.H264.SlicesPerFrame.Description="Сколько кусков I-Кадров должно быть сохранено в каждом кадре?\nЗначение 0 позволяет кодировщику выбирать \"на лету\".\nКодирование Intra-Refresh используется для быстрого воспроизведения и поиска при перемотке."
77
+AMF.H264.SliceMode="Режим Slice"
78
+AMF.H264.SliceMode.Description="Неизвестно, Экспериментально"
79
+AMF.H264.MaximumSliceSize="Максимальный размер Slice"
80
+AMF.H264.MaximumSliceSize.Description="Неизвестно, Экспериментально"
81
+AMF.H264.SliceControlMode="Режим управления Slice"
82
+AMF.H264.SliceControlMode.Description="Неизвестно, Экспериментально"
83
+AMF.H264.SliceControlSize="Размер элемента управления Slice"
84
+AMF.H264.SliceControlSize.Description="Неизвестно, Экспериментально"
85
+AMF.H264.IntraRefresh.NumberOfStripes="Число полос Intra-Refresh"
86
+AMF.H264.IntraRefresh.NumberOfStripes.Description="Неизвестно, Экспериментально"
87
+AMF.H264.IntraRefresh.MacroblocksPerSlot="Количество Intra-Refresh Макроблоков на слот"
88
+AMF.H264.IntraRefresh.MacroblocksPerSlot.Description="Сколько Макроблоков должно быть сохранено в каждом слоте?\nЗначение 0 отключает эту функцию.\nКодирование Intra-Refresh используется для быстрого воспроизведения и поиска при перемотке."
89
+AMF.H264.VideoAPI="Video API"
90
+AMF.H264.VideoAPI.Description="Какой API использовать для кодирования."
91
+AMF.H264.VideoAdapter="Видеоадаптер"
92
+AMF.H264.VideoAdapter.Description="Какой видеоадаптер использовать для кодирования."
93
+AMF.H264.OpenCL="OpenCL"
94
+AMF.H264.OpenCL.Description="Должен ли кодировщик использовать OpenCL для подтверждения индивидуальных кадров?"
95
AMF.H264.View="Режим просмотра"
96
AMF.H264.View.Description="Какие параметры должны быть видны. Вы не будете получать поддержку при использовании режимов 'Эксперт' и 'Мастер'."
97
AMF.H264.View.Basic="Обычный"
98
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/sv-SE.ini -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Resources/locale/sv-SE.ini
Changed
60
1
2
AMF.H264.Bitrate.Target.Description="Bithastighet att försöka uppnå i den övergripande sekvensen."
3
AMF.H264.Bitrate.Peak="Maximal bithastighet"
4
AMF.H264.QP.Minimum="Minimal QP"
5
+AMF.H264.QP.Minimum.Description="Lägsta QP-värde att använda i en bildruta."
6
AMF.H264.QP.Maximum="Maximal QP"
7
+AMF.H264.QP.Maximum.Description="Högsta QP-värde att använda i en bildruta."
8
+AMF.H264.QP.IFrame="QP för I-bildrutor"
9
+AMF.H264.QP.IFrame.Description="Konstant QP-värde att använda för I-bildrutor."
10
+AMF.H264.QP.PFrame="QP för P-bildrutor"
11
+AMF.H264.QP.PFrame.Description="Konstant QP-värde att använda för P-bildrutor."
12
+AMF.H264.QP.BFrame="QP för B-bildrutor"
13
+AMF.H264.QP.BFrame.Description="Konstant QP-värde att använda för B-bildrutor."
14
AMF.H264.VBVBuffer="VBV-buffert"
15
AMF.H264.VBVBuffer.Description="Vilken metod som ska användas för att bestämma VBV-buffertens storlek:\n- '\@AMF.Util.Automatic\@' beräknar storleken med hjälp av en strikt begränsning,\n- '\@AMF.Util.Manual\@' låter användaren kontrollera storleken.\nVBV-buffertern (Video Buffering Verifier) används av vissa Rate Control Methods för att hålla den övergripande bithastigheten inom de angivna begränsningarna."
16
AMF.H264.VBVBuffer.Strictness="Strikthet för VBV-buffert"
17
+AMF.H264.VBVBuffer.Strictness.Description="Bestämmer noggrannheten för VBV-bufferten, där 100% är så noggrann som möjligt och 0% är gränslös."
18
AMF.H264.VBVBuffer.Size="VBV-buffertstorlek"
19
+AMF.H264.FillerData="Fyllningsdata"
20
+AMF.H264.FillerData.Description="Fyllningsdata låter kodaren behålla önskad bithastighet genom att fylla upp det återstående utrymmet i en sekvens med tom information."
21
AMF.H264.FrameSkipping="Hoppa över bildrutor"
22
AMF.H264.EnforceHRDCompatibility="Tvinga HRD-kompatibilitet"
23
+AMF.H264.KeyframeInterval="Intervall för keyframes"
24
+AMF.H264.KeyframeInterval.Description="Definierar avståndet mellan keyframes i sekunder. Kontrollerar även GOP-sekvensens storlek."
25
AMF.H264.IDRPeriod="IDR-period"
26
AMF.H264.IDRPeriod.Description="Definierar avståndet mellan Instantaneous Decoding Refreshes (IDR) i bildrutor. Kontrollerar även GOP-sekvensens storlek."
27
+AMF.H264.BFrame.Pattern="B-bildrutor"
28
AMF.H264.DeblockingFilter="Avblockningsfilter"
29
AMF.H264.ScanType="Typ av skanning"
30
AMF.H264.ScanType.Description="Vilken skanningsmetod att använda, lämna alltid detta på '\@AMF.H264.ScanType.Progressive\@'."
31
32
AMF.H264.CodingType="Kodningstyp"
33
AMF.H264.CodingType.Description="Vilken typ av kodning som ska användas:\n* \@AMF.Util.Default\@ låter AMF bestämma (rekommenderas).\n* CALVC (Context-Adaptive Variable-Length Coding) är snabbare, men större.\n* CABAC (Context-Adaptive Binary Arithmetic Coding) är långsammare, men mindre."
34
AMF.H264.MaximumLTRFrames="Maximalt antal LTR-bildrutor"
35
+AMF.H264.HeaderInsertionSpacing.Description="Hur många bildrutor som borde vara mellan NAL-headers."
36
+AMF.H264.WaitForTask="Väntar på arbetsuppgifter"
37
+AMF.H264.WaitForTask.Description="Okänd, experimentell"
38
+AMF.H264.PreAnalysisPass.Description="Okänd, experimentell"
39
+AMF.H264.VBAQ="VBAQ"
40
+AMF.H264.VBAQ.Description="Okänd, experimentell"
41
+AMF.H264.GOPSize="GOP-storlek"
42
+AMF.H264.GOPSize.Description="Okänd, experimentell"
43
+AMF.H264.GOPAlignment="GOP-justering"
44
+AMF.H264.GOPAlignment.Description="Okänd, experimentell"
45
+AMF.H264.MaximumReferenceFrames.Description="Okänd, experimentell"
46
+AMF.H264.SliceMode.Description="Okänd, experimentell"
47
+AMF.H264.MaximumSliceSize.Description="Okänd, experimentell"
48
+AMF.H264.SliceControlMode.Description="Okänd, experimentell"
49
+AMF.H264.SliceControlSize.Description="Okänd, experimentell"
50
+AMF.H264.IntraRefresh.NumberOfStripes.Description="Okänd, experimentell"
51
+AMF.H264.IntraRefresh.MacroblocksPerSlot.Description="Hur många Macroblock bör lagras i varje plats?\nEtt värdet på 0 inaktiverar denna funktion.\nIntra-uppdaterade kodning används för snabbare uppspelning och sökning."
52
+AMF.H264.VideoAPI="Video-API"
53
+AMF.H264.VideoAPI.Description="Vilken API att använda för kodning."
54
+AMF.H264.VideoAdapter="Grafikkort"
55
+AMF.H264.OpenCL="OpenCL"
56
+AMF.H264.OpenCL.Description="Bör kodaren använda OpenCL för att skicka de individuella bildrutorna?"
57
AMF.H264.View="Visningsläge"
58
AMF.H264.View.Basic="Grundläggande"
59
AMF.H264.View.Advanced="Avancerad"
60
obs-studio-17.0.1.tar.xz/plugins/enc-amf/Resources/locale/tr-TR.ini
Added
54
1
2
+AMF.Util.Default="Varsayılan"
3
+AMF.Util.Automatic="Otomatik"
4
+AMF.Util.Manual="Elle"
5
+AMF.Util.Toggle.Disabled="Devre Dışı"
6
+AMF.Util.Toggle.Enabled="Etkin"
7
+AMF.H264.Preset="Ön Tanımlı"
8
+AMF.H264.Preset.ResetToDefaults="Varsayılan Ayarlara Geri Dön"
9
+AMF.H264.Preset.Recording="Kaydediliyor"
10
+AMF.H264.Preset.HighQuality="Yüksek Kalite"
11
+AMF.H264.Preset.Lossless="Kayıpsız"
12
+AMF.H264.Preset.Twitch="Twitch"
13
+AMF.H264.Preset.YouTube="YouTube"
14
+AMF.H264.Usage="Kullanım"
15
+AMF.H264.Usage.UltraLowLatency="Ultra Düşük Gecikme"
16
+AMF.H264.Usage.LowLatency="Düşük Gecikme"
17
+AMF.H264.QualityPreset.Speed="Hız"
18
+AMF.H264.QualityPreset.Balanced="Dengeli"
19
+AMF.H264.QualityPreset.Quality="Kalite"
20
+AMF.H264.Profile="Profil"
21
+AMF.H264.ProfileLevel="Profil Seviyesi"
22
+AMF.H264.Bitrate.Target="Hedef Bit Hızı"
23
+AMF.H264.QP.Minimum="Minimum QP"
24
+AMF.H264.QP.Maximum="Maksimum QP"
25
+AMF.H264.VBVBuffer.Size="VBV Arabellek Boyutu"
26
+AMF.H264.FrameSkipping="Kare Atlama"
27
+AMF.H264.ScanType="Tarama Türü"
28
+AMF.H264.MotionEstimation.None="Hiçbiri"
29
+AMF.H264.MotionEstimation.Half="Yarım Piksel"
30
+AMF.H264.MotionEstimation.Quarter="Çeyrek Piksel"
31
+AMF.H264.MotionEstimation.Both="Yarım ve Çeyrek Piksel"
32
+AMF.H264.WaitForTask.Description="Bilinmeyen, Deneysel"
33
+AMF.H264.PreAnalysisPass.Description="Bilinmeyen, Deneysel"
34
+AMF.H264.VBAQ="VBAQ"
35
+AMF.H264.VBAQ.Description="Bilinmeyen, Deneysel"
36
+AMF.H264.GOPSize.Description="Bilinmeyen, Deneysel"
37
+AMF.H264.GOPAlignment.Description="Bilinmeyen, Deneysel"
38
+AMF.H264.MaximumReferenceFrames.Description="Bilinmeyen, Deneysel"
39
+AMF.H264.SliceMode.Description="Bilinmeyen, Deneysel"
40
+AMF.H264.MaximumSliceSize.Description="Bilinmeyen, Deneysel"
41
+AMF.H264.SliceControlMode.Description="Bilinmeyen, Deneysel"
42
+AMF.H264.SliceControlSize.Description="Bilinmeyen, Deneysel"
43
+AMF.H264.IntraRefresh.NumberOfStripes.Description="Bilinmeyen, Deneysel"
44
+AMF.H264.VideoAPI="Video API"
45
+AMF.H264.VideoAdapter="Ekran Kartı"
46
+AMF.H264.OpenCL="OpenCL"
47
+AMF.H264.View="Görüntüleme Modu"
48
+AMF.H264.View.Basic="Temel"
49
+AMF.H264.View.Advanced="Gelişmiş"
50
+AMF.H264.View.Expert="Uzman"
51
+AMF.H264.View.Master="Usta"
52
+AMF.H264.Debug="Hata Ayıklama"
53
+
54
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/uk-UA.ini -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Resources/locale/uk-UA.ini
Changed
23
1
2
AMF.H264.BFrame.Pattern="B-кадри"
3
AMF.H264.BFrame.Pattern.Description="Визначає кількість послідовних B-кадрів у кодуванні.\nПідтримується принаймні 2-м та 3-м поколінням VCE карт. Маєнегативний вплив на продуктивність."
4
AMF.H264.BFrame.DeltaQP="B-кадри, відхил QP"
5
+AMF.H264.BFrame.DeltaQP.Description="Відхил QP (параметра квантування) для не опорних B-кадрів, по відношенню до I-кадрів та P-кадрів."
6
+AMF.H264.BFrame.Reference="B-кадри як опорні"
7
+AMF.H264.BFrame.Reference.Description="Дозволяє робити B-кадри опорними для інших B-кадрів в додаток до вже існуючих P- та I-кадрів."
8
+AMF.H264.BFrame.ReferenceDeltaQP="Відхил QP (параметра квантування) для опорних B-кадрів"
9
+AMF.H264.BFrame.ReferenceDeltaQP.Description="Відхил QP (параметра квантування) для опорних B-кадрів, по відношенню до I-кадрів та P-кадрів."
10
AMF.H264.DeblockingFilter="Деблокінг-фільтр"
11
AMF.H264.DeblockingFilter.Description="Встановлює позначку, що дозволяє декодеру використовувати Деблокінг-фільтр для цього відео."
12
AMF.H264.ScanType="Вид розгортки"
13
14
AMF.H264.SlicesPerFrame.Description="Скільки фрагментів I-кадрів буде у кожному кадру?\nНульове значення дозволяє енкодеру визначати цю кількість під час кодування самостійно.\nIntra-Refresh кодування використовується для більш швидкого відтворення та навігації."
15
AMF.H264.IntraRefresh.NumberOfStripes="Кількість рядків Intra-Refresh"
16
AMF.H264.IntraRefresh.MacroblocksPerSlot="Кількість Intra-Refresh макроблоків на слот"
17
+AMF.H264.IntraRefresh.MacroblocksPerSlot.Description="Визначає скільки Intra-Refresh макроблоків на слот можна використовувати при кодуванні.\nНульове значення вимикає цю опцію.\nIntra-Refresh кодування використовується для більш швидкого відтворення та навігації."
18
+AMF.H264.VideoAPI="Відео API"
19
+AMF.H264.VideoAPI.Description="Визначає який API використовувати для кодування."
20
AMF.H264.VideoAdapter="Відеоадаптер"
21
AMF.H264.VideoAdapter.Description="Визначає який відеоадаптер використовувати для кодування."
22
AMF.H264.OpenCL="OpenCL"
23
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/vi-VN.ini -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Resources/locale/vi-VN.ini
Changed
14
1
2
AMF.H264.MotionEstimation.Both="1/2 và 1/4 Pixel"
3
AMF.H264.CodingType="Coding Type"
4
AMF.H264.MaximumLTRFrames="LTR Frames tối đa"
5
+AMF.H264.GOPSize="Kích cỡ GOP"
6
+AMF.H264.GOPSize.Description="Không rõ, thử nghiệm"
7
AMF.H264.SlicesPerFrame="Lát cho mỗi khung hình"
8
+AMF.H264.VideoAPI="Video API"
9
+AMF.H264.VideoAdapter="Card đồ họa"
10
+AMF.H264.OpenCL="OpenCL"
11
AMF.H264.View="Chế độ xem"
12
AMF.H264.View.Basic="Cơ bản"
13
AMF.H264.View.Advanced="Nâng cao"
14
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Resources/locale/zh-TW.ini -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Resources/locale/zh-TW.ini
Changed
99
1
2
AMF.H264.Usage.UltraLowLatency="超低延遲"
3
AMF.H264.Usage.LowLatency="低延遲"
4
AMF.H264.QualityPreset="預設品質"
5
+AMF.H264.QualityPreset.Description="AMF 嘗試達成的預設品質:\n- '\@AMF.H264.QualityPreset.Speed\@' 為最快但最差的品質,\n- '\@AMF.H264.QualityPreset.Balanced\@' 為中間點,\n- '\@AMF.H264.QualityPreset.Quality\@' 在給定的位元速率下有最佳的品質。"
6
AMF.H264.QualityPreset.Speed="速度"
7
AMF.H264.QualityPreset.Balanced="平衡"
8
AMF.H264.QualityPreset.Quality="品質"
9
10
AMF.H264.QP.Maximum="最大 QP 值"
11
AMF.H264.QP.Maximum.Description="一個訊框中使用的最高 QP (量化參數) 值。"
12
AMF.H264.QP.IFrame="I-訊框 QP"
13
+AMF.H264.QP.IFrame.Description="I 訊框所使用的固定 QP 值"
14
AMF.H264.QP.PFrame="P-訊框 QP"
15
+AMF.H264.QP.PFrame.Description="P 訊框所使用的固定 QP 值"
16
AMF.H264.QP.BFrame="B-訊框 QP"
17
AMF.H264.QP.BFrame.Description="B-訊框使用的固定 QP (量化參數) 值。"
18
AMF.H264.VBVBuffer="VBV(Video Buffering Verifier) 緩衝區"
19
AMF.H264.VBVBuffer.Description="決定 VBV 緩衝區大小的方法:\n- '\@AMF.Util.Automatic\@' 根據嚴格性計算大小,\n- '\@AMF.Util.Manual\@' 允許使用者調整大小。\n 某些速率控制方法會使用 VBV (Video Buffering Verifier) 緩衝區讓整體的位元速率保持在給定的條件之內。"
20
AMF.H264.VBVBuffer.Strictness="VBV 緩衝區嚴格性"
21
+AMF.H264.VBVBuffer.Strictness.Description="決定 VBV 緩衝區的嚴密性,100% 表示盡可能的嚴格,0% 表示完全不限制。"
22
AMF.H264.VBVBuffer.Size="VBV 緩衝區大小"
23
+AMF.H264.VBVBuffer.Size.Description="VBV緩衝區的大小,這將用於過程中的位元速率控制"
24
AMF.H264.VBVBuffer.Fullness="初始 VBV 緩衝區填充度"
25
AMF.H264.VBVBuffer.Fullness.Description="VBV 緩衝區起始該多滿,將只影響編碼的起始。"
26
AMF.H264.FillerData="填塞空白資料"
27
AMF.H264.FillerData.Description="啟用填塞空白資料允許編碼器保持位元速率至少有目標位元速率,編碼器將會將不足的位元用空白訊息填滿"
28
AMF.H264.FrameSkipping="省略訊框"
29
+AMF.H264.FrameSkipping.Description="省略訊框允許編碼器在為了達成目標位元速率時省略部份訊框。\n當編碼器省略訊框時,他將插入重複上一個訊框的指令。\n對極低的目標位元速率有幫助。"
30
AMF.H264.EnforceHRDCompatibility="與 HRD 相容"
31
+AMF.H264.EnforceHRDCompatibility.Description="執行 Hypothetical Reference Decoder 限制,這將限制單一訊框內 QP 值的最大變化量。"
32
+AMF.H264.KeyframeInterval="關鍵訊框間隔"
33
+AMF.H264.KeyframeInterval.Description="以秒為單位,定義關鍵訊框之間的距離。同時也控制了 GOP 序列的大小。"
34
+AMF.H264.IDRPeriod="IDR 周期"
35
+AMF.H264.IDRPeriod.Description="以訊框為單位,定義瞬間解碼重新更新(Instantaneous Decoding Refreshes)間的距離。同時也控制了 GOP 序列的大小。"
36
+AMF.H264.BFrame.Pattern="B 訊框"
37
+AMF.H264.BFrame.Pattern.Description="編碼時使用的 B 訊框數量。\n搭載第二代和第三代影像編碼引擎的顯示卡支援此參數。對編碼效能會有不良影響。"
38
+AMF.H264.BFrame.DeltaQP="B 訊框的 QP 值變化"
39
+AMF.H264.BFrame.DeltaQP.Description="在沒使用可參照 B 訊框時, B 訊框與上一個I或P訊框間的QP值變化。"
40
+AMF.H264.BFrame.Reference="可參照 B 訊框"
41
+AMF.H264.BFrame.Reference.Description="允許 B 訊框也使用 B 訊框作為參照,而不限於 P 和 I 訊框。"
42
+AMF.H264.BFrame.ReferenceDeltaQP="可參照 B 訊框的 QP 值變化"
43
+AMF.H264.BFrame.ReferenceDeltaQP.Description="在使用可參照 B 訊框時,B 訊框與上一個 I 或 P 訊框間的 QP 值變化。"
44
AMF.H264.DeblockingFilter="去塊狀色斑濾鏡"
45
+AMF.H264.DeblockingFilter.Description="設定選項,讓解碼器可以使用去塊狀色斑濾鏡。"
46
AMF.H264.ScanType="掃描類型"
47
+AMF.H264.ScanType.Description="掃描方式,請確保此值為'\@AMF.H264.ScanType.Progressive\@'。"
48
AMF.H264.ScanType.Progressive="漸進式"
49
AMF.H264.ScanType.Interlaced="交错式"
50
AMF.H264.MotionEstimation="動態估算"
51
52
AMF.H264.MotionEstimation.Half="半像素"
53
AMF.H264.MotionEstimation.Quarter="四分之一像素"
54
AMF.H264.MotionEstimation.Both="半 & 四分之一像素"
55
-AMF.H264.MaximumLTRFrames="長期參照訊框(LTR)最大數量"
56
+AMF.H264.CodingType="Coding Type"
57
+AMF.H264.CodingType.Description="Which type of coding to use:\n* \@AMF.Util.Default\@ lets AMF decide (recommended).\n* CALVC (Context-Adaptive Variable-Length Coding) is faster, but larger.\n* CABAC (Context-Adaptive Binary Arithmetic Coding) is slower, but smaller."
58
+AMF.H264.MaximumLTRFrames="Maximum LTR Frames"
59
+AMF.H264.MaximumLTRFrames.Description="Long Term Reference (LTR) Frames are a feature that allows the encoder to flag certain frames in a sequence as referencable for a long time.\nLTR Frames can't be used with B-Frames and the encoder will disable B-Frames if these are used."
60
+AMF.H264.MaximumAccessUnitSize="Maximum Access Unit Size"
61
+AMF.H264.MaximumAccessUnitSize.Description="Largest Size of an Access Unit for a NAL."
62
+AMF.H264.HeaderInsertionSpacing="Header Insertion Spacing"
63
+AMF.H264.HeaderInsertionSpacing.Description="How many frames should be between NAL headers."
64
+AMF.H264.WaitForTask="Wait For Task"
65
+AMF.H264.WaitForTask.Description="Unknown, Experimental"
66
+AMF.H264.PreAnalysisPass="預分析階段"
67
+AMF.H264.PreAnalysisPass.Description="Unknown, Experimental"
68
+AMF.H264.VBAQ="VBAQ"
69
+AMF.H264.VBAQ.Description="Unknown, Experimental"
70
+AMF.H264.GOPSize="GOP Size"
71
+AMF.H264.GOPSize.Description="Unknown, Experimental"
72
+AMF.H264.GOPAlignment="GOP Alignment"
73
+AMF.H264.GOPAlignment.Description="Unknown, Experimental"
74
+AMF.H264.MaximumReferenceFrames="Maximum Reference Frames"
75
+AMF.H264.MaximumReferenceFrames.Description="Unknown, Experimental"
76
+AMF.H264.SlicesPerFrame="Slices Per Frame"
77
+AMF.H264.SlicesPerFrame.Description="How many I-Frame slices should be stored with each frame?\nA value of zero lets the encoder decide on the fly.\nIntra-Refresh encoding is used for faster playback and seeking."
78
+AMF.H264.SliceMode="Slice Mode"
79
+AMF.H264.SliceMode.Description="Unknown, Experimental"
80
+AMF.H264.MaximumSliceSize="Maximum Slice Size"
81
+AMF.H264.MaximumSliceSize.Description="Unknown, Experimental"
82
+AMF.H264.SliceControlMode="Slice Control Mode"
83
+AMF.H264.SliceControlMode.Description="Unknown, Experimental"
84
+AMF.H264.SliceControlSize="Slice Control Size"
85
+AMF.H264.SliceControlSize.Description="Unknown, Experimental"
86
+AMF.H264.IntraRefresh.NumberOfStripes="Intra-Refresh Number of Stripes"
87
+AMF.H264.IntraRefresh.NumberOfStripes.Description="Unknown, Experimental"
88
+AMF.H264.IntraRefresh.MacroblocksPerSlot="Intra-Refresh Macroblocks per Slot"
89
+AMF.H264.IntraRefresh.MacroblocksPerSlot.Description="How many Macroblocks should be stored in each slot?\nA value of 0 disables this feature.\nIntra-Refresh encoding is used for faster playback and seeking."
90
+AMF.H264.VideoAPI="影像 API"
91
+AMF.H264.VideoAPI.Description="用於編碼的API。"
92
+AMF.H264.VideoAdapter="顯示卡"
93
+AMF.H264.VideoAdapter.Description="用於編碼的顯示卡。"
94
+AMF.H264.OpenCL="OpenCL"
95
+AMF.H264.OpenCL.Description="編碼器應該使用 OpenCL 來發送各個訊框?"
96
AMF.H264.View="檢視模式"
97
AMF.H264.View.Description="該顯示哪些屬性?\n使用'\@AMF.H264.View.Master\@'時將不提供任何的支援。"
98
AMF.H264.View.Basic="基本"
99
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Source/amf-capabilities.cpp -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Source/amf-capabilities.cpp
Changed
218
1
2
3
void Plugin::AMD::VCECapabilities::ReportAdapterCapabilities(std::shared_ptr<Plugin::API::Base> api, Plugin::API::Adapter adapter) {
4
auto inst = GetInstance();
5
- VCEEncoderType types[] = {
6
- VCEEncoderType_AVC,
7
- VCEEncoderType_SVC,
8
+ H264EncoderType types[] = {
9
+ H264EncoderType::AVC,
10
+ H264EncoderType::SVC,
11
};
12
13
- AMF_LOG_INFO("Capabilities for Device '%s' on API %s:",
14
- adapter.Name.c_str(),
15
- api->GetName().c_str());
16
+ AMF_LOG_INFO("Capabilities for %s adapter '%s':",
17
+ api->GetName().c_str(),
18
+ adapter.Name.c_str());
19
20
for (auto type : types) {
21
ReportAdapterTypeCapabilities(api, adapter, type);
22
}
23
}
24
25
-void Plugin::AMD::VCECapabilities::ReportAdapterTypeCapabilities(std::shared_ptr<Plugin::API::Base> api, Plugin::API::Adapter adapter, VCEEncoderType type) {
26
+void Plugin::AMD::VCECapabilities::ReportAdapterTypeCapabilities(std::shared_ptr<Plugin::API::Base> api, Plugin::API::Adapter adapter, H264EncoderType type) {
27
auto inst = GetInstance();
28
auto caps = inst->GetAdapterCapabilities(api, adapter, type);
29
30
AMF_LOG_INFO(" %s (Acceleration: %s)",
31
- (type == VCEEncoderType_AVC ? "AVC" : (type == VCEEncoderType_SVC ? "SVC" : (type == VCEEncoderType_HEVC ? "HEVC" : "Unknown"))),
32
+ (type == H264EncoderType::AVC ? "AVC" : (type == H264EncoderType::SVC ? "SVC" : "Unknown")),
33
(caps.acceleration_type == amf::AMF_ACCEL_SOFTWARE ? "Software" : (caps.acceleration_type == amf::AMF_ACCEL_GPU ? "GPU" : (caps.acceleration_type == amf::AMF_ACCEL_HARDWARE ? "Hardware" : "None")))
34
);
35
36
37
return;
38
39
AMF_LOG_INFO(" Limits");
40
- AMF_LOG_INFO(" Profile: %s", Plugin::Utility::ProfileAsString((VCEProfile)caps.maxProfile));
41
+ AMF_LOG_INFO(" Profile: %s", Plugin::Utility::ProfileAsString((H264Profile)caps.maxProfile));
42
AMF_LOG_INFO(" Profile Level: %ld.%ld", caps.maxProfileLevel / 10, caps.maxProfileLevel % 10);
43
AMF_LOG_INFO(" Bitrate: %ld", caps.maxBitrate);
44
AMF_LOG_INFO(" Reference Frames: %ld (min) - %ld (max)", caps.minReferenceFrames, caps.maxReferenceFrames);
45
- if (type == VCEEncoderType_SVC)
46
+ if (type == H264EncoderType::SVC)
47
AMF_LOG_INFO(" Temporal Layers: %ld", caps.maxTemporalLayers);
48
AMF_LOG_INFO(" Features");
49
AMF_LOG_INFO(" B-Frames: %s", caps.supportsBFrames ? "Supported" : "Not Supported");
50
51
ReportAdapterTypeIOCapabilities(api, adapter, type, true);
52
}
53
54
-void Plugin::AMD::VCECapabilities::ReportAdapterTypeIOCapabilities(std::shared_ptr<Plugin::API::Base> api, Plugin::API::Adapter adapter, VCEEncoderType type, bool output) {
55
+void Plugin::AMD::VCECapabilities::ReportAdapterTypeIOCapabilities(std::shared_ptr<Plugin::API::Base> api, Plugin::API::Adapter adapter, H264EncoderType type, bool output) {
56
auto amf = Plugin::AMD::AMF::GetInstance();
57
58
auto inst = GetInstance();
59
60
try {
61
adapters = api->EnumerateAdapters();
62
} catch (std::exception e) {
63
- AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> Unexpected exception while enumerating adapters for API '%s':", api->GetName());
64
- AMF_LOG_ERROR("%s", e.what());
65
+ AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> Exception while enumerating %s adapters: %s.",
66
+ api->GetName(),
67
+ e.what());
68
continue;
69
} catch (...) {
70
- AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> Unexpected critical exception while enumerating adapters for API '%s'.", api->GetName());
71
+ AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> Critical exception while enumerating %s adapters.",
72
+ api->GetName());
73
throw;
74
}
75
76
for (auto adapter : adapters) {
77
// Create AMF Instance
78
amf::AMFContextPtr amfContext;
79
- if (amfFactory->CreateContext(&amfContext) != AMF_OK) {
80
- AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> CreateContext failed for device '%s', error %ls (code %d).",
81
+ res = amfFactory->CreateContext(&amfContext);
82
+ if (res != AMF_OK) {
83
+ AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> Unable to create context on %s adapter '%s', error %ls (code %lld).",
84
+ api->GetName().c_str(),
85
adapter.Name.c_str(),
86
amfInstance->GetTrace()->GetResultText(res),
87
res);
88
89
try {
90
apiInst = api->CreateInstanceOnAdapter(adapter);
91
} catch (std::exception e) {
92
- AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> Unexpected exception while testing adapter '%s' on API '%s':", adapter.Name, api->GetName());
93
- AMF_LOG_ERROR("%s", e.what());
94
+ AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> Exception while intializing %s adapter '%s': %s.",
95
+ api->GetName(),
96
+ adapter.Name,
97
+ e.what());
98
continue;
99
} catch (...) {
100
- AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> Unexpected critical exceptionwhile testing adapter '%s' on API '%s'.", adapter.Name, api->GetName());
101
+ AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> Critical exception while intializing %s adapter '%s'.",
102
+ api->GetName(),
103
+ adapter.Name);
104
throw;
105
}
106
switch (api->GetType()) {
107
- case Plugin::API::APIType_Direct3D11:
108
+ case Plugin::API::Type::Direct3D11:
109
res = amfContext->InitDX11(api->GetContextFromInstance(apiInst));
110
break;
111
- case Plugin::API::APIType_Direct3D9:
112
+ case Plugin::API::Type::Direct3D9:
113
res = amfContext->InitDX9(api->GetContextFromInstance(apiInst));
114
break;
115
- case Plugin::API::APIType_OpenGL:
116
+ case Plugin::API::Type::OpenGL:
117
res = amfContext->InitOpenGL(api->GetContextFromInstance(apiInst), nullptr, nullptr);
118
break;
119
default:
120
121
break;
122
}
123
if (res != AMF_OK) {
124
- AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> Init failed for device '%s', error %ls (code %d).",
125
+ AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> Initialization failed for %s adapter '%s', error %ls (code %lld).",
126
+ api->GetName(),
127
adapter.Name.c_str(),
128
amfInstance->GetTrace()->GetResultText(res),
129
res);
130
continue;
131
}
132
133
- VCEEncoderType types[] = {
134
- VCEEncoderType_AVC,
135
- VCEEncoderType_SVC
136
+ H264EncoderType types[] = {
137
+ H264EncoderType::AVC,
138
+ H264EncoderType::SVC
139
};
140
for (auto type : types) {
141
VCEDeviceCapabilities devCaps = VCEDeviceCapabilities();
142
143
amf::AMFComponentPtr amfComponent;
144
- if (amfFactory->CreateComponent(amfContext,
145
+ res = amfFactory->CreateComponent(amfContext,
146
Plugin::Utility::VCEEncoderTypeAsAMF(type),
147
- &amfComponent) != AMF_OK) {
148
- AMF_LOG_ERROR("CreateComponent failed for device '%s' with codec '%s', error %ls (code %d).",
149
+ &amfComponent);
150
+ if (res != AMF_OK) {
151
+ AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> Unable to create component for %s adapter '%s' with codec '%s', error %ls (code %lld).",
152
+ api->GetName(),
153
adapter.Name.c_str(),
154
Plugin::Utility::VCEEncoderTypeAsString(type),
155
- amfInstance->GetTrace()->GetResultText(res),
156
- res);
157
+ amfInstance->GetTrace()->GetResultText(res), res);
158
continue;
159
}
160
161
amf::AMFCapsPtr amfCaps;
162
res = amfComponent->GetCaps(&amfCaps);
163
if (res != AMF_OK) {
164
- AMF_LOG_ERROR("GetCaps failed for device '%s' with codec '%s', error %ls (code %d).",
165
+ AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> Unable to query capabilities for %s adapter '%s' with codec '%s', error %ls (code %lld).",
166
+ api->GetName(),
167
adapter.Name.c_str(),
168
Plugin::Utility::VCEEncoderTypeAsString(type),
169
- amfInstance->GetTrace()->GetResultText(res),
170
- res);
171
+ amfInstance->GetTrace()->GetResultText(res), res);
172
amfComponent->Terminate();
173
continue;
174
}
175
176
amfCaps->GetProperty(AMF_VIDEO_ENCODER_CAP_FIXED_SLICE_MODE, &(devCaps.supportsFixedSliceMode));
177
amfCaps->GetProperty(AMF_VIDEO_ENCODER_CAP_NUM_OF_HW_INSTANCES, &(devCaps.maxNumOfHwInstances));
178
179
- if (GetIOCapability(false, amfCaps, &(devCaps.input)) != AMF_OK)
180
- AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> GetInputCaps failed for device '%s' with codec '%ls', error %ls (code %d).",
181
+ res = GetIOCapability(false, amfCaps, &(devCaps.input));
182
+ if (res != AMF_OK)
183
+ AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> Unable to query input capabilities for %s adapter '%s' with codec '%s', error %ls (code %lld).",
184
+ api->GetName(),
185
adapter.Name.c_str(),
186
Plugin::Utility::VCEEncoderTypeAsString(type),
187
amfInstance->GetTrace()->GetResultText(res), res);
188
189
- if (GetIOCapability(true, amfCaps, &(devCaps.output)) != AMF_OK)
190
- AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> GetOutputCaps failed capabilities for device '%s' with codec '%ls', error %ls (code %d).",
191
+ res = GetIOCapability(true, amfCaps, &(devCaps.output));
192
+ if (res != AMF_OK)
193
+ AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> Unable to query output capabilities for %s adapter '%s' with codec '%s', error %ls (code %lld).",
194
+ api->GetName(),
195
adapter.Name.c_str(),
196
Plugin::Utility::VCEEncoderTypeAsString(type),
197
amfInstance->GetTrace()->GetResultText(res), res);
198
199
return true;
200
}
201
202
-std::vector<std::pair<VCEEncoderType, VCEDeviceCapabilities>> Plugin::AMD::VCECapabilities::GetAllAdapterCapabilities(std::shared_ptr<Plugin::API::Base> api, Plugin::API::Adapter adapter) {
203
- std::vector<std::pair<VCEEncoderType, VCEDeviceCapabilities>> caps;
204
+std::vector<std::pair<H264EncoderType, VCEDeviceCapabilities>> Plugin::AMD::VCECapabilities::GetAllAdapterCapabilities(std::shared_ptr<Plugin::API::Base> api, Plugin::API::Adapter adapter) {
205
+ std::vector<std::pair<H264EncoderType, VCEDeviceCapabilities>> caps;
206
for (auto kv : capabilityMap) {
207
auto apiName = std::get<0>(kv.first);
208
auto adapter = std::get<1>(kv.first);
209
210
return caps;
211
}
212
213
-Plugin::AMD::VCEDeviceCapabilities Plugin::AMD::VCECapabilities::GetAdapterCapabilities(std::shared_ptr<Plugin::API::Base> api, Plugin::API::Adapter adapter, VCEEncoderType type) {
214
+Plugin::AMD::VCEDeviceCapabilities Plugin::AMD::VCECapabilities::GetAdapterCapabilities(std::shared_ptr<Plugin::API::Base> api, Plugin::API::Adapter adapter, H264EncoderType type) {
215
auto key = std::make_tuple(api->GetName(), adapter, type);
216
217
if (capabilityMap.count(key) == 0)
218
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Source/amf-h264.cpp -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Source/amf-h264.cpp
Changed
1678
1
2
// Code
3
//////////////////////////////////////////////////////////////////////////
4
5
+#define AMF_PROPERTY_FRAME L"Frame"
6
+#define AMF_PROPERTY_TIME_SENDINPUT L"TimeSendInput"
7
+#define AMF_PROPERTY_TIME_CREATESURFACE L"TimeCreateSurface"
8
+#define AMF_PROPERTY_TIME_CONVERT L"TimeConvert"
9
+#define AMF_PROPERTY_TIME_ENCODE L"TimeEncode"
10
+
11
// Logging and Exception Helpers
12
static void FormatTextWithAMFError(std::vector<char>* buffer, const char* format, AMF_RESULT res) {
13
sprintf(buffer->data(), format, Plugin::AMD::AMF::GetInstance()->GetTrace()->GetResultText(res), res);
14
15
}
16
#endif
17
18
-Plugin::AMD::VCEEncoder::VCEEncoder(
19
- VCEEncoderType p_Type,
20
+Plugin::AMD::H264Encoder::H264Encoder(
21
+ H264EncoderType p_Type,
22
std::string p_VideoAPI,
23
uint64_t p_VideoAdapterId,
24
bool p_OpenCL,
25
- VCEColorFormat p_SurfaceFormat/* = VCESurfaceFormat_NV12*/
26
+ H264ColorFormat p_SurfaceFormat/* = VCESurfaceFormat_NV12*/
27
) {
28
#pragma region Assign Default Values
29
m_EncoderType = p_Type;
30
31
m_FrameRate.first = 30; m_FrameRate.second = 1;
32
m_FrameRateDivisor = ((double_t)m_FrameRate.first / (double_t)m_FrameRate.second);
33
m_FrameRateReverseDivisor = ((double_t)m_FrameRate.second / (double_t)m_FrameRate.first);
34
- m_InputQueueLimit = (uint32_t)(m_FrameRateDivisor);
35
+ m_InputQueueLimit = (uint32_t)(m_FrameRateDivisor * 3);
36
m_InputQueueLastSize = 0;
37
m_TimerPeriod = 1;
38
m_LastQueueWarnMessageTime = std::chrono::high_resolution_clock::time_point(std::chrono::high_resolution_clock::duration(0));
39
40
m_APIAdapter = m_API->GetAdapterById(p_VideoAdapterId & UINT_MAX, (p_VideoAdapterId >> 32) & UINT_MAX);
41
m_APIInstance = m_API->CreateInstanceOnAdapter(m_APIAdapter);
42
switch (m_API->GetType()) {
43
- case Plugin::API::APIType_Direct3D11:
44
- m_MemoryType = VCEMemoryType_DirectX11;
45
+ case Plugin::API::Type::Direct3D11:
46
+ m_MemoryType = H264MemoryType::DirectX11;
47
res = m_AMFContext->InitDX11(m_API->GetContextFromInstance(m_APIInstance));
48
break;
49
- case Plugin::API::APIType_Direct3D9:
50
- m_MemoryType = VCEMemoryType_DirectX9;
51
+ case Plugin::API::Type::Direct3D9:
52
+ m_MemoryType = H264MemoryType::DirectX11;
53
res = m_AMFContext->InitDX9(m_API->GetContextFromInstance(m_APIInstance));
54
break;
55
- case Plugin::API::APIType_OpenGL:
56
- m_MemoryType = VCEMemoryType_OpenGL;
57
+ case Plugin::API::Type::OpenGL:
58
+ m_MemoryType = H264MemoryType::OpenGL;
59
res = m_AMFContext->InitOpenGL(m_API->GetContextFromInstance(m_APIInstance), GetDesktopWindow(), nullptr);
60
break;
61
- case Plugin::API::APIType_Host:
62
- m_MemoryType = VCEMemoryType_Host;
63
+ case Plugin::API::Type::Host:
64
+ m_MemoryType = H264MemoryType::Host;
65
m_OpenCL = false;
66
break;
67
}
68
69
/// Create the AMF Converter component.
70
if (m_AMFFactory->CreateComponent(m_AMFContext, AMFVideoConverter, &m_AMFConverter) != AMF_OK)
71
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Unable to create VideoConverter component, error %ls (code %ld).", res);
72
- if (m_AMFConverter->SetProperty(AMF_VIDEO_CONVERTER_MEMORY_TYPE, Utility::MemoryTypeAsAMF(m_MemoryType)) != AMF_OK)
73
- ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Memory Type not supported by VideoConverter component, error %ls (code %ld).", res);
74
- if (m_AMFConverter->SetProperty(AMF_VIDEO_CONVERTER_OUTPUT_FORMAT, Utility::SurfaceFormatAsAMF(m_ColorFormat)))
75
- ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Color Format not supported by VideoConverter component, error %ls (code %ld).", res);
76
77
#ifdef _DEBUG
78
printDebugInfo(m_AMFEncoder);
79
80
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Initialized.");
81
}
82
83
-Plugin::AMD::VCEEncoder::~VCEEncoder() {
84
+Plugin::AMD::H264Encoder::~H264Encoder() {
85
if (m_Flag_IsStarted)
86
Stop();
87
88
89
m_API = nullptr;
90
}
91
92
-void Plugin::AMD::VCEEncoder::Start() {
93
+void Plugin::AMD::H264Encoder::Start() {
94
+ AMF_RESULT res = AMF_UNEXPECTED;
95
+
96
// Set proper Timer resolution.
97
m_TimerPeriod = 1;
98
while (timeBeginPeriod(m_TimerPeriod) == TIMERR_NOCANDO) {
99
++m_TimerPeriod;
100
}
101
102
- // Create Encoder
103
- AMF_RESULT res = m_AMFEncoder->Init(Utility::SurfaceFormatAsAMF(m_ColorFormat),
104
- m_FrameSize.first, m_FrameSize.second);
105
- if (res != AMF_OK)
106
- ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Encoder initialization failed with error %ls (code %ld).", res);
107
-
108
- // Create Converter
109
- m_AMFConverter->SetProperty(AMF_VIDEO_CONVERTER_COLOR_PROFILE, this->GetColorProfile());
110
+ // Initialize Converter
111
+ if (m_AMFConverter->SetProperty(AMF_VIDEO_CONVERTER_MEMORY_TYPE, Utility::MemoryTypeAsAMF(m_MemoryType)) != AMF_OK)
112
+ ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Memory Type not supported by VideoConverter component, error %ls (code %ld).", res);
113
+ if (m_AMFConverter->SetProperty(AMF_VIDEO_CONVERTER_OUTPUT_FORMAT, amf::AMF_SURFACE_NV12))
114
+ ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Color Format not supported by VideoConverter component, error %ls (code %ld).", res);
115
+ m_AMFConverter->SetProperty(AMF_VIDEO_CONVERTER_COLOR_PROFILE, (size_t)this->GetColorProfile());
116
if (m_AMFConverter->SetProperty(L"FullRangeColor", this->IsFullRangeColorEnabled()) != AMF_OK)
117
m_AMFConverter->SetProperty(L"NominalRange", this->IsFullRangeColorEnabled());
118
-
119
res = m_AMFConverter->Init(Utility::SurfaceFormatAsAMF(m_ColorFormat), m_FrameSize.first, m_FrameSize.second);
120
if (res != AMF_OK)
121
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Converter initialization failed with error %ls (code %ld).", res);
122
123
+ // Initialize Encoder
124
+ res = m_AMFEncoder->Init(amf::AMF_SURFACE_NV12,
125
+ m_FrameSize.first, m_FrameSize.second);
126
+ if (res != AMF_OK)
127
+ ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Encoder initialization failed with error %ls (code %ld).", res);
128
+
129
m_Flag_IsStarted = true;
130
131
// Threading
132
- m_Input.thread = std::thread(&(Plugin::AMD::VCEEncoder::InputThreadMain), this);
133
- m_Output.thread = std::thread(&(Plugin::AMD::VCEEncoder::OutputThreadMain), this);
134
+ m_Input.thread = std::thread(&(Plugin::AMD::H264Encoder::InputThreadMain), this);
135
+ m_Output.thread = std::thread(&(Plugin::AMD::H264Encoder::OutputThreadMain), this);
136
137
#ifdef _DEBUG
138
printDebugInfo(m_AMFEncoder);
139
#endif
140
}
141
142
-void Plugin::AMD::VCEEncoder::Restart() {
143
+void Plugin::AMD::H264Encoder::Restart() {
144
if (!m_Flag_IsStarted)
145
return;
146
147
148
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Initialization failed with error %ls (code %ld).", res);
149
}
150
151
-void Plugin::AMD::VCEEncoder::Stop() {
152
+void Plugin::AMD::H264Encoder::Stop() {
153
// Restore Timer precision.
154
if (m_TimerPeriod != 0) {
155
timeEndPeriod(m_TimerPeriod);
156
157
std::queue<amf::AMFDataPtr>().swap(m_Output.queue);
158
m_PacketDataBuffer.clear();
159
m_ExtraDataBuffer.clear();
160
- }
161
+}
162
163
-bool Plugin::AMD::VCEEncoder::IsStarted() {
164
+bool Plugin::AMD::H264Encoder::IsStarted() {
165
return m_Flag_IsStarted;
166
}
167
168
-bool Plugin::AMD::VCEEncoder::SendInput(struct encoder_frame* frame) {
169
+bool Plugin::AMD::H264Encoder::SendInput(struct encoder_frame* frame) {
170
// Early-Exception if not encoding.
171
if (!m_Flag_IsStarted) {
172
const char* error = "<" __FUNCTION_NAME__ "> Attempted to send input while not running.";
173
174
throw std::exception(error);
175
}
176
177
+ /* Performance Monitoring */ std::chrono::high_resolution_clock::time_point tpSend = std::chrono::high_resolution_clock::now();
178
+
179
// Attempt to queue for 1 second (forces "Encoding overloaded" message to appear).
180
bool queueSuccessful = false;
181
auto queueStart = std::chrono::high_resolution_clock::now();
182
183
184
// Push into queue if it has room.
185
if (queueSize < m_InputQueueLimit) {
186
+ /* Performance Monitoring */ std::chrono::high_resolution_clock::time_point tpCreateSurface = std::chrono::high_resolution_clock::now();
187
amf::AMFSurfacePtr pAMFSurface = CreateSurfaceFromFrame(frame);
188
+ /* Performance Monitoring */ auto timeCreate = std::chrono::high_resolution_clock::now() - tpCreateSurface;
189
if (!pAMFSurface) {
190
AMF_LOG_ERROR("Unable copy frame for submission, terminating...");
191
return false;
192
} else {
193
pAMFSurface->SetPts(frame->pts / m_FrameRate.second);
194
- pAMFSurface->SetProperty(L"Frame", frame->pts);
195
pAMFSurface->SetDuration((uint64_t)ceil(m_FrameRateReverseDivisor * AMF_SECOND));
196
+ pAMFSurface->SetProperty(AMF_PROPERTY_FRAME, frame->pts);
197
+ /* Performance Monitoring */ pAMFSurface->SetProperty(AMF_PROPERTY_TIME_SENDINPUT, std::chrono::nanoseconds(tpSend.time_since_epoch()).count());
198
+ /* Performance Monitoring */ pAMFSurface->SetProperty(AMF_PROPERTY_TIME_CREATESURFACE, std::chrono::nanoseconds(timeCreate).count());
199
+ /* Performance Monitoring */ pAMFSurface->SetProperty(AMF_PROPERTY_TIME_CONVERT, 0);
200
+ /* Performance Monitoring */ pAMFSurface->SetProperty(AMF_PROPERTY_TIME_ENCODE, 0);
201
}
202
203
{
204
205
return true;
206
}
207
208
-bool Plugin::AMD::VCEEncoder::GetOutput(struct encoder_packet* packet, bool* received_packet) {
209
+bool Plugin::AMD::H264Encoder::GetOutput(struct encoder_packet* packet, bool* received_packet) {
210
// Early-Exception if not encoding.
211
if (!m_Flag_IsStarted) {
212
const char* error = "<" __FUNCTION_NAME__ "> Attempted to send input while not running.";
213
214
throw std::exception(error);
215
}
216
217
+ /* Performance Monitoring */ std::chrono::high_resolution_clock::time_point tpRetrieve = std::chrono::high_resolution_clock::now();
218
+
219
// Signal Output Thread to wake up.
220
m_Output.condvar.notify_all();
221
222
223
*received_packet = true;
224
225
// Debug: Packet Information
226
- std::vector<wchar_t> fileName(128);
227
+ /// Convert File Name and Function Name
228
+ static std::vector<wchar_t> fileName(2048);
229
mbstowcs(fileName.data(), __FILE__, fileName.size());
230
- std::vector<wchar_t> functionName(128);
231
- mbstowcs(functionName.data(), __FUNCTION__, functionName.size());
232
- m_AMF->GetTrace()->TraceW(fileName.data(), __LINE__, AMF_TRACE_TRACE, L"Plugin::GetOutput", 4, L"Packet: Type(%lld), PTS(%4lld), DTS(%4lld), Size(%8lld)", (int64_t)packet->priority, (int64_t)packet->pts, (int64_t)packet->dts, (int64_t)packet->size);
233
+
234
+ /// Timing Information
235
+ uint64_t debugPacketType, debugDTS, debugPTS, debugDuration,
236
+ debugTimeSend,
237
+ debugTimeCreate,
238
+ debugTimeConvert,
239
+ debugTimeEncode;
240
+ pAMFData->GetProperty(AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE, &debugPacketType);
241
+ debugDTS = pAMFData->GetPts();
242
+ pAMFData->GetProperty(AMF_PROPERTY_FRAME, &debugPTS);
243
+ debugDuration = pAMFData->GetDuration();
244
+ pAMFData->GetProperty(AMF_PROPERTY_TIME_SENDINPUT, &debugTimeSend);
245
+ pAMFData->GetProperty(AMF_PROPERTY_TIME_CREATESURFACE, &debugTimeCreate);
246
+ pAMFData->GetProperty(AMF_PROPERTY_TIME_CONVERT, &debugTimeConvert);
247
+ pAMFData->GetProperty(AMF_PROPERTY_TIME_ENCODE, &debugTimeEncode);
248
+ uint64_t totalTimeSendRetrieve = std::chrono::nanoseconds(tpRetrieve.time_since_epoch()).count() - debugTimeSend;
249
+
250
+ /// All times are in nanoseconds.
251
+ /// Frame DTS() PTS() Duration() Type() TimeCreate() TimeConvert(SUBMIT,QUERY,TOTAL) TimeEncode(SUBMIT,ENCODE,QUERY,TOTAL) TimeSendToRetrieve()
252
+ m_AMF->GetTrace()->TraceW(
253
+ fileName.data(), __LINE__,
254
+ AMF_TRACE_TRACE, L"Performance Tracking", 9,
255
+ L"Frame DTS(%8lld) PTS(%8lld) Duration(%8lld) Type(%1lld) Size(%8lld) TimeCreate(%8lld) TimeConvert(%8lld) TimeEncode(%8lld) TimeSendToRetrieve(%8lld)",
256
+ (uint64_t)debugDTS,
257
+ (uint64_t)debugPTS,
258
+ (uint64_t)debugDuration,
259
+ (uint64_t)debugPacketType,
260
+ (uint64_t)packet->size,
261
+ (uint64_t)debugTimeCreate,
262
+ (uint64_t)debugTimeConvert,
263
+ (uint64_t)debugTimeEncode,
264
+ (uint64_t)totalTimeSendRetrieve);
265
}
266
267
return true;
268
}
269
270
-bool Plugin::AMD::VCEEncoder::GetExtraData(uint8_t**& extra_data, size_t*& extra_data_size) {
271
+bool Plugin::AMD::H264Encoder::GetExtraData(uint8_t**& extra_data, size_t*& extra_data_size) {
272
if (!m_AMFContext || !m_AMFEncoder)
273
throw std::exception("<" __FUNCTION_NAME__ "> Called while not initialized.");
274
275
276
return false;
277
}
278
279
-void Plugin::AMD::VCEEncoder::GetVideoInfo(struct video_scale_info*& vsi) {
280
+void Plugin::AMD::H264Encoder::GetVideoInfo(struct video_scale_info*& vsi) {
281
if (!m_AMFContext || !m_AMFEncoder)
282
throw std::exception("<" __FUNCTION_NAME__ "> Called while not initialized.");
283
284
285
286
switch (m_ColorFormat) {
287
// 4:2:0 Formats
288
- case VCEColorFormat_NV12:
289
+ case H264ColorFormat::NV12:
290
vsi->format = VIDEO_FORMAT_NV12;
291
break;
292
- case VCEColorFormat_I420:
293
+ case H264ColorFormat::I420:
294
vsi->format = VIDEO_FORMAT_I420;
295
break;
296
// 4:2:2 Formats
297
- case VCEColorFormat_YUY2:
298
+ case H264ColorFormat::YUY2:
299
vsi->format = VIDEO_FORMAT_YUY2;
300
break;
301
// Uncompressed
302
- case VCEColorFormat_RGBA:
303
+ case H264ColorFormat::RGBA:
304
vsi->format = VIDEO_FORMAT_RGBA;
305
break;
306
- case VCEColorFormat_BGRA:
307
+ case H264ColorFormat::BGRA:
308
vsi->format = VIDEO_FORMAT_BGRA;
309
break;
310
// Other
311
- case VCEColorFormat_GRAY:
312
+ case H264ColorFormat::GRAY:
313
vsi->format = VIDEO_FORMAT_Y800;
314
break;
315
}
316
317
}
318
}
319
320
-void Plugin::AMD::VCEEncoder::InputThreadMain(Plugin::AMD::VCEEncoder* p_this) {
321
+void Plugin::AMD::H264Encoder::InputThreadMain(Plugin::AMD::H264Encoder* p_this) {
322
p_this->InputThreadLogic();
323
}
324
325
-void Plugin::AMD::VCEEncoder::OutputThreadMain(Plugin::AMD::VCEEncoder* p_this) {
326
+void Plugin::AMD::H264Encoder::OutputThreadMain(Plugin::AMD::H264Encoder* p_this) {
327
p_this->OutputThreadLogic();
328
}
329
330
-void Plugin::AMD::VCEEncoder::InputThreadLogic() { // Thread Loop that handles Surface Submission
331
+void Plugin::AMD::H264Encoder::InputThreadLogic() { // Thread Loop that handles Surface Submission
332
// Assign Thread Name
333
static const char* __threadName = "enc-amf Input Thread";
334
SetThreadName(__threadName);
335
336
do {
337
m_Input.condvar.wait(lock);
338
339
- // Assign Thread Name
340
- static const char* __threadName = "enc-amf Input Thread";
341
- SetThreadName(__threadName);
342
-
343
// Skip to check if isStarted is false.
344
if (!m_Flag_IsStarted)
345
continue;
346
347
AMF_RESULT res;
348
amf::AMFDataPtr outbuf;
349
350
+ /* Performance Monitoring */ std::chrono::high_resolution_clock::time_point tpConvert = std::chrono::high_resolution_clock::now();
351
res = m_AMFConverter->SubmitInput(surface);
352
if (res != AMF_OK)
353
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Unable to submit Frame to Converter, error %ls (code %ld).", res);
354
res = m_AMFConverter->QueryOutput(&outbuf);
355
if (res != AMF_OK)
356
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Unable to retrieve Frame from Converter, error %ls (code %ld).", res);
357
+ /* Performance Monitoring */ outbuf->SetProperty(AMF_PROPERTY_TIME_CONVERT,
358
+ std::chrono::nanoseconds(std::chrono::high_resolution_clock::now() - tpConvert).count());
359
360
/// Submit to AMF
361
+ /* Performance Monitoring */ outbuf->SetProperty(AMF_PROPERTY_TIME_ENCODE, std::chrono::nanoseconds(std::chrono::high_resolution_clock::now().time_since_epoch()).count());
362
res = m_AMFEncoder->SubmitInput(outbuf);
363
if (res == AMF_OK) {
364
m_Flag_FirstFrameSubmitted = true;
365
366
// Continue with next Surface.
367
m_Input.condvar.notify_all();
368
} else if (res == AMF_INPUT_FULL) {
369
- m_Output.condvar.notify_all();
370
if (repeatSurfaceSubmission < 5) {
371
repeatSurfaceSubmission++;
372
m_Input.condvar.notify_all();
373
+ m_Output.condvar.notify_all();
374
}
375
} else if (res == AMF_EOF) {
376
// This should never happen, but on the off-chance that it does, just straight up leave the loop.
377
378
} while (m_Flag_IsStarted);
379
}
380
381
-void Plugin::AMD::VCEEncoder::OutputThreadLogic() { // Thread Loop that handles Querying
382
+void Plugin::AMD::H264Encoder::OutputThreadLogic() { // Thread Loop that handles Querying
383
// Assign Thread Name
384
static const char* __threadName = "enc-amf Output Thread";
385
SetThreadName(__threadName);
386
387
do {
388
m_Output.condvar.wait(lock);
389
390
- // Assign Thread Name
391
- static const char* __threadName = "enc-amf Output Thread";
392
- SetThreadName(__threadName);
393
-
394
// Skip to check if isStarted is false.
395
if (!m_Flag_IsStarted)
396
continue;
397
398
if (res == AMF_OK) {
399
m_Flag_FirstFrameReceived = true;
400
401
+ uint64_t debugTimeEncode = 0;
402
+ pData->GetProperty(AMF_PROPERTY_TIME_ENCODE, &debugTimeEncode);
403
+ /* Performance Monitoring */ pData->SetProperty(AMF_PROPERTY_TIME_ENCODE,
404
+ (uint64_t)(
405
+ std::chrono::high_resolution_clock::now().time_since_epoch().count() -
406
+ debugTimeEncode
407
+ ));
408
+
409
{ // Queue
410
std::unique_lock<std::mutex> qlock(m_Output.queuemutex);
411
m_Output.queue.push(pData);
412
413
} while (m_Flag_IsStarted);
414
}
415
416
-inline amf::AMFSurfacePtr Plugin::AMD::VCEEncoder::CreateSurfaceFromFrame(struct encoder_frame*& frame) {
417
+inline amf::AMFSurfacePtr Plugin::AMD::H264Encoder::CreateSurfaceFromFrame(struct encoder_frame*& frame) {
418
AMF_RESULT res = AMF_UNEXPECTED;
419
amf::AMFSurfacePtr pSurface = nullptr;
420
if (m_OpenCL) {
421
422
// AMF Properties
423
//////////////////////////////////////////////////////////////////////////
424
425
-void Plugin::AMD::VCEEncoder::LogProperties() {
426
+void Plugin::AMD::H264Encoder::LogProperties() {
427
AMF_LOG_INFO("-- AMD Advanced Media Framework Encoder --");
428
429
// Initialization Properties
430
AMF_LOG_INFO("Initialization Properties: ");
431
AMF_LOG_INFO(" Type: %s", Utility::VCEEncoderTypeAsString(m_EncoderType));
432
AMF_LOG_INFO(" Video API: %s", Utility::MemoryTypeAsString(m_MemoryType));
433
- if (m_MemoryType != VCEMemoryType_Host) {
434
+ if (m_MemoryType != H264MemoryType::Host) {
435
AMF_LOG_INFO(" Video Adapter: %s", m_APIAdapter.Name.c_str());
436
AMF_LOG_INFO(" OpenCL: %s", m_OpenCL ? "Enabled" : "Disabled");
437
}
438
439
AMF_LOG_INFO("Startup Properties: ");
440
AMF_LOG_INFO(" Usage: %s", Utility::UsageAsString(GetUsage()));
441
AMF_LOG_INFO(" Quality Preset: %s", Utility::QualityPresetAsString(GetQualityPreset()));
442
- AMF_LOG_INFO(" Profile: %s %d.%d", Utility::ProfileAsString(GetProfile()), GetProfileLevel() / 10, this->GetProfileLevel() % 10);
443
+ uint8_t profileLevel = (uint8_t)this->GetProfileLevel();
444
+ AMF_LOG_INFO(" Profile: %s %d.%d", Utility::ProfileAsString(GetProfile()), profileLevel / 10, profileLevel % 10);
445
446
// Frame Properties
447
AMF_LOG_INFO("Frame Properties: ");
448
try {
449
- AMF_LOG_INFO(" Color Profile: %s", GetColorProfile() == VCEColorProfile_709 ? "709" : "601");
450
+ AMF_LOG_INFO(" Color Profile: %s", GetColorProfile() == H264ColorProfile::Rec709 ? "709" : "601");
451
} catch (...) {
452
AMF_LOG_INFO(" Color Profile: N/A");
453
}
454
455
}
456
AMF_LOG_INFO(" Resolution: %dx%d", GetResolution().first, GetResolution().second);
457
AMF_LOG_INFO(" Frame Rate: %d/%d", GetFrameRate().first, GetFrameRate().second);
458
- AMF_LOG_INFO(" Scan Type: %s", GetScanType() == VCEScanType_Progressive ? "Progressive" : "Interlaced");
459
+ AMF_LOG_INFO(" Scan Type: %s", GetScanType() == H264ScanType::Progressive ? "Progressive" : "Interlaced");
460
461
// Rate Control Properties
462
AMF_LOG_INFO("Rate Control Properties: ");
463
- AMF_LOG_INFO(" Method: %s", Utility::RateControlMethodAsString(GetRateControlMethod()));
464
+ if (GetUsage() != H264Usage::UltraLowLatency) {
465
+ AMF_LOG_INFO(" Method: %s", Utility::RateControlMethodAsString(GetRateControlMethod()));
466
+ } else {
467
+ AMF_LOG_INFO(" Method: Ultra Low Latency");
468
+ }
469
AMF_LOG_INFO(" Bitrate: ");
470
AMF_LOG_INFO(" Target: %d bits", GetTargetBitrate());
471
- AMF_LOG_INFO(" Peak: %d bits", GetPeakBitrate());
472
+ if (GetUsage() != H264Usage::UltraLowLatency) {
473
+ AMF_LOG_INFO(" Peak: %d bits", GetPeakBitrate());
474
+ } else {
475
+ AMF_LOG_INFO(" Peak: Ultra Low Latency");
476
+ }
477
AMF_LOG_INFO(" Quantization Parameter: ");
478
AMF_LOG_INFO(" Minimum: %d", GetMinimumQP());
479
AMF_LOG_INFO(" Maximum: %d", GetMaximumQP());
480
AMF_LOG_INFO(" I-Frame: %d", GetIFrameQP());
481
AMF_LOG_INFO(" P-Frame: %d", GetPFrameQP());
482
- if (VCECapabilities::GetInstance()->GetAdapterCapabilities(m_API, m_APIAdapter, VCEEncoderType_AVC).supportsBFrames) {
483
+ if (VCECapabilities::GetInstance()->GetAdapterCapabilities(m_API, m_APIAdapter, H264EncoderType::AVC).supportsBFrames) {
484
try { AMF_LOG_INFO(" B-Frame: %d", GetBFrameQP()); } catch (...) {}
485
} else {
486
AMF_LOG_INFO(" B-Frame: N/A");
487
}
488
AMF_LOG_INFO(" VBV Buffer: ");
489
AMF_LOG_INFO(" Size: %d bits", GetVBVBufferSize());
490
- AMF_LOG_INFO(" Initial Fullness: %f%%", GetInitialVBVBufferFullness() * 100.0);
491
+ if (GetUsage() != H264Usage::UltraLowLatency) {
492
+ AMF_LOG_INFO(" Initial Fullness: %f%%", GetInitialVBVBufferFullness() * 100.0);
493
+ } else {
494
+ AMF_LOG_INFO(" Initial Fullness: Ultra Low Latency");
495
+ }
496
AMF_LOG_INFO(" Flags: ");
497
- AMF_LOG_INFO(" Filler Data: %s", IsFillerDataEnabled() ? "Enabled" : "Disabled");
498
- AMF_LOG_INFO(" Frame Skipping: %s", IsFrameSkippingEnabled() ? "Enabled" : "Disabled");
499
- AMF_LOG_INFO(" Enforce HRD Restrictions: %s", IsEnforceHRDRestrictionsEnabled() ? "Enabled" : "Disabled");
500
+ if (GetUsage() != H264Usage::UltraLowLatency) {
501
+ AMF_LOG_INFO(" Filler Data: %s", IsFillerDataEnabled() ? "Enabled" : "Disabled");
502
+ AMF_LOG_INFO(" Frame Skipping: %s", IsFrameSkippingEnabled() ? "Enabled" : "Disabled");
503
+ AMF_LOG_INFO(" Enforce HRD Restrictions: %s", IsEnforceHRDRestrictionsEnabled() ? "Enabled" : "Disabled");
504
+ } else {
505
+ AMF_LOG_INFO(" Filler Data: Ultra Low Latency");
506
+ AMF_LOG_INFO(" Frame Skipping: Ultra Low Latency");
507
+ AMF_LOG_INFO(" Enforce HRD Restrictions: Ultra Low Latency");
508
+ }
509
510
// Picture Control Properties
511
AMF_LOG_INFO("Picture Control Properties: ");
512
AMF_LOG_INFO(" IDR Period: %d frames", GetIDRPeriod());
513
- if (VCECapabilities::GetInstance()->GetAdapterCapabilities(m_API, m_APIAdapter, VCEEncoderType_AVC).supportsBFrames) {
514
+ if (VCECapabilities::GetInstance()->GetAdapterCapabilities(m_API, m_APIAdapter, H264EncoderType::AVC).supportsBFrames) {
515
AMF_LOG_INFO(" B-Frame Pattern: %d", GetBFramePattern());
516
try {
517
AMF_LOG_INFO(" B-Frame Delta QP: %d", GetBFrameDeltaQP());
518
} catch (...) {
519
AMF_LOG_INFO(" B-Frame Delta QP: N/A");
520
}
521
- AMF_LOG_INFO(" B-Frame Reference: %s", IsBFrameReferenceEnabled() ? "Enabled" : "Disabled");
522
- try {
523
- AMF_LOG_INFO(" B-Frame Reference Delta QP: %d", GetBFrameReferenceDeltaQP());
524
- } catch (...) {
525
- AMF_LOG_INFO(" B-Frame Reference Delta QP: N/A");
526
+ if (GetUsage() == H264Usage::Transcoding) {
527
+ AMF_LOG_INFO(" B-Frame Reference: %s", IsBFrameReferenceEnabled() ? "Enabled" : "Disabled");
528
+ try {
529
+ AMF_LOG_INFO(" B-Frame Reference Delta QP: %d", GetBFrameReferenceDeltaQP());
530
+ } catch (...) {
531
+ AMF_LOG_INFO(" B-Frame Reference Delta QP: N/A");
532
+ }
533
+ } else {
534
+ AMF_LOG_INFO(" B-Frame Reference: Low Latency Mode");
535
+ AMF_LOG_INFO(" B-Frame Reference Delta QP: Low Latency Mode");
536
}
537
} else {
538
AMF_LOG_INFO(" B-Frame Pattern: N/A");
539
540
}
541
542
AMF_LOG_INFO("Miscellaneous Properties: ");
543
- AMF_LOG_INFO(" Deblocking Filter: %s", IsDeblockingFilterEnabled() ? "Enabled" : "Disabled");
544
+ if (GetUsage() == H264Usage::Transcoding) {
545
+ AMF_LOG_INFO(" Deblocking Filter: %s", IsDeblockingFilterEnabled() ? "Enabled" : "Disabled");
546
+ } else {
547
+ AMF_LOG_INFO(" Deblocking Filter: Low Latency Mode");
548
+ }
549
AMF_LOG_INFO(" Motion Estimation: %s",
550
(this->IsHalfPixelMotionEstimationEnabled()
551
? (this->IsQuarterPixelMotionEstimationEnabled()
552
553
AMF_LOG_INFO("-- AMD Advanced Media Framework VCE Encoder --");
554
}
555
556
-void Plugin::AMD::VCEEncoder::SetUsage(VCEUsage usage) {
557
+void Plugin::AMD::H264Encoder::SetUsage(H264Usage usage) {
558
AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_USAGE,
559
(uint32_t)Utility::UsageAsAMF(usage));
560
if (res != AMF_OK) {
561
562
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", Utility::UsageAsString(usage));
563
}
564
565
-Plugin::AMD::VCEUsage Plugin::AMD::VCEEncoder::GetUsage() {
566
+Plugin::AMD::H264Usage Plugin::AMD::H264Encoder::GetUsage() {
567
uint32_t usage;
568
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_USAGE, &usage);
569
if (res != AMF_OK) {
570
571
return Utility::UsageFromAMF(usage);
572
}
573
574
-void Plugin::AMD::VCEEncoder::SetQualityPreset(VCEQualityPreset preset) {
575
+void Plugin::AMD::H264Encoder::SetQualityPreset(H264QualityPreset preset) {
576
static AMF_VIDEO_ENCODER_QUALITY_PRESET_ENUM CustomToAMF[] = {
577
AMF_VIDEO_ENCODER_QUALITY_PRESET_SPEED,
578
AMF_VIDEO_ENCODER_QUALITY_PRESET_BALANCED,
579
580
"Quality",
581
};
582
583
- AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_QUALITY_PRESET, (uint32_t)CustomToAMF[preset]);
584
+ AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_QUALITY_PRESET, (uint32_t)CustomToAMF[(uint8_t)preset]);
585
if (res != AMF_OK) {
586
- ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, CustomToName[preset]);
587
+ ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, CustomToName[(uint8_t)preset]);
588
}
589
- AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", CustomToName[preset]);
590
+ AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", CustomToName[(uint8_t)preset]);
591
}
592
593
-Plugin::AMD::VCEQualityPreset Plugin::AMD::VCEEncoder::GetQualityPreset() {
594
- static VCEQualityPreset AMFToCustom[] = {
595
- VCEQualityPreset_Balanced,
596
- VCEQualityPreset_Speed,
597
- VCEQualityPreset_Quality,
598
+Plugin::AMD::H264QualityPreset Plugin::AMD::H264Encoder::GetQualityPreset() {
599
+ static H264QualityPreset AMFToCustom[] = {
600
+ H264QualityPreset::Balanced,
601
+ H264QualityPreset::Speed,
602
+ H264QualityPreset::Quality,
603
};
604
static char* CustomToName[] = {
605
"Speed",
606
607
if (res != AMF_OK) {
608
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
609
}
610
- AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", CustomToName[AMFToCustom[preset]]);
611
- return AMFToCustom[preset];
612
+ AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", CustomToName[(uint8_t)AMFToCustom[(uint8_t)preset]]);
613
+ return AMFToCustom[(uint8_t)preset];
614
}
615
616
-void Plugin::AMD::VCEEncoder::SetProfile(VCEProfile profile) {
617
+void Plugin::AMD::H264Encoder::SetProfile(H264Profile profile) {
618
AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_PROFILE, (uint32_t)profile);
619
if (res != AMF_OK) {
620
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, Utility::ProfileAsString(profile));
621
622
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", Utility::ProfileAsString(profile));
623
}
624
625
-Plugin::AMD::VCEProfile Plugin::AMD::VCEEncoder::GetProfile() {
626
+Plugin::AMD::H264Profile Plugin::AMD::H264Encoder::GetProfile() {
627
uint32_t profile;
628
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_PROFILE, &profile);
629
if (res != AMF_OK) {
630
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
631
}
632
- AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", Utility::ProfileAsString((VCEProfile)profile));
633
- return (VCEProfile)profile;
634
+ AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", Utility::ProfileAsString((H264Profile)profile));
635
+ return (H264Profile)profile;
636
}
637
638
-void Plugin::AMD::VCEEncoder::SetProfileLevel(VCEProfileLevel level) {
639
+void Plugin::AMD::H264Encoder::SetProfileLevel(H264ProfileLevel level) {
640
// Automatic Detection
641
- if (level == VCEProfileLevel_Automatic) {
642
+ if (level == H264ProfileLevel::Automatic) {
643
auto frameSize = this->GetResolution();
644
auto frameRate = this->GetFrameRate();
645
level = Plugin::Utility::GetMinimumProfileLevel(frameSize, frameRate);
646
647
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", level);
648
}
649
650
-Plugin::AMD::VCEProfileLevel Plugin::AMD::VCEEncoder::GetProfileLevel() {
651
+Plugin::AMD::H264ProfileLevel Plugin::AMD::H264Encoder::GetProfileLevel() {
652
uint32_t profileLevel;
653
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_PROFILE_LEVEL, &profileLevel);
654
if (res != AMF_OK) {
655
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
656
}
657
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", profileLevel);
658
- return (VCEProfileLevel)(profileLevel);
659
+ return (H264ProfileLevel)(profileLevel);
660
}
661
662
-void Plugin::AMD::VCEEncoder::SetColorProfile(VCEColorProfile profile) {
663
+void Plugin::AMD::H264Encoder::SetColorProfile(H264ColorProfile profile) {
664
AMF_VIDEO_CONVERTER_COLOR_PROFILE_ENUM pluginToAMF[] = {
665
AMF_VIDEO_CONVERTER_COLOR_PROFILE_601,
666
AMF_VIDEO_CONVERTER_COLOR_PROFILE_709,
667
668
};
669
670
AMF_RESULT res = m_AMFConverter->SetProperty(AMF_VIDEO_CONVERTER_COLOR_PROFILE,
671
- pluginToAMF[profile]);
672
+ pluginToAMF[(uint8_t)profile]);
673
if (res != AMF_OK)
674
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Unable to set Color Profile, error %ls (code %ld).", res);
675
m_ColorProfile = profile;
676
- AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", pluginToString[profile]);
677
+ AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", pluginToString[(uint8_t)profile]);
678
}
679
680
-Plugin::AMD::VCEColorProfile Plugin::AMD::VCEEncoder::GetColorProfile() {
681
+Plugin::AMD::H264ColorProfile Plugin::AMD::H264Encoder::GetColorProfile() {
682
return m_ColorProfile;
683
}
684
685
-void Plugin::AMD::VCEEncoder::SetFullRangeColorEnabled(bool enabled) {
686
+void Plugin::AMD::H264Encoder::SetFullRangeColorEnabled(bool enabled) {
687
// Info from Mikhail:
688
// - Name may change in the future
689
// - Use GetProperty or GetPropertyDescription to test for older or newer drivers.
690
691
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
692
}
693
694
-bool Plugin::AMD::VCEEncoder::IsFullRangeColorEnabled() {
695
+bool Plugin::AMD::H264Encoder::IsFullRangeColorEnabled() {
696
// Info from Mikhail:
697
// - Name may change in the future
698
// - Use GetProperty or GetPropertyDescription to test for older or newer drivers.
699
700
return enabled;
701
}
702
703
-void Plugin::AMD::VCEEncoder::SetResolution(uint32_t width, uint32_t height) {
704
+void Plugin::AMD::H264Encoder::SetResolution(uint32_t width, uint32_t height) {
705
AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_FRAMESIZE, ::AMFConstructSize(width, height));
706
if (res != AMF_OK) {
707
std::vector<char> msgBuf(128);
708
709
m_FrameSize.first = width;
710
m_FrameSize.second = height;
711
712
- if (this->GetProfileLevel() == VCEProfileLevel_Automatic)
713
- this->SetProfileLevel(VCEProfileLevel_Automatic);
714
+ if (this->GetProfileLevel() == H264ProfileLevel::Automatic)
715
+ this->SetProfileLevel(H264ProfileLevel::Automatic);
716
}
717
718
-std::pair<uint32_t, uint32_t> Plugin::AMD::VCEEncoder::GetResolution() {
719
+std::pair<uint32_t, uint32_t> Plugin::AMD::H264Encoder::GetResolution() {
720
AMFSize frameSize;
721
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_FRAMESIZE, &frameSize);
722
if (res != AMF_OK) {
723
724
m_FrameSize.first = frameSize.width;
725
m_FrameSize.second = frameSize.height;
726
727
- if (this->GetProfileLevel() == VCEProfileLevel_Automatic)
728
- this->SetProfileLevel(VCEProfileLevel_Automatic);
729
+ if (this->GetProfileLevel() == H264ProfileLevel::Automatic)
730
+ this->SetProfileLevel(H264ProfileLevel::Automatic);
731
732
return std::pair<uint32_t, uint32_t>(m_FrameSize);
733
}
734
735
-void Plugin::AMD::VCEEncoder::SetFrameRate(uint32_t num, uint32_t den) {
736
+void Plugin::AMD::H264Encoder::SetFrameRate(uint32_t num, uint32_t den) {
737
AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_FRAMERATE, ::AMFConstructRate(num, den));
738
if (res != AMF_OK) {
739
std::vector<char> msgBuf;
740
741
m_FrameRate.second = den;
742
m_FrameRateDivisor = (double_t)m_FrameRate.first / (double_t)m_FrameRate.second;
743
m_FrameRateReverseDivisor = ((double_t)m_FrameRate.second / (double_t)m_FrameRate.first);
744
- m_InputQueueLimit = (uint32_t)ceil(m_FrameRateDivisor);
745
+ m_InputQueueLimit = (uint32_t)ceil(m_FrameRateDivisor * 3);
746
747
- if (this->GetProfileLevel() == VCEProfileLevel_Automatic)
748
- this->SetProfileLevel(VCEProfileLevel_Automatic);
749
+ if (this->GetProfileLevel() == H264ProfileLevel::Automatic)
750
+ this->SetProfileLevel(H264ProfileLevel::Automatic);
751
}
752
753
-std::pair<uint32_t, uint32_t> Plugin::AMD::VCEEncoder::GetFrameRate() {
754
+std::pair<uint32_t, uint32_t> Plugin::AMD::H264Encoder::GetFrameRate() {
755
AMFRate frameRate;
756
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_FRAMERATE, &frameRate);
757
if (res != AMF_OK) {
758
759
m_FrameRate.first = frameRate.num;
760
m_FrameRate.second = frameRate.den;
761
m_FrameRateDivisor = (double_t)frameRate.num / (double_t)frameRate.den;
762
- m_InputQueueLimit = (uint32_t)ceil(m_FrameRateDivisor);
763
+ m_InputQueueLimit = (uint32_t)ceil(m_FrameRateDivisor * 3);
764
765
- if (this->GetProfileLevel() == VCEProfileLevel_Automatic)
766
- this->SetProfileLevel(VCEProfileLevel_Automatic);
767
+ if (this->GetProfileLevel() == H264ProfileLevel::Automatic)
768
+ this->SetProfileLevel(H264ProfileLevel::Automatic);
769
770
return std::pair<uint32_t, uint32_t>(m_FrameRate);
771
}
772
773
-void Plugin::AMD::VCEEncoder::SetScanType(VCEScanType scanType) {
774
+void Plugin::AMD::H264Encoder::SetScanType(H264ScanType scanType) {
775
static AMF_VIDEO_ENCODER_SCANTYPE_ENUM CustomToAMF[] = {
776
AMF_VIDEO_ENCODER_SCANTYPE_PROGRESSIVE,
777
AMF_VIDEO_ENCODER_SCANTYPE_INTERLACED,
778
779
"Interlaced",
780
};
781
782
- AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_SCANTYPE, (uint32_t)CustomToAMF[scanType]);
783
+ AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_SCANTYPE, (uint32_t)CustomToAMF[(uint8_t)scanType]);
784
if (res != AMF_OK) {
785
- ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, CustomToName[scanType]);
786
+ ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, CustomToName[(uint8_t)scanType]);
787
}
788
- AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", CustomToName[scanType]);
789
+ AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", CustomToName[(uint8_t)scanType]);
790
}
791
792
-Plugin::AMD::VCEScanType Plugin::AMD::VCEEncoder::GetScanType() {
793
+Plugin::AMD::H264ScanType Plugin::AMD::H264Encoder::GetScanType() {
794
static char* CustomToName[] = {
795
"Progressive",
796
"Interlaced",
797
798
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
799
}
800
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", CustomToName[scanType]);
801
- return (Plugin::AMD::VCEScanType)scanType;
802
+ return (Plugin::AMD::H264ScanType)scanType;
803
}
804
805
-void Plugin::AMD::VCEEncoder::SetRateControlMethod(VCERateControlMethod method) {
806
+void Plugin::AMD::H264Encoder::SetRateControlMethod(H264RateControlMethod method) {
807
AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD,
808
(uint64_t)Utility::RateControlMethodAsAMF(method));
809
if (res != AMF_OK) {
810
811
Utility::RateControlMethodAsString(method));
812
}
813
814
-Plugin::AMD::VCERateControlMethod Plugin::AMD::VCEEncoder::GetRateControlMethod() {
815
+Plugin::AMD::H264RateControlMethod Plugin::AMD::H264Encoder::GetRateControlMethod() {
816
uint32_t method;
817
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD, &method);
818
if (res != AMF_OK) {
819
820
return Utility::RateControlMethodFromAMF(method);
821
}
822
823
-void Plugin::AMD::VCEEncoder::SetTargetBitrate(uint32_t bitrate) {
824
+void Plugin::AMD::H264Encoder::SetTargetBitrate(uint32_t bitrate) {
825
// Clamp Value
826
bitrate = clamp(bitrate, 10000,
827
- Plugin::AMD::VCECapabilities::GetInstance()->GetAdapterCapabilities(m_API, m_APIAdapter, VCEEncoderType_AVC).maxBitrate);
828
+ Plugin::AMD::VCECapabilities::GetInstance()->GetAdapterCapabilities(m_API, m_APIAdapter, H264EncoderType::AVC).maxBitrate);
829
830
AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_TARGET_BITRATE, bitrate);
831
if (res != AMF_OK) {
832
833
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d bits.", bitrate);
834
}
835
836
-uint32_t Plugin::AMD::VCEEncoder::GetTargetBitrate() {
837
+uint32_t Plugin::AMD::H264Encoder::GetTargetBitrate() {
838
uint32_t bitrate;
839
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_TARGET_BITRATE, &bitrate);
840
if (res != AMF_OK) {
841
842
return bitrate;
843
}
844
845
-void Plugin::AMD::VCEEncoder::SetPeakBitrate(uint32_t bitrate) {
846
+void Plugin::AMD::H264Encoder::SetPeakBitrate(uint32_t bitrate) {
847
// Clamp Value
848
bitrate = clamp(bitrate, 10000,
849
- Plugin::AMD::VCECapabilities::GetInstance()->GetAdapterCapabilities(m_API, m_APIAdapter, VCEEncoderType_AVC).maxBitrate);
850
+ Plugin::AMD::VCECapabilities::GetInstance()->GetAdapterCapabilities(m_API, m_APIAdapter, H264EncoderType::AVC).maxBitrate);
851
852
AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_PEAK_BITRATE, (uint32_t)bitrate);
853
if (res != AMF_OK) {
854
855
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d bits.", bitrate);
856
}
857
858
-uint32_t Plugin::AMD::VCEEncoder::GetPeakBitrate() {
859
+uint32_t Plugin::AMD::H264Encoder::GetPeakBitrate() {
860
uint32_t bitrate;
861
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_PEAK_BITRATE, &bitrate);
862
if (res != AMF_OK) {
863
864
return bitrate;
865
}
866
867
-void Plugin::AMD::VCEEncoder::SetMinimumQP(uint8_t qp) {
868
+void Plugin::AMD::H264Encoder::SetMinimumQP(uint8_t qp) {
869
// Clamp Value
870
qp = clamp(qp, 0, 51);
871
872
873
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", qp);
874
}
875
876
-uint8_t Plugin::AMD::VCEEncoder::GetMinimumQP() {
877
+uint8_t Plugin::AMD::H264Encoder::GetMinimumQP() {
878
uint32_t qp;
879
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_MIN_QP, &qp);
880
if (res != AMF_OK) {
881
882
return (uint8_t)qp;
883
}
884
885
-void Plugin::AMD::VCEEncoder::SetMaximumQP(uint8_t qp) {
886
+void Plugin::AMD::H264Encoder::SetMaximumQP(uint8_t qp) {
887
// Clamp Value
888
qp = clamp(qp, 0, 51);
889
890
891
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", qp);
892
}
893
894
-uint8_t Plugin::AMD::VCEEncoder::GetMaximumQP() {
895
+uint8_t Plugin::AMD::H264Encoder::GetMaximumQP() {
896
uint32_t qp;
897
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_MAX_QP, &qp);
898
if (res != AMF_OK) {
899
900
return (uint8_t)qp;
901
}
902
903
-void Plugin::AMD::VCEEncoder::SetIFrameQP(uint8_t qp) {
904
+void Plugin::AMD::H264Encoder::SetIFrameQP(uint8_t qp) {
905
// Clamp Value
906
qp = clamp(qp, 0, 51);
907
908
909
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", qp);
910
}
911
912
-uint8_t Plugin::AMD::VCEEncoder::GetIFrameQP() {
913
+uint8_t Plugin::AMD::H264Encoder::GetIFrameQP() {
914
uint32_t qp;
915
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_QP_I, &qp);
916
if (res != AMF_OK) {
917
918
return (uint8_t)qp;
919
}
920
921
-void Plugin::AMD::VCEEncoder::SetPFrameQP(uint8_t qp) {
922
+void Plugin::AMD::H264Encoder::SetPFrameQP(uint8_t qp) {
923
// Clamp Value
924
qp = clamp(qp, 0, 51);
925
926
927
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", qp);
928
}
929
930
-uint8_t Plugin::AMD::VCEEncoder::GetPFrameQP() {
931
+uint8_t Plugin::AMD::H264Encoder::GetPFrameQP() {
932
uint32_t qp;
933
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_QP_P, &qp);
934
if (res != AMF_OK) {
935
936
return (uint8_t)qp;
937
}
938
939
-void Plugin::AMD::VCEEncoder::SetBFrameQP(uint8_t qp) {
940
+void Plugin::AMD::H264Encoder::SetBFrameQP(uint8_t qp) {
941
// Clamp Value
942
qp = clamp(qp, 0, 51);
943
944
945
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", qp);
946
}
947
948
-uint8_t Plugin::AMD::VCEEncoder::GetBFrameQP() {
949
+uint8_t Plugin::AMD::H264Encoder::GetBFrameQP() {
950
uint32_t qp;
951
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_QP_B, &qp);
952
if (res != AMF_OK) {
953
954
return (uint8_t)qp;
955
}
956
957
-void Plugin::AMD::VCEEncoder::SetVBVBufferSize(uint32_t size) {
958
+void Plugin::AMD::H264Encoder::SetVBVBufferSize(uint32_t size) {
959
// Clamp Value
960
size = clamp(size, 1000, 100000000); // 1kbit to 100mbit.
961
962
963
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d bits.", size);
964
}
965
966
-void Plugin::AMD::VCEEncoder::SetVBVBufferAutomatic(double_t strictness) {
967
+void Plugin::AMD::H264Encoder::SetVBVBufferAutomatic(double_t strictness) {
968
uint32_t strictBitrate = 1000, looseBitrate = 100000000;
969
970
// Strict VBV Buffer Size = Bitrate / FPS
971
// Loose VBV Buffer Size = Bitrate
972
973
- switch (this->GetRateControlMethod()) {
974
- case VCERateControlMethod_ConstantBitrate:
975
- case VCERateControlMethod_VariableBitrate_LatencyConstrained:
976
- looseBitrate = this->GetTargetBitrate();
977
- break;
978
- case VCERateControlMethod_VariableBitrate_PeakConstrained:
979
- looseBitrate = max(this->GetTargetBitrate(), this->GetPeakBitrate());
980
- break;
981
- case VCERateControlMethod_ConstantQP:
982
- // When using Constant QP, one will have to pick a QP that is decent
983
- // in both quality and bitrate. We can easily calculate both the QP
984
- // required for an average bitrate and the average bitrate itself
985
- // with these formulas:
986
- // BITRATE = ((1 - (QP / 51)) ^ 2) * ((Width * Height) * 1.5 * (FPSNumerator / FPSDenumerator))
987
- // QP = (1 - sqrt(BITRATE / ((Width * Height) * 1.5 * (FPSNumerator / FPSDenumerator)))) * 51
988
-
989
- auto frameSize = this->GetResolution();
990
- auto frameRate = this->GetFrameRate();
991
-
992
- double_t bitrate = frameSize.first * frameSize.second;
993
- switch (this->m_ColorFormat) {
994
- case VCEColorFormat_NV12:
995
- case VCEColorFormat_I420:
996
- bitrate *= 1.5;
997
- break;
998
- case VCEColorFormat_YUY2:
999
- bitrate *= 4;
1000
- break;
1001
- case VCEColorFormat_BGRA:
1002
- case VCEColorFormat_RGBA:
1003
- bitrate *= 3;
1004
- break;
1005
- case VCEColorFormat_GRAY:
1006
- bitrate *= 1;
1007
- break;
1008
- }
1009
- bitrate *= frameRate.first / frameRate.second;
1010
-
1011
- uint8_t qp_i, qp_p, qp_b;
1012
- qp_i = this->GetIFrameQP();
1013
- qp_p = this->GetPFrameQP();
1014
- try { qp_b = this->GetBFrameQP(); } catch (...) { qp_b = 51; }
1015
- double_t qp = 1 - ((double_t)(min(min(qp_i, qp_p), qp_b)) / 51.0);
1016
- qp = max(qp * qp, 0.001); // Needs to be at least 0.001.
1017
-
1018
- looseBitrate = static_cast<uint32_t>(bitrate * qp);
1019
- break;
1020
+ if (GetUsage() == H264Usage::UltraLowLatency) {
1021
+ looseBitrate = GetTargetBitrate();
1022
+ } else {
1023
+ switch (this->GetRateControlMethod()) {
1024
+ case H264RateControlMethod::ConstantBitrate:
1025
+ case H264RateControlMethod::VariableBitrate_LatencyConstrained:
1026
+ looseBitrate = this->GetTargetBitrate();
1027
+ break;
1028
+ case H264RateControlMethod::VariableBitrate_PeakConstrained:
1029
+ looseBitrate = max(this->GetTargetBitrate(), this->GetPeakBitrate());
1030
+ break;
1031
+ case H264RateControlMethod::ConstantQP:
1032
+ // When using Constant QP, one will have to pick a QP that is decent
1033
+ // in both quality and bitrate. We can easily calculate both the QP
1034
+ // required for an average bitrate and the average bitrate itself
1035
+ // with these formulas:
1036
+ // BITRATE = ((1 - (QP / 51)) ^ 2) * ((Width * Height) * 1.5 * (FPSNumerator / FPSDenumerator))
1037
+ // QP = (1 - sqrt(BITRATE / ((Width * Height) * 1.5 * (FPSNumerator / FPSDenumerator)))) * 51
1038
+
1039
+ auto frameSize = this->GetResolution();
1040
+ auto frameRate = this->GetFrameRate();
1041
+
1042
+ double_t bitrate = frameSize.first * frameSize.second;
1043
+ switch (this->m_ColorFormat) {
1044
+ case H264ColorFormat::NV12:
1045
+ case H264ColorFormat::I420:
1046
+ bitrate *= 1.5;
1047
+ break;
1048
+ case H264ColorFormat::YUY2:
1049
+ bitrate *= 4;
1050
+ break;
1051
+ case H264ColorFormat::BGRA:
1052
+ case H264ColorFormat::RGBA:
1053
+ bitrate *= 3;
1054
+ break;
1055
+ case H264ColorFormat::GRAY:
1056
+ bitrate *= 1;
1057
+ break;
1058
+ }
1059
+ bitrate *= frameRate.first / frameRate.second;
1060
+
1061
+ uint8_t qp_i, qp_p, qp_b;
1062
+ qp_i = this->GetIFrameQP();
1063
+ qp_p = this->GetPFrameQP();
1064
+ try { qp_b = this->GetBFrameQP(); } catch (...) { qp_b = 51; }
1065
+ double_t qp = 1 - ((double_t)(min(min(qp_i, qp_p), qp_b)) / 51.0);
1066
+ qp = max(qp * qp, 0.001); // Needs to be at least 0.001.
1067
+
1068
+ looseBitrate = static_cast<uint32_t>(bitrate * qp);
1069
+ break;
1070
+ }
1071
}
1072
strictBitrate = static_cast<uint32_t>(looseBitrate * m_FrameRateReverseDivisor);
1073
1074
- #define PI 3.14159265
1075
- double_t interpVal = (sin(max(min(strictness, 1.0), 0.0) * 90 * (PI / 180))); // sin curve?
1076
- uint32_t realBitrate = static_cast<uint32_t>(ceil((strictBitrate * interpVal) + (looseBitrate * (1.0 - interpVal))));
1077
- this->SetVBVBufferSize(realBitrate);
1078
+ // 0% = 100000, 50% = looseBitrate, 100% = strictBitrate
1079
+ strictness = min(max(strictness, 0.0), 1.0);
1080
+ double_t aAB = min(strictness * 2.0, 1.0f);
1081
+ double_t bAB = max(strictness * 2.0 - 1.0, 0.0);
1082
+
1083
+ double_t aFade = (looseBitrate * aAB) + (100000 * (1.0 - aAB));
1084
+ double_t bFade = (strictness * bAB) + (aFade * (1.0 - bAB));
1085
+
1086
+ uint32_t vbvBufferSize = static_cast<uint32_t>(round(bFade));
1087
+ this->SetVBVBufferSize(vbvBufferSize);
1088
}
1089
1090
-uint32_t Plugin::AMD::VCEEncoder::GetVBVBufferSize() {
1091
+uint32_t Plugin::AMD::H264Encoder::GetVBVBufferSize() {
1092
uint32_t size;
1093
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_VBV_BUFFER_SIZE, &size);
1094
if (res != AMF_OK) {
1095
1096
return size;
1097
}
1098
1099
-void Plugin::AMD::VCEEncoder::SetInitialVBVBufferFullness(double_t fullness) {
1100
+void Plugin::AMD::H264Encoder::SetInitialVBVBufferFullness(double_t fullness) {
1101
// Clamp Value
1102
fullness = max(min(fullness, 1), 0); // 0 to 100 %
1103
1104
1105
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %f%%.", fullness * 100);
1106
}
1107
1108
-double_t Plugin::AMD::VCEEncoder::GetInitialVBVBufferFullness() {
1109
+double_t Plugin::AMD::H264Encoder::GetInitialVBVBufferFullness() {
1110
uint32_t vbvBufferFullness;
1111
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_INITIAL_VBV_BUFFER_FULLNESS, &vbvBufferFullness);
1112
if (res != AMF_OK) {
1113
1114
return ((double_t)vbvBufferFullness / 64.0);
1115
}
1116
1117
-void Plugin::AMD::VCEEncoder::SetFillerDataEnabled(bool enabled) {
1118
+void Plugin::AMD::H264Encoder::SetFillerDataEnabled(bool enabled) {
1119
AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_FILLER_DATA_ENABLE, enabled);
1120
if (res != AMF_OK) {
1121
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1122
1123
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1124
}
1125
1126
-bool Plugin::AMD::VCEEncoder::IsFillerDataEnabled() {
1127
+bool Plugin::AMD::H264Encoder::IsFillerDataEnabled() {
1128
bool enabled;
1129
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_FILLER_DATA_ENABLE, &enabled);
1130
if (res != AMF_OK) {
1131
1132
return enabled;
1133
}
1134
1135
-void Plugin::AMD::VCEEncoder::SetFrameSkippingEnabled(bool enabled) {
1136
+void Plugin::AMD::H264Encoder::SetFrameSkippingEnabled(bool enabled) {
1137
AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_RATE_CONTROL_SKIP_FRAME_ENABLE, enabled);
1138
if (res != AMF_OK) {
1139
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1140
1141
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1142
}
1143
1144
-bool Plugin::AMD::VCEEncoder::IsFrameSkippingEnabled() {
1145
+bool Plugin::AMD::H264Encoder::IsFrameSkippingEnabled() {
1146
bool enabled;
1147
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_RATE_CONTROL_SKIP_FRAME_ENABLE, &enabled);
1148
if (res != AMF_OK) {
1149
1150
return enabled;
1151
}
1152
1153
-void Plugin::AMD::VCEEncoder::SetEnforceHRDRestrictionsEnabled(bool enabled) {
1154
+void Plugin::AMD::H264Encoder::SetEnforceHRDRestrictionsEnabled(bool enabled) {
1155
AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_ENFORCE_HRD, enabled);
1156
if (res != AMF_OK) {
1157
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1158
1159
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1160
}
1161
1162
-bool Plugin::AMD::VCEEncoder::IsEnforceHRDRestrictionsEnabled() {
1163
+bool Plugin::AMD::H264Encoder::IsEnforceHRDRestrictionsEnabled() {
1164
bool enabled;
1165
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_ENFORCE_HRD, &enabled);
1166
if (res != AMF_OK) {
1167
1168
return enabled;
1169
}
1170
1171
-void Plugin::AMD::VCEEncoder::SetIDRPeriod(uint32_t period) {
1172
+void Plugin::AMD::H264Encoder::SetIDRPeriod(uint32_t period) {
1173
// Clamp Value
1174
period = max(min(period, 1000), 1); // 1-1000 so that OBS can actually quit.
1175
1176
1177
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", period);
1178
}
1179
1180
-uint32_t Plugin::AMD::VCEEncoder::GetIDRPeriod() {
1181
+uint32_t Plugin::AMD::H264Encoder::GetIDRPeriod() {
1182
int32_t period;
1183
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_IDR_PERIOD, &period);
1184
if (res != AMF_OK) {
1185
1186
return period;
1187
}
1188
1189
-void Plugin::AMD::VCEEncoder::SetBFramePattern(VCEBFramePattern pattern) {
1190
+void Plugin::AMD::H264Encoder::SetBFramePattern(H264BFramePattern pattern) {
1191
AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_B_PIC_PATTERN, (uint32_t)pattern);
1192
if (res != AMF_OK) {
1193
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, pattern);
1194
1195
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", pattern);
1196
}
1197
1198
-Plugin::AMD::VCEBFramePattern Plugin::AMD::VCEEncoder::GetBFramePattern() {
1199
+Plugin::AMD::H264BFramePattern Plugin::AMD::H264Encoder::GetBFramePattern() {
1200
uint32_t pattern;
1201
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_B_PIC_PATTERN, &pattern);
1202
if (res != AMF_OK) {
1203
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1204
}
1205
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %d.", pattern);
1206
- return (Plugin::AMD::VCEBFramePattern)pattern;
1207
+ return (Plugin::AMD::H264BFramePattern)pattern;
1208
}
1209
1210
-void Plugin::AMD::VCEEncoder::SetBFrameDeltaQP(int8_t qp) {
1211
+void Plugin::AMD::H264Encoder::SetBFrameDeltaQP(int8_t qp) {
1212
// Clamp Value
1213
qp = clamp(qp, -10, 10);
1214
1215
1216
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", qp);
1217
}
1218
1219
-int8_t Plugin::AMD::VCEEncoder::GetBFrameDeltaQP() {
1220
+int8_t Plugin::AMD::H264Encoder::GetBFrameDeltaQP() {
1221
int32_t qp;
1222
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_B_PIC_DELTA_QP, &qp);
1223
if (res != AMF_OK) {
1224
1225
return (int8_t)qp;
1226
}
1227
1228
-void Plugin::AMD::VCEEncoder::SetBFrameReferenceEnabled(bool enabled) {
1229
+void Plugin::AMD::H264Encoder::SetBFrameReferenceEnabled(bool enabled) {
1230
AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_B_REFERENCE_ENABLE, enabled);
1231
if (res != AMF_OK) {
1232
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1233
1234
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1235
}
1236
1237
-bool Plugin::AMD::VCEEncoder::IsBFrameReferenceEnabled() {
1238
+bool Plugin::AMD::H264Encoder::IsBFrameReferenceEnabled() {
1239
bool enabled;
1240
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_B_REFERENCE_ENABLE, &enabled);
1241
if (res != AMF_OK) {
1242
1243
return enabled;
1244
}
1245
1246
-void Plugin::AMD::VCEEncoder::SetBFrameReferenceDeltaQP(int8_t qp) {
1247
+void Plugin::AMD::H264Encoder::SetBFrameReferenceDeltaQP(int8_t qp) {
1248
// Clamp Value
1249
qp = clamp(qp, -10, 10);
1250
1251
1252
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", qp);
1253
}
1254
1255
-int8_t Plugin::AMD::VCEEncoder::GetBFrameReferenceDeltaQP() {
1256
+int8_t Plugin::AMD::H264Encoder::GetBFrameReferenceDeltaQP() {
1257
int32_t qp;
1258
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_REF_B_PIC_DELTA_QP, &qp);
1259
if (res != AMF_OK) {
1260
1261
return (int8_t)qp;
1262
}
1263
1264
-void Plugin::AMD::VCEEncoder::SetDeblockingFilterEnabled(bool enabled) {
1265
+void Plugin::AMD::H264Encoder::SetDeblockingFilterEnabled(bool enabled) {
1266
AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_DE_BLOCKING_FILTER, enabled);
1267
if (res != AMF_OK) {
1268
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1269
1270
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1271
}
1272
1273
-bool Plugin::AMD::VCEEncoder::IsDeblockingFilterEnabled() {
1274
+bool Plugin::AMD::H264Encoder::IsDeblockingFilterEnabled() {
1275
bool enabled;
1276
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_DE_BLOCKING_FILTER, &enabled);
1277
if (res != AMF_OK) {
1278
1279
return enabled;
1280
}
1281
1282
-void Plugin::AMD::VCEEncoder::SetHalfPixelMotionEstimationEnabled(bool enabled) {
1283
+void Plugin::AMD::H264Encoder::SetHalfPixelMotionEstimationEnabled(bool enabled) {
1284
AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_MOTION_HALF_PIXEL, enabled);
1285
if (res != AMF_OK) {
1286
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1287
1288
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1289
}
1290
1291
-bool Plugin::AMD::VCEEncoder::IsHalfPixelMotionEstimationEnabled() {
1292
+bool Plugin::AMD::H264Encoder::IsHalfPixelMotionEstimationEnabled() {
1293
bool enabled;
1294
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_MOTION_HALF_PIXEL, &enabled);
1295
if (res != AMF_OK) {
1296
1297
return enabled;
1298
}
1299
1300
-void Plugin::AMD::VCEEncoder::SetQuarterPixelMotionEstimationEnabled(bool enabled) {
1301
+void Plugin::AMD::H264Encoder::SetQuarterPixelMotionEstimationEnabled(bool enabled) {
1302
AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_MOTION_QUARTERPIXEL, enabled);
1303
if (res != AMF_OK) {
1304
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1305
1306
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1307
}
1308
1309
-bool Plugin::AMD::VCEEncoder::IsQuarterPixelMotionEstimationEnabled() {
1310
+bool Plugin::AMD::H264Encoder::IsQuarterPixelMotionEstimationEnabled() {
1311
bool enabled;
1312
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_MOTION_QUARTERPIXEL, &enabled);
1313
if (res != AMF_OK) {
1314
1315
//////////////////////////////////////////////////////////////////////////
1316
// Their effect may vary from driver to driver, card to card.
1317
1318
-uint32_t Plugin::AMD::VCEEncoder::GetMaxMBPerSec() {
1319
+uint32_t Plugin::AMD::H264Encoder::GetMaxMBPerSec() {
1320
uint32_t maxMBPerSec;
1321
AMF_RESULT res = m_AMFEncoder->GetProperty(L"MaxMBPerSec", &maxMBPerSec);
1322
if (res != AMF_OK) {
1323
1324
return maxMBPerSec;
1325
}
1326
1327
-void Plugin::AMD::VCEEncoder::SetHeaderInsertionSpacing(uint32_t spacing) {
1328
+void Plugin::AMD::H264Encoder::SetHeaderInsertionSpacing(uint32_t spacing) {
1329
// Clamp Value
1330
spacing = max(min(spacing, m_FrameRate.second * 1000), 0);
1331
1332
1333
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", spacing);
1334
}
1335
1336
-uint32_t Plugin::AMD::VCEEncoder::GetHeaderInsertionSpacing() {
1337
+uint32_t Plugin::AMD::H264Encoder::GetHeaderInsertionSpacing() {
1338
int32_t headerInsertionSpacing;
1339
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_HEADER_INSERTION_SPACING, &headerInsertionSpacing);
1340
if (res != AMF_OK) {
1341
1342
return headerInsertionSpacing;
1343
}
1344
1345
-void Plugin::AMD::VCEEncoder::SetMaximumLongTermReferenceFrames(uint32_t maximumLTRFrames) {
1346
+void Plugin::AMD::H264Encoder::SetMaximumLongTermReferenceFrames(uint32_t maximumLTRFrames) {
1347
// Clamp Parameter Value
1348
maximumLTRFrames = max(min(maximumLTRFrames, 2), 0);
1349
1350
1351
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", maximumLTRFrames);
1352
}
1353
1354
-uint32_t Plugin::AMD::VCEEncoder::GetMaximumLongTermReferenceFrames() {
1355
+uint32_t Plugin::AMD::H264Encoder::GetMaximumLongTermReferenceFrames() {
1356
uint32_t maximumLTRFrames;
1357
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_MAX_LTR_FRAMES, &maximumLTRFrames);
1358
if (res != AMF_OK) {
1359
1360
return maximumLTRFrames;
1361
}
1362
1363
-void Plugin::AMD::VCEEncoder::SetCodingType(VCECodingType type) {
1364
- AMF_RESULT res = m_AMFEncoder->SetProperty(L"CABACEnable", type);
1365
+void Plugin::AMD::H264Encoder::SetCodingType(H264CodingType type) {
1366
+ AMF_RESULT res = m_AMFEncoder->SetProperty(L"CABACEnable", (size_t)type);
1367
if (res != AMF_OK) {
1368
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, Utility::CodingTypeAsString(type));
1369
}
1370
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", Utility::CodingTypeAsString(type));
1371
}
1372
1373
-VCECodingType Plugin::AMD::VCEEncoder::GetCodingType() {
1374
+H264CodingType Plugin::AMD::H264Encoder::GetCodingType() {
1375
uint64_t type;
1376
AMF_RESULT res = m_AMFEncoder->GetProperty(L"CABACEnable", &type);
1377
if (res != AMF_OK) {
1378
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1379
}
1380
- AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", Utility::CodingTypeAsString((VCECodingType)type));
1381
- return (VCECodingType)type;
1382
+ AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", Utility::CodingTypeAsString((H264CodingType)type));
1383
+ return (H264CodingType)type;
1384
}
1385
1386
-void Plugin::AMD::VCEEncoder::SetMaximumAccessUnitSize(uint32_t size) {
1387
+void Plugin::AMD::H264Encoder::SetMaximumAccessUnitSize(uint32_t size) {
1388
// Clamp Value
1389
size = max(min(size, 100000000), 0); // 1kbit to 100mbit.
1390
1391
1392
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d bits.", size);
1393
}
1394
1395
-uint32_t Plugin::AMD::VCEEncoder::GetMaximumAccessUnitSize() {
1396
+uint32_t Plugin::AMD::H264Encoder::GetMaximumAccessUnitSize() {
1397
uint32_t size;
1398
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_MAX_AU_SIZE, &size);
1399
if (res != AMF_OK) {
1400
1401
return size;
1402
}
1403
1404
-void Plugin::AMD::VCEEncoder::SetWaitForTaskEnabled(bool enabled) {
1405
+void Plugin::AMD::H264Encoder::SetWaitForTaskEnabled(bool enabled) {
1406
AMF_RESULT res = m_AMFEncoder->SetProperty(L"WaitForTask", enabled);
1407
if (res != AMF_OK) {
1408
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1409
1410
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1411
}
1412
1413
-bool Plugin::AMD::VCEEncoder::IsWaitForTaskEnabled() {
1414
+bool Plugin::AMD::H264Encoder::IsWaitForTaskEnabled() {
1415
bool enabled;
1416
AMF_RESULT res = m_AMFEncoder->GetProperty(L"WaitForTask", &enabled);
1417
if (res != AMF_OK) {
1418
1419
return enabled;
1420
}
1421
1422
-void Plugin::AMD::VCEEncoder::SetPreAnalysisPassEnabled(bool enabled) {
1423
+void Plugin::AMD::H264Encoder::SetPreAnalysisPassEnabled(bool enabled) {
1424
AMF_RESULT res = m_AMFEncoder->SetProperty(L"RateControlPreanalysisEnable", enabled);
1425
if (res != AMF_OK) {
1426
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1427
1428
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1429
}
1430
1431
-bool Plugin::AMD::VCEEncoder::IsPreAnalysisPassEnabled() {
1432
+bool Plugin::AMD::H264Encoder::IsPreAnalysisPassEnabled() {
1433
bool enabled;
1434
AMF_RESULT res = m_AMFEncoder->GetProperty(L"RateControlPreanalysisEnable", &enabled);
1435
if (res != AMF_OK) {
1436
1437
return enabled;
1438
}
1439
1440
-void Plugin::AMD::VCEEncoder::SetVBAQEnabled(bool enabled) {
1441
+void Plugin::AMD::H264Encoder::SetVBAQEnabled(bool enabled) {
1442
const wchar_t* names[] = {
1443
L"EnableVBAQ", // 16.12.1
1444
L"EanbleVBAQ", // 16.11.5 and below.
1445
1446
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1447
}
1448
1449
-bool Plugin::AMD::VCEEncoder::IsVBAQEnabled() {
1450
+bool Plugin::AMD::H264Encoder::IsVBAQEnabled() {
1451
const wchar_t* names[] = {
1452
L"EnableVBAQ", // 16.12.1
1453
L"EanbleVBAQ", // 16.11.5 and below.
1454
1455
return enabled;
1456
}
1457
1458
-void Plugin::AMD::VCEEncoder::SetGOPSize(uint32_t size) {
1459
+void Plugin::AMD::H264Encoder::SetGOPSize(uint32_t size) {
1460
AMF_RESULT res = m_AMFEncoder->SetProperty(L"GOPSize", (uint32_t)size);
1461
if (res != AMF_OK) {
1462
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, size);
1463
1464
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", size);
1465
}
1466
1467
-uint32_t Plugin::AMD::VCEEncoder::GetGOPSize() {
1468
+uint32_t Plugin::AMD::H264Encoder::GetGOPSize() {
1469
uint32_t size;
1470
AMF_RESULT res = m_AMFEncoder->GetProperty(L"GOPSize", &size);
1471
if (res != AMF_OK) {
1472
1473
return size;
1474
}
1475
1476
-void Plugin::AMD::VCEEncoder::SetGOPAlignmentEnabled(bool enabled) {
1477
+void Plugin::AMD::H264Encoder::SetGOPAlignmentEnabled(bool enabled) {
1478
AMF_RESULT res = m_AMFEncoder->SetProperty(L"EnableGOPAlignment", enabled);
1479
if (res != AMF_OK) {
1480
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, enabled ? "Enabled" : "Disabled");
1481
1482
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", enabled ? "Enabled" : "Disabled");
1483
}
1484
1485
-bool Plugin::AMD::VCEEncoder::IsGOPAlignementEnabled() {
1486
+bool Plugin::AMD::H264Encoder::IsGOPAlignementEnabled() {
1487
bool enabled;
1488
AMF_RESULT res = m_AMFEncoder->GetProperty(L"EnableGOPAlignment", &enabled);
1489
if (res != AMF_OK) {
1490
1491
return enabled;
1492
}
1493
1494
-void Plugin::AMD::VCEEncoder::SetMaximumReferenceFrames(uint32_t numFrames) {
1495
- auto caps = VCECapabilities::GetInstance()->GetAdapterCapabilities(m_API, m_APIAdapter, VCEEncoderType_AVC);
1496
+void Plugin::AMD::H264Encoder::SetMaximumReferenceFrames(uint32_t numFrames) {
1497
+ auto caps = VCECapabilities::GetInstance()->GetAdapterCapabilities(m_API, m_APIAdapter, H264EncoderType::AVC);
1498
numFrames = clamp(numFrames,
1499
caps.minReferenceFrames,
1500
caps.maxReferenceFrames);
1501
1502
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", numFrames);
1503
}
1504
1505
-uint32_t Plugin::AMD::VCEEncoder::GetMaximumReferenceFrames() {
1506
+uint32_t Plugin::AMD::H264Encoder::GetMaximumReferenceFrames() {
1507
uint32_t numFrames;
1508
AMF_RESULT res = m_AMFEncoder->GetProperty(L"MaxNumRefFrames", &numFrames);
1509
if (res != AMF_OK) {
1510
1511
return numFrames;
1512
}
1513
1514
-void Plugin::AMD::VCEEncoder::SetAspectRatio(uint32_t num, uint32_t den) {
1515
+void Plugin::AMD::H264Encoder::SetAspectRatio(uint32_t num, uint32_t den) {
1516
AMF_RESULT res = m_AMFEncoder->SetProperty(L"AspectRatio", ::AMFConstructRate(num, den));
1517
if (res != AMF_OK) {
1518
std::vector<char> msgBuf;
1519
1520
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d:%d.", num, den);
1521
}
1522
1523
-std::pair<uint32_t, uint32_t> Plugin::AMD::VCEEncoder::GetAspectRatio() {
1524
+std::pair<uint32_t, uint32_t> Plugin::AMD::H264Encoder::GetAspectRatio() {
1525
AMFRate aspectRatio;
1526
AMF_RESULT res = m_AMFEncoder->GetProperty(L"AspectRatio", &aspectRatio);
1527
if (res != AMF_OK) {
1528
1529
return std::pair<uint32_t, uint32_t>(aspectRatio.num, aspectRatio.den);
1530
}
1531
1532
-void Plugin::AMD::VCEEncoder::SetIntraRefreshMacroblocksPerSlot(uint32_t mbs) {
1533
+void Plugin::AMD::H264Encoder::SetIntraRefreshMacroblocksPerSlot(uint32_t mbs) {
1534
AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_INTRA_REFRESH_NUM_MBS_PER_SLOT, (uint32_t)mbs);
1535
if (res != AMF_OK) {
1536
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %d failed with error %ls (code %d).", res, mbs);
1537
1538
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", mbs);
1539
}
1540
1541
-uint32_t Plugin::AMD::VCEEncoder::GetIntraRefreshMacroblocksPerSlot() {
1542
+uint32_t Plugin::AMD::H264Encoder::GetIntraRefreshMacroblocksPerSlot() {
1543
int32_t mbs;
1544
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_INTRA_REFRESH_NUM_MBS_PER_SLOT, &mbs);
1545
if (res != AMF_OK) {
1546
1547
return mbs;
1548
}
1549
1550
-void Plugin::AMD::VCEEncoder::SetIntraRefreshNumberOfStripes(uint32_t stripes) {
1551
+void Plugin::AMD::H264Encoder::SetIntraRefreshNumberOfStripes(uint32_t stripes) {
1552
stripes = clamp(stripes, 0, INT_MAX);
1553
1554
AMF_RESULT res = m_AMFEncoder->SetProperty(L"IntraRefreshNumOfStripes", (uint32_t)stripes);
1555
1556
1557
}
1558
1559
-uint32_t Plugin::AMD::VCEEncoder::GetIntraRefreshNumberOfStripes() {
1560
+uint32_t Plugin::AMD::H264Encoder::GetIntraRefreshNumberOfStripes() {
1561
uint32_t stripes;
1562
AMF_RESULT res = m_AMFEncoder->GetProperty(L"IntraRefreshNumOfStripes", &stripes);
1563
if (res != AMF_OK) {
1564
1565
return stripes;
1566
}
1567
1568
-void Plugin::AMD::VCEEncoder::SetSlicesPerFrame(uint32_t slices) {
1569
+void Plugin::AMD::H264Encoder::SetSlicesPerFrame(uint32_t slices) {
1570
slices = max(slices, 1);
1571
1572
AMF_RESULT res = m_AMFEncoder->SetProperty(AMF_VIDEO_ENCODER_SLICES_PER_FRAME, (uint32_t)slices);
1573
1574
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", slices);
1575
}
1576
1577
-uint32_t Plugin::AMD::VCEEncoder::GetSlicesPerFrame() {
1578
+uint32_t Plugin::AMD::H264Encoder::GetSlicesPerFrame() {
1579
uint32_t slices;
1580
AMF_RESULT res = m_AMFEncoder->GetProperty(AMF_VIDEO_ENCODER_SLICES_PER_FRAME, &slices);
1581
if (res != AMF_OK) {
1582
1583
return slices;
1584
}
1585
1586
-void Plugin::AMD::VCEEncoder::SetSliceMode(VCESliceMode mode) {
1587
+void Plugin::AMD::H264Encoder::SetSliceMode(H264SliceMode mode) {
1588
AMF_RESULT res = m_AMFEncoder->SetProperty(L"SliceMode", (uint32_t)mode);
1589
if (res != AMF_OK) {
1590
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, Utility::SliceModeAsString(mode));
1591
1592
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", Utility::SliceModeAsString(mode));
1593
}
1594
1595
-Plugin::AMD::VCESliceMode Plugin::AMD::VCEEncoder::GetSliceMode() {
1596
+Plugin::AMD::H264SliceMode Plugin::AMD::H264Encoder::GetSliceMode() {
1597
uint32_t mode;
1598
AMF_RESULT res = m_AMFEncoder->GetProperty(L"SliceMode", &mode);
1599
if (res != AMF_OK) {
1600
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1601
}
1602
- AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", Utility::SliceModeAsString((VCESliceMode)mode));
1603
- return (VCESliceMode)mode;
1604
+ AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", Utility::SliceModeAsString((H264SliceMode)mode));
1605
+ return (H264SliceMode)mode;
1606
}
1607
1608
-void Plugin::AMD::VCEEncoder::SetMaximumSliceSize(uint32_t size) {
1609
+void Plugin::AMD::H264Encoder::SetMaximumSliceSize(uint32_t size) {
1610
size = clamp(size, 1, INT_MAX);
1611
1612
AMF_RESULT res = m_AMFEncoder->SetProperty(L"MaxSliceSize", (uint32_t)size);
1613
1614
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", size);
1615
}
1616
1617
-uint32_t Plugin::AMD::VCEEncoder::GetMaximumSliceSize() {
1618
+uint32_t Plugin::AMD::H264Encoder::GetMaximumSliceSize() {
1619
uint32_t size;
1620
AMF_RESULT res = m_AMFEncoder->GetProperty(L"MaxSliceSize", &size);
1621
if (res != AMF_OK) {
1622
1623
return size;
1624
}
1625
1626
-void Plugin::AMD::VCEEncoder::SetSliceControlMode(VCESliceControlMode mode) {
1627
+void Plugin::AMD::H264Encoder::SetSliceControlMode(H264SliceControlMode mode) {
1628
AMF_RESULT res = m_AMFEncoder->SetProperty(L"SliceControlMode", (uint32_t)mode);
1629
if (res != AMF_OK) {
1630
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Setting to %s failed with error %ls (code %d).", res, Utility::SliceControlModeAsString(mode));
1631
1632
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %s.", Utility::SliceControlModeAsString(mode));
1633
}
1634
1635
-Plugin::AMD::VCESliceControlMode Plugin::AMD::VCEEncoder::GetSliceControlMode() {
1636
+Plugin::AMD::H264SliceControlMode Plugin::AMD::H264Encoder::GetSliceControlMode() {
1637
uint32_t mode;
1638
AMF_RESULT res = m_AMFEncoder->GetProperty(L"SliceControlMode", &mode);
1639
if (res != AMF_OK) {
1640
ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Failed with error %ls (code %d).", res);
1641
}
1642
- AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", Utility::SliceControlModeAsString((VCESliceControlMode)mode));
1643
- return (VCESliceControlMode)mode;
1644
+ AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Value is %s.", Utility::SliceControlModeAsString((H264SliceControlMode)mode));
1645
+ return (H264SliceControlMode)mode;
1646
}
1647
1648
-void Plugin::AMD::VCEEncoder::SetSliceControlSize(uint32_t size) {
1649
+void Plugin::AMD::H264Encoder::SetSliceControlSize(uint32_t size) {
1650
// If GetSliceMode() is VCESliceMode_Vertical, then it outputs nothing with the following settings:
1651
// - SliceControlMode: VCESliceControlMode_Macroblock
1652
// - SliceControlSize: < 3600
1653
1654
1655
// H264 Macroblock = 16*16 = 256
1656
switch (GetSliceControlMode()) {
1657
- case VCESliceControlMode_Off:
1658
+ case H264SliceControlMode::Off:
1659
return;
1660
- case VCESliceControlMode_Macroblock:
1661
+ case H264SliceControlMode::Macroblock:
1662
size = clamp(size, 0, (uint32_t)(ceil(m_FrameSize.first / 16) * ceil(m_FrameSize.second / 16)));
1663
break;
1664
- case VCESliceControlMode_Macroblock_Row:
1665
+ case H264SliceControlMode::Macroblock_Row:
1666
size = clamp(size, 0, (uint32_t)ceil(m_FrameSize.second / 16));
1667
break;
1668
}
1669
1670
AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Set to %d.", size);
1671
}
1672
1673
-uint32_t Plugin::AMD::VCEEncoder::GetSliceControlSize() {
1674
+uint32_t Plugin::AMD::H264Encoder::GetSliceControlSize() {
1675
uint32_t size;
1676
AMF_RESULT res = m_AMFEncoder->GetProperty(L"SliceControlSize", &size);
1677
if (res != AMF_OK) {
1678
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Source/amf.cpp -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Source/amf.cpp
Changed
154
1
2
3
class CustomWriter : public amf::AMFTraceWriter {
4
public:
5
+
6
virtual void Write(const wchar_t* scope, const wchar_t* message) override {
7
const wchar_t* realmsg = &(message[(33 + wcslen(scope) + 2)]); // Skip Time & Scope
8
size_t msgLen = wcslen(realmsg) - (sizeof(wchar_t));
9
10
- blog(LOG_INFO, "[AMF Encoder] [%.*ls][%ls] %.*ls",
11
+ blog(LOG_INFO, "[AMF Encoder] [%.*ls][%ls] %.*ls",
12
12, &(message[11]),
13
- scope,
14
+ scope,
15
msgLen, realmsg);
16
}
17
18
virtual void Flush() override {}
19
-
20
- static std::shared_ptr<CustomWriter> GetInstance() {
21
- static std::shared_ptr<CustomWriter> __instance = std::make_shared<CustomWriter>();
22
- static std::mutex __mutex;
23
-
24
- const std::lock_guard<std::mutex> lock(__mutex);
25
- return __instance;
26
- }
27
};
28
29
std::shared_ptr<Plugin::AMD::AMF> Plugin::AMD::AMF::GetInstance() {
30
31
AMF_RESULT res = AMF_OK;
32
33
// Initialize AMF Library
34
- AMF_LOG_DEBUG("<Plugin::AMD::AMF::AMF> Initializing...");
35
+ AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Initializing...");
36
37
#pragma region Null Class Members
38
m_TimerPeriod = 0;
39
40
DWORD error = GetLastError();
41
std::vector<char> buf(1024);
42
sprintf(buf.data(), "Unable to load '%ls', error code %ld.", AMF_DLL_NAME, error);
43
- AMF_LOG_ERROR("%s", buf.data());
44
- throw std::exception(buf.data(), error);
45
+ throw std::exception(buf.data());
46
}
47
- AMF_LOG_DEBUG("<Plugin::AMD::AMF::AMF> Loaded '%ls'.", AMF_DLL_NAME);
48
+ AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Loaded '%ls'.", AMF_DLL_NAME);
49
#ifdef _WIN32 // Windows: Get Product Version
50
std::vector<char> verbuf(GetFileVersionInfoSizeW(AMF_DLL_NAME, nullptr));
51
GetFileVersionInfoW(AMF_DLL_NAME, 0, (DWORD)verbuf.size(), verbuf.data());
52
53
if (!AMFQueryVersion) {
54
DWORD error = GetLastError();
55
std::vector<char> buf(1024);
56
- sprintf(buf.data(), "<Plugin::AMD::AMF::AMF> Finding Address of Function '%s' failed with error code %ld.", AMF_QUERY_VERSION_FUNCTION_NAME, error);
57
- AMF_LOG_ERROR("%s", buf.data());
58
- throw std::exception(buf.data(), error);
59
+ sprintf(buf.data(), "<" __FUNCTION_NAME__ "> Finding Address of Function '%s' failed with error code %ld.", AMF_QUERY_VERSION_FUNCTION_NAME, error);
60
+ throw std::exception(buf.data());
61
}
62
/// Query Runtime Version
63
m_AMFVersion_Compiler = AMF_FULL_VERSION;
64
res = AMFQueryVersion(&m_AMFVersion_Runtime);
65
if (res != AMF_OK)
66
- ThrowExceptionWithAMFError("<Plugin::AMD::AMF::AMF> Querying Version failed with error %ls (code %ld).", res);
67
+ ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Querying Version failed with error %ls (code %ld).", res);
68
#pragma endregion Query AMF Runtime Version
69
70
/// Find Function for Initializing AMF.
71
72
if (!AMFInit) {
73
DWORD error = GetLastError();
74
std::vector<char> buf(1024);
75
- sprintf(buf.data(), "<Plugin::AMD::AMF::AMF> Finding Address of Function '%s' failed with error code %ld.", AMF_INIT_FUNCTION_NAME, error);
76
- AMF_LOG_ERROR("%s", buf.data());
77
+ sprintf(buf.data(), "<" __FUNCTION_NAME__ "> Finding Address of Function '%s' failed with error code %ld.", AMF_INIT_FUNCTION_NAME, error);
78
throw std::exception(buf.data(), error);
79
} else {
80
res = AMFInit(m_AMFVersion_Runtime, &m_AMFFactory);
81
if (res != AMF_OK)
82
- ThrowExceptionWithAMFError("<Plugin::AMD::AMF::AMF> Initializing AMF Library failed with error %ls (code %ld).", res);
83
+ ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Initializing AMF Library failed with error %ls (code %ld).", res);
84
}
85
- AMF_LOG_DEBUG("<Plugin::AMD::AMF::AMF> AMF Library initialized.");
86
+ AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> AMF Library initialized.");
87
88
/// Retrieve Trace Object.
89
res = m_AMFFactory->GetTrace(&m_AMFTrace);
90
if (res != AMF_OK) {
91
- ThrowExceptionWithAMFError("<Plugin::AMD::AMF::AMF> Retrieving Trace object failed with error %ls (code %ld).", res);
92
+ ThrowExceptionWithAMFError("<" __FUNCTION_NAME__ "> Retrieving Trace object failed with error %ls (code %ld).", res);
93
}
94
95
/// Retrieve Debug Object.
96
res = m_AMFFactory->GetDebug(&m_AMFDebug);
97
if (res != AMF_OK) {
98
- AMF_LOG_ERROR("<Plugin::AMD::AMF::AMF> Retrieving Debug object failed with error code %ls (code %ld).", res);
99
+ AMF_LOG_ERROR("<" __FUNCTION_NAME__ "> Retrieving Debug object failed with error code %ls (code %ld).", res);
100
throw std::exception("", res);
101
}
102
103
- /// Register Custom Trace Writer and disable Debug Tracing.
104
- m_AMFTrace->RegisterWriter(L"OBSWriter", CustomWriter::GetInstance().get(), true);
105
+ /// Register Trace Writer and disable Debug Tracing.
106
+ m_TraceWriter = new CustomWriter();
107
+ m_AMFTrace->RegisterWriter(L"OBSWriter", m_TraceWriter, true);
108
this->EnableDebugTrace(false);
109
110
// Log success
111
112
lProductVersionSize, pProductVersion
113
);
114
115
- AMF_LOG_DEBUG("<Plugin::AMD::AMF::AMF> Initialized.");
116
+ AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Initialized.");
117
}
118
119
Plugin::AMD::AMF::~AMF() {
120
- AMF_LOG_DEBUG("<Plugin::AMD::AMF::AMF> Finalizing.");
121
+ AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Finalizing.");
122
123
- /// Unregister Writer
124
- if (m_AMFTrace)
125
- m_AMFTrace->UnregisterWriter(L"OBSWriter");
126
+ /// Unregister Trace Writer
127
+ m_AMFTrace->UnregisterWriter(L"OBSWriter");
128
+ delete m_TraceWriter;
129
+ m_TraceWriter = nullptr;
130
131
// Free Library again
132
if (m_AMFModule)
133
134
AMFInit = nullptr;
135
#pragma endregion Null Class Members
136
137
- AMF_LOG_DEBUG("<Plugin::AMD::AMF::AMF> Finalized.");
138
+ AMF_LOG_DEBUG("<" __FUNCTION_NAME__ "> Finalized.");
139
}
140
141
amf::AMFFactory* Plugin::AMD::AMF::GetFactory() {
142
143
144
void Plugin::AMD::AMF::EnableDebugTrace(bool enable) {
145
if (!m_AMFTrace)
146
- throw std::exception(__FUNCTION_NAME__ " called without a AMFTrace object!");
147
+ throw std::exception("<" __FUNCTION_NAME__ "> called without a AMFTrace object!");
148
if (!m_AMFDebug)
149
- throw std::exception(__FUNCTION_NAME__ " called without a AMFDebug object!");
150
+ throw std::exception("<" __FUNCTION_NAME__ "> called without a AMFDebug object!");
151
152
m_AMFTrace->EnableWriter(AMF_TRACE_WRITER_CONSOLE, false);
153
m_AMFTrace->SetWriterLevel(AMF_TRACE_WRITER_CONSOLE, AMF_TRACE_ERROR);
154
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Source/api-d3d11.cpp -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Source/api-d3d11.cpp
Changed
10
1
2
delete instance;
3
}
4
5
-Plugin::API::APIType Plugin::API::Direct3D11::GetType() {
6
- return APIType_Direct3D11;
7
+Plugin::API::Type Plugin::API::Direct3D11::GetType() {
8
+ return Type::Direct3D11;
9
}
10
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Source/api-d3d9.cpp -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Source/api-d3d9.cpp
Changed
10
1
2
delete instance;
3
}
4
5
-Plugin::API::APIType Plugin::API::Direct3D9::GetType() {
6
- return APIType_Direct3D9;
7
+Plugin::API::Type Plugin::API::Direct3D9::GetType() {
8
+ return Type::Direct3D9;
9
}
10
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Source/api-host.cpp -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Source/api-host.cpp
Changed
12
1
2
return "Host";
3
}
4
5
-Plugin::API::APIType Plugin::API::Host::GetType() {
6
- return APIType_Host;
7
+Plugin::API::Type Plugin::API::Host::GetType() {
8
+ return Type::Host;
9
}
10
11
std::vector<Adapter> Plugin::API::Host::EnumerateAdapters() {
12
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Source/api-opengl.cpp -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Source/api-opengl.cpp
Changed
10
1
2
return nullptr;
3
}
4
5
-Plugin::API::APIType Plugin::API::OpenGL::GetType() {
6
- return APIType_OpenGL;
7
+Plugin::API::Type Plugin::API::OpenGL::GetType() {
8
+ return Type::OpenGL;
9
}
10
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Source/enc-h264.cpp -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Source/enc-h264.cpp
Changed
1486
1
2
using namespace Plugin::AMD;
3
using namespace Plugin::Interface;
4
5
-enum Presets {
6
+enum class Presets : int8_t {
7
None = -1,
8
ResetToDefaults = 0,
9
Recording,
10
11
Twitch,
12
YouTube,
13
};
14
-enum ViewMode {
15
+enum class ViewMode :uint8_t {
16
Basic,
17
Advanced,
18
Expert,
19
20
bool haveAVCsupport = false;
21
for (auto api : Plugin::API::Base::EnumerateAPIs()) {
22
for (auto adapter : api->EnumerateAdapters()) {
23
- auto caps = VCECapabilities::GetInstance()->GetAdapterCapabilities(api, adapter, VCEEncoderType_AVC);
24
+ auto caps = VCECapabilities::GetInstance()->GetAdapterCapabilities(api, adapter, H264EncoderType::AVC);
25
if (caps.acceleration_type != amf::AMF_ACCEL_NOT_SUPPORTED)
26
haveAVCsupport = true;
27
}
28
29
AMF_LOG_ERROR("%s", e->what());
30
delete e;
31
} catch (...) {
32
- AMF_LOG_ERROR("Unknown Exception during start up.");
33
+ AMF_LOG_ERROR("Unknown Exception.");
34
}
35
if (enc)
36
delete enc;
37
38
AMF_LOG_ERROR("%s", e->what());
39
delete e;
40
} catch (...) {
41
- AMF_LOG_ERROR("Unknown Exception during shut down.");
42
+ AMF_LOG_ERROR("Unknown Exception.");
43
}
44
data = nullptr;
45
}
46
47
try {
48
return static_cast<Plugin::Interface::H264Interface*>(data)->encode(frame, packet, received_packet);
49
} catch (std::exception e) {
50
- AMF_LOG_ERROR("Exception: %s", e.what());
51
- AMF_LOG_ERROR("Unable to encode, see log for more information.");
52
- return false;
53
+ AMF_LOG_ERROR("%s", e.what());
54
+ } catch (std::exception* e) {
55
+ AMF_LOG_ERROR("%s", e->what());
56
+ delete e;
57
} catch (...) {
58
+ AMF_LOG_ERROR("Unknown Exception.");
59
throw;
60
}
61
+ return false;
62
}
63
64
void Plugin::Interface::H264Interface::get_defaults(obs_data_t *data) {
65
66
#pragma endregion OBS - Enforce Streaming Service Restrictions
67
68
// Preset
69
- obs_data_set_default_int(data, AMF_H264_PRESET, -1);
70
+ obs_data_set_default_int(data, AMF_H264_PRESET, static_cast<int32_t>(Presets::None));
71
72
// Static Properties
73
- obs_data_set_default_int(data, AMF_H264_USAGE, VCEUsage_Transcoding);
74
- obs_data_set_default_int(data, AMF_H264_QUALITY_PRESET, VCEQualityPreset_Balanced);
75
- obs_data_set_default_int(data, AMF_H264_PROFILE, VCEProfile_Main);
76
- obs_data_set_default_int(data, AMF_H264_PROFILELEVEL, VCEProfileLevel_Automatic);
77
+ obs_data_set_default_int(data, AMF_H264_USAGE, static_cast<int32_t>(H264Usage::Transcoding));
78
+ obs_data_set_default_int(data, AMF_H264_QUALITY_PRESET, static_cast<int32_t>(H264QualityPreset::Balanced));
79
+ obs_data_set_default_int(data, AMF_H264_PROFILE, static_cast<int32_t>(H264Profile::Main));
80
+ obs_data_set_default_int(data, AMF_H264_PROFILELEVEL, static_cast<int32_t>(H264ProfileLevel::Automatic));
81
82
// Rate Control Properties
83
obs_data_set_int(data, "last" vstr(AMF_H264_RATECONTROLMETHOD), -1);
84
- obs_data_set_default_int(data, AMF_H264_RATECONTROLMETHOD, VCERateControlMethod_ConstantBitrate);
85
+ obs_data_set_default_int(data, AMF_H264_RATECONTROLMETHOD, static_cast<int32_t>(H264RateControlMethod::ConstantBitrate));
86
obs_data_set_default_int(data, AMF_H264_BITRATE_TARGET, 3500);
87
obs_data_set_default_int(data, AMF_H264_BITRATE_PEAK, 9000);
88
- obs_data_set_default_int(data, AMF_H264_QP_MINIMUM, 0);
89
+ obs_data_set_default_int(data, AMF_H264_QP_MINIMUM, 11);
90
obs_data_set_default_int(data, AMF_H264_QP_MAXIMUM, 51);
91
obs_data_set_default_int(data, AMF_H264_QP_IFRAME, 22);
92
obs_data_set_default_int(data, AMF_H264_QP_PFRAME, 22);
93
94
obs_data_set_int(data, "last" vstr(AMF_H264_VBVBUFFER), -1);
95
obs_data_set_default_int(data, AMF_H264_VBVBUFFER, 0);
96
obs_data_set_default_int(data, AMF_H264_VBVBUFFER_SIZE, 3500);
97
- obs_data_set_default_double(data, AMF_H264_VBVBUFFER_STRICTNESS, 0);
98
+ obs_data_set_default_double(data, AMF_H264_VBVBUFFER_STRICTNESS, 50);
99
obs_data_set_default_double(data, AMF_H264_VBVBUFFER_FULLNESS, 100);
100
obs_data_set_default_int(data, AMF_H264_MAXIMUMACCESSUNITSIZE, 0);
101
obs_data_set_default_int(data, AMF_H264_FILLERDATA, 1);
102
103
obs_data_set_default_double(data, AMF_H264_KEYFRAME_INTERVAL, 2);
104
obs_data_set_default_int(data, AMF_H264_IDR_PERIOD, 60);
105
obs_data_set_int(data, "last" vstr(AMF_H264_BFRAME_PATTERN), -1);
106
- obs_data_set_default_int(data, AMF_H264_BFRAME_PATTERN, VCEBFramePattern_None);
107
+ obs_data_set_default_int(data, AMF_H264_BFRAME_PATTERN, static_cast<int32_t>(H264BFramePattern::None));
108
obs_data_set_int(data, "last" vstr(AMF_H264_BFRAME_REFERENCE), -1);
109
obs_data_set_default_int(data, AMF_H264_BFRAME_REFERENCE, 0);
110
obs_data_set_default_int(data, AMF_H264_BFRAME_REFERENCEDELTAQP, 2);
111
112
obs_data_set_default_int(data, AMF_H264_DEBLOCKINGFILTER, 1);
113
114
// Miscellaneous Control Properties
115
- obs_data_set_default_int(data, AMF_H264_SCANTYPE, VCEScanType_Progressive);
116
+ obs_data_set_default_int(data, AMF_H264_SCANTYPE, static_cast<int32_t>(H264ScanType::Progressive));
117
obs_data_set_default_int(data, AMF_H264_MOTIONESTIMATION, 3);
118
119
// Experimental Properties
120
obs_data_set_default_int(data, AMF_H264_MAXIMUMLTRFRAMES, 0);
121
- obs_data_set_default_int(data, AMF_H264_CODINGTYPE, VCECodingType_Default);
122
+ obs_data_set_default_int(data, AMF_H264_CODINGTYPE, static_cast<int32_t>(H264CodingType::Default));
123
obs_data_set_default_int(data, AMF_H264_HEADER_INSERTION_SPACING, 0);
124
obs_data_set_default_int(data, AMF_H264_SLICESPERFRAME, 1);
125
- obs_data_set_default_int(data, AMF_H264_SLICEMODE, VCESliceMode_Horizontal);
126
+ obs_data_set_default_int(data, AMF_H264_SLICEMODE, static_cast<int32_t>(H264SliceMode::Horizontal));
127
obs_data_set_default_int(data, AMF_H264_MAXIMUMSLICESIZE, INT_MAX);
128
- obs_data_set_default_int(data, AMF_H264_SLICECONTROLMODE, VCESliceControlMode_Off);
129
+ obs_data_set_default_int(data, AMF_H264_SLICECONTROLMODE, static_cast<int32_t>(H264SliceControlMode::Off));
130
obs_data_set_default_int(data, AMF_H264_SLICECONTROLSIZE, 0);
131
obs_data_set_default_int(data, AMF_H264_INTRAREFRESH_NUMBEROFSTRIPES, 0);
132
obs_data_set_default_int(data, AMF_H264_INTRAREFRESH_MACROBLOCKSPERSLOT, 0);
133
134
obs_data_set_default_int(data, AMF_H264_VIDEOADAPTER, 0);
135
obs_data_set_default_int(data, AMF_H264_OPENCL, 0);
136
obs_data_set_int(data, "last" vstr(AMF_H264_VIEW), -1);
137
- obs_data_set_default_int(data, AMF_H264_VIEW, ViewMode::Basic);
138
+ obs_data_set_default_int(data, AMF_H264_VIEW, static_cast<int32_t>(ViewMode::Basic));
139
obs_data_set_default_bool(data, AMF_H264_DEBUG, false);
140
+ obs_data_set_default_int(data, AMF_H264_VERSION, 0x0001000400030005ull);
141
}
142
143
static void fill_api_list(obs_property_t* p) {
144
145
p = obs_properties_add_list(props, AMF_H264_PRESET, TEXT_T(AMF_H264_PRESET), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
146
obs_property_set_modified_callback(p, properties_modified);
147
obs_property_list_add_int(p, "", -1);
148
- obs_property_list_add_int(p, TEXT_T(AMF_H264_PRESET_RESETTODEFAULTS), Presets::ResetToDefaults);
149
- obs_property_list_add_int(p, TEXT_T(AMF_H264_PRESET_RECORDING), Presets::Recording);
150
- obs_property_list_add_int(p, TEXT_T(AMF_H264_PRESET_HIGHQUALITY), Presets::HighQuality);
151
- obs_property_list_add_int(p, TEXT_T(AMF_H264_PRESET_INDISTINGUISHABLE), Presets::Indistinguishable);
152
- obs_property_list_add_int(p, TEXT_T(AMF_H264_PRESET_LOSSLESS), Presets::Lossless);
153
- obs_property_list_add_int(p, TEXT_T(AMF_H264_PRESET_TWITCH), Presets::Twitch);
154
- obs_property_list_add_int(p, TEXT_T(AMF_H264_PRESET_YOUTUBE), Presets::YouTube);
155
+ obs_property_list_add_int(p, TEXT_T(AMF_H264_PRESET_RESETTODEFAULTS), static_cast<int32_t>(Presets::ResetToDefaults));
156
+ obs_property_list_add_int(p, TEXT_T(AMF_H264_PRESET_RECORDING), static_cast<int32_t>(Presets::Recording));
157
+ obs_property_list_add_int(p, TEXT_T(AMF_H264_PRESET_HIGHQUALITY), static_cast<int32_t>(Presets::HighQuality));
158
+ obs_property_list_add_int(p, TEXT_T(AMF_H264_PRESET_INDISTINGUISHABLE), static_cast<int32_t>(Presets::Indistinguishable));
159
+ obs_property_list_add_int(p, TEXT_T(AMF_H264_PRESET_LOSSLESS), static_cast<int32_t>(Presets::Lossless));
160
+ obs_property_list_add_int(p, TEXT_T(AMF_H264_PRESET_TWITCH), static_cast<int32_t>(Presets::Twitch));
161
+ obs_property_list_add_int(p, TEXT_T(AMF_H264_PRESET_YOUTUBE), static_cast<int32_t>(Presets::YouTube));
162
#pragma endregion Preset
163
164
#pragma region Static Properties
165
#pragma region Usage
166
p = obs_properties_add_list(props, AMF_H264_USAGE, TEXT_T(AMF_H264_USAGE), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
167
obs_property_set_long_description(p, TEXT_T(AMF_H264_USAGE_DESCRIPTION));
168
- obs_property_list_add_int(p, TEXT_T(AMF_H264_USAGE_TRANSCODING), VCEUsage_Transcoding);
169
- obs_property_list_add_int(p, TEXT_T(AMF_H264_USAGE_ULTRALOWLATENCY), VCEUsage_UltraLowLatency);
170
- obs_property_list_add_int(p, TEXT_T(AMF_H264_USAGE_LOWLATENCY), VCEUsage_LowLatency);
171
+ obs_property_list_add_int(p, TEXT_T(AMF_H264_USAGE_TRANSCODING), static_cast<int32_t>(H264Usage::Transcoding));
172
+ obs_property_list_add_int(p, TEXT_T(AMF_H264_USAGE_ULTRALOWLATENCY), static_cast<int32_t>(H264Usage::UltraLowLatency));
173
+ obs_property_list_add_int(p, TEXT_T(AMF_H264_USAGE_LOWLATENCY), static_cast<int32_t>(H264Usage::LowLatency));
174
// Webcam requires SVC, which is not something OBSs properties API makes easy to support. Nor would it look like anything usable.
175
//obs_property_list_add_int(list, TEXT_T(AMF_H264_USAGE_WEBCAM), VCEUsage_Webcam);
176
#pragma endregion Usage
177
178
#pragma region Quality Preset
179
p = obs_properties_add_list(props, AMF_H264_QUALITY_PRESET, TEXT_T(AMF_H264_QUALITY_PRESET), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
180
obs_property_set_long_description(p, TEXT_T(AMF_H264_QUALITY_PRESET_DESCRIPTION));
181
- obs_property_list_add_int(p, TEXT_T(AMF_H264_QUALITY_PRESET_SPEED), VCEQualityPreset_Speed);
182
- obs_property_list_add_int(p, TEXT_T(AMF_H264_QUALITY_PRESET_BALANCED), VCEQualityPreset_Balanced);
183
- obs_property_list_add_int(p, TEXT_T(AMF_H264_QUALITY_PRESET_QUALITY), VCEQualityPreset_Quality);
184
+ obs_property_list_add_int(p, TEXT_T(AMF_H264_QUALITY_PRESET_SPEED), static_cast<int32_t>(H264QualityPreset::Speed));
185
+ obs_property_list_add_int(p, TEXT_T(AMF_H264_QUALITY_PRESET_BALANCED), static_cast<int32_t>(H264QualityPreset::Balanced));
186
+ obs_property_list_add_int(p, TEXT_T(AMF_H264_QUALITY_PRESET_QUALITY), static_cast<int32_t>(H264QualityPreset::Quality));
187
#pragma endregion Quality Preset
188
189
#pragma region Profile
190
191
#pragma region Method
192
p = obs_properties_add_list(props, AMF_H264_RATECONTROLMETHOD, TEXT_T(AMF_H264_RATECONTROLMETHOD), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
193
obs_property_set_long_description(p, TEXT_T(AMF_H264_RATECONTROLMETHOD_DESCRIPTION));
194
- obs_property_list_add_int(p, TEXT_T(AMF_H264_RATECONTROLMETHOD_CQP), VCERateControlMethod_ConstantQP);
195
- obs_property_list_add_int(p, TEXT_T(AMF_H264_RATECONTROLMETHOD_CBR), VCERateControlMethod_ConstantBitrate);
196
- obs_property_list_add_int(p, TEXT_T(AMF_H264_RATECONTROLMETHOD_VBR), VCERateControlMethod_VariableBitrate_PeakConstrained);
197
- obs_property_list_add_int(p, TEXT_T(AMF_H264_RATECONTROLMETHOD_VBR_LAT), VCERateControlMethod_VariableBitrate_LatencyConstrained);
198
+ obs_property_list_add_int(p, TEXT_T(AMF_H264_RATECONTROLMETHOD_CQP), static_cast<int32_t>(H264RateControlMethod::ConstantQP));
199
+ obs_property_list_add_int(p, TEXT_T(AMF_H264_RATECONTROLMETHOD_CBR), static_cast<int32_t>(H264RateControlMethod::ConstantBitrate));
200
+ obs_property_list_add_int(p, TEXT_T(AMF_H264_RATECONTROLMETHOD_VBR), static_cast<int32_t>(H264RateControlMethod::VariableBitrate_PeakConstrained));
201
+ obs_property_list_add_int(p, TEXT_T(AMF_H264_RATECONTROLMETHOD_VBR_LAT), static_cast<int32_t>(H264RateControlMethod::VariableBitrate_LatencyConstrained));
202
obs_property_set_modified_callback(p, properties_modified);
203
#pragma endregion Method
204
205
#pragma region Method Parameters
206
/// Bitrate Constraints
207
p = obs_properties_add_int(props, AMF_H264_BITRATE_TARGET, TEXT_T(AMF_H264_BITRATE_TARGET), 0,
208
- 1, 1);
209
+ 1, 1);
210
obs_property_set_long_description(p, TEXT_T(AMF_H264_BITRATE_TARGET_DESCRIPTION));
211
p = obs_properties_add_int(props, AMF_H264_BITRATE_PEAK, TEXT_T(AMF_H264_BITRATE_PEAK), 0,
212
- 1, 1);
213
+ 1, 1);
214
obs_property_set_long_description(p, TEXT_T(AMF_H264_BITRATE_PEAK_DESCRIPTION));
215
216
/// Minimum QP, Maximum QP
217
218
#pragma region B-Frames
219
/// B-Frames Pattern
220
p = obs_properties_add_int_slider(props, AMF_H264_BFRAME_PATTERN, TEXT_T(AMF_H264_BFRAME_PATTERN),
221
- VCEBFramePattern_None, VCEBFramePattern_Three, 1);
222
+ static_cast<int32_t>(H264BFramePattern::None),
223
+ static_cast<int32_t>(H264BFramePattern::Three),
224
+ 1);
225
obs_property_set_long_description(p, TEXT_T(AMF_H264_BFRAME_PATTERN_DESCRIPTION));
226
obs_property_set_modified_callback(p, properties_modified);
227
/// Enable Reference to B-Frames (2nd Generation GCN and newer)
228
229
/// Scan Type
230
p = obs_properties_add_list(props, AMF_H264_SCANTYPE, TEXT_T(AMF_H264_SCANTYPE), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
231
obs_property_set_long_description(p, TEXT_T(AMF_H264_SCANTYPE_DESCRIPTION));
232
- obs_property_list_add_int(p, TEXT_T(AMF_H264_SCANTYPE_PROGRESSIVE), VCEScanType_Progressive);
233
- obs_property_list_add_int(p, TEXT_T(AMF_H264_SCANTYPE_INTERLACED), VCEScanType_Interlaced);
234
+ obs_property_list_add_int(p, TEXT_T(AMF_H264_SCANTYPE_PROGRESSIVE), static_cast<int32_t>(H264ScanType::Progressive));
235
+ obs_property_list_add_int(p, TEXT_T(AMF_H264_SCANTYPE_INTERLACED), static_cast<int32_t>(H264ScanType::Interlaced));
236
237
/// Motion Estimation
238
p = obs_properties_add_list(props, AMF_H264_MOTIONESTIMATION, TEXT_T(AMF_H264_MOTIONESTIMATION), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
239
240
#pragma region Coding Type
241
p = obs_properties_add_list(props, AMF_H264_CODINGTYPE, TEXT_T(AMF_H264_CODINGTYPE), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
242
obs_property_set_long_description(p, TEXT_T(AMF_H264_CODINGTYPE_DESCRIPTION));
243
- obs_property_list_add_int(p, TEXT_T(AMF_UTIL_DEFAULT), VCECodingType_Default);
244
- obs_property_list_add_int(p, "CABAC", VCECodingType_CABAC);
245
- obs_property_list_add_int(p, "CALVC", VCECodingType_CALVC);
246
+ obs_property_list_add_int(p, TEXT_T(AMF_UTIL_DEFAULT), static_cast<int32_t>(H264CodingType::Default));
247
+ obs_property_list_add_int(p, "CABAC", static_cast<int32_t>(H264CodingType::CABAC));
248
+ obs_property_list_add_int(p, "CALVC", static_cast<int32_t>(H264CodingType::CALVC));
249
#pragma endregion Coding Type
250
251
#pragma region Long Term Reference Frames
252
253
/// Slice Mode
254
p = obs_properties_add_list(props, AMF_H264_SLICEMODE, TEXT_T(AMF_H264_SLICEMODE), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
255
obs_property_set_long_description(p, TEXT_T(AMF_H264_SLICEMODE_DESCRIPTION));
256
- obs_property_list_add_int(p, "Horizontal", VCESliceMode_Horizontal);
257
- obs_property_list_add_int(p, "Vertical", VCESliceMode_Vertical);
258
+ obs_property_list_add_int(p, "Horizontal", static_cast<int32_t>(H264SliceMode::Horizontal));
259
+ obs_property_list_add_int(p, "Vertical", static_cast<int32_t>(H264SliceMode::Vertical));
260
261
/// Maximum Slice Size
262
p = obs_properties_add_int_slider(props, AMF_H264_MAXIMUMSLICESIZE, TEXT_T(AMF_H264_MAXIMUMSLICESIZE), 1, INT_MAX, 1);
263
264
/// Slice Control Mode
265
p = obs_properties_add_list(props, AMF_H264_SLICECONTROLMODE, TEXT_T(AMF_H264_SLICECONTROLMODE), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
266
obs_property_set_long_description(p, TEXT_T(AMF_H264_SLICECONTROLMODE_DESCRIPTION));
267
- obs_property_list_add_int(p, Utility::SliceControlModeAsString(VCESliceControlMode_Off), VCESliceControlMode_Off);
268
- obs_property_list_add_int(p, Utility::SliceControlModeAsString(VCESliceControlMode_Macroblock), VCESliceControlMode_Macroblock);
269
- obs_property_list_add_int(p, Utility::SliceControlModeAsString(VCESliceControlMode_Macroblock_Row), VCESliceControlMode_Macroblock_Row);
270
+ obs_property_list_add_int(p, Utility::SliceControlModeAsString(H264SliceControlMode::Off), static_cast<int32_t>(H264SliceControlMode::Off));
271
+ obs_property_list_add_int(p, Utility::SliceControlModeAsString(H264SliceControlMode::Macroblock), static_cast<int32_t>(H264SliceControlMode::Macroblock));
272
+ obs_property_list_add_int(p, Utility::SliceControlModeAsString(H264SliceControlMode::Macroblock_Row), static_cast<int32_t>(H264SliceControlMode::Macroblock_Row));
273
274
/// Slice Control Size
275
p = obs_properties_add_int_slider(props, AMF_H264_SLICECONTROLSIZE, TEXT_T(AMF_H264_SLICECONTROLSIZE), 0, 34560, 1); // 4096x2160 / 16x16
276
277
/// View Mode
278
p = obs_properties_add_list(props, AMF_H264_VIEW, TEXT_T(AMF_H264_VIEW), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
279
obs_property_set_long_description(p, TEXT_T(AMF_H264_VIEW_DESCRIPTION));
280
- obs_property_list_add_int(p, TEXT_T(AMF_H264_VIEW_BASIC), ViewMode::Basic);
281
- obs_property_list_add_int(p, TEXT_T(AMF_H264_VIEW_ADVANCED), ViewMode::Advanced);
282
- obs_property_list_add_int(p, TEXT_T(AMF_H264_VIEW_EXPERT), ViewMode::Expert);
283
- obs_property_list_add_int(p, TEXT_T(AMF_H264_VIEW_MASTER), ViewMode::Master);
284
+ obs_property_list_add_int(p, TEXT_T(AMF_H264_VIEW_BASIC), static_cast<int32_t>(ViewMode::Basic));
285
+ obs_property_list_add_int(p, TEXT_T(AMF_H264_VIEW_ADVANCED), static_cast<int32_t>(ViewMode::Advanced));
286
+ obs_property_list_add_int(p, TEXT_T(AMF_H264_VIEW_EXPERT), static_cast<int32_t>(ViewMode::Expert));
287
+ obs_property_list_add_int(p, TEXT_T(AMF_H264_VIEW_MASTER), static_cast<int32_t>(ViewMode::Master));
288
obs_property_set_modified_callback(p, properties_modified);
289
290
/// Debug
291
292
}
293
}
294
295
+static void obs_data_transfer_settings(obs_data_t * data) {
296
+ #pragma region Version Differences
297
+ uint64_t version = obs_data_get_int(data, AMF_H264_VERSION);
298
+ switch (version) {
299
+ case 0x0001000400030005ull:
300
+ obs_data_set_double(data, AMF_H264_VBVBUFFER_STRICTNESS, obs_data_get_double(data, AMF_H264_VBVBUFFER_STRICTNESS) + 50.0);
301
+ case PLUGIN_VERSION_FULL:
302
+ obs_data_set_int(data, AMF_H264_VERSION, PLUGIN_VERSION_FULL);
303
+ break;
304
+ }
305
+ #pragma endregion Version Differences
306
+}
307
+
308
bool Plugin::Interface::H264Interface::properties_modified(obs_properties_t *props, obs_property_t *, obs_data_t *data) {
309
bool result = false;
310
obs_property_t* p;
311
312
+ obs_data_transfer_settings(data);
313
+
314
#pragma region Presets
315
- Presets lastPreset = (Presets)obs_data_get_int(data, "last" vstr(AMF_H264_PRESET)),
316
- preset = (Presets)obs_data_get_int(data, AMF_H264_PRESET);
317
+ Presets lastPreset = static_cast<Presets>(obs_data_get_int(data, "last" vstr(AMF_H264_PRESET))),
318
+ preset = static_cast<Presets>(obs_data_get_int(data, AMF_H264_PRESET));
319
if (lastPreset != preset) { // Reset State
320
obs_property_t* pn = obs_properties_first(props);
321
do {
322
323
result = true;
324
325
switch (preset) {
326
- case ResetToDefaults:
327
+ case Presets::ResetToDefaults:
328
#pragma region Default
329
- {
330
- obs_property_t* pn = obs_properties_first(props);
331
- do {
332
- const char* name = obs_property_name(pn);
333
-
334
- // Do not reset Video Adapter or API.
335
- if ((strcmp(name, AMF_H264_VIDEOAPI) == 0) || (strcmp(name, AMF_H264_VIDEOADAPTER) == 0))
336
- continue;
337
-
338
- switch (obs_property_get_type(pn)) {
339
- case obs_property_type::OBS_PROPERTY_BOOL:
340
- obs_data_set_bool(data, name, obs_data_get_default_bool(data, name));
341
- break;
342
- case obs_property_type::OBS_PROPERTY_FLOAT:
343
- obs_data_set_double(data, name, obs_data_get_default_double(data, name));
344
- break;
345
- case obs_property_type::OBS_PROPERTY_INT:
346
- obs_data_set_int(data, name, obs_data_get_default_int(data, name));
347
- break;
348
- case obs_property_type::OBS_PROPERTY_TEXT:
349
- obs_data_set_string(data, name, obs_data_get_default_string(data, name));
350
- break;
351
- case obs_property_type::OBS_PROPERTY_LIST:
352
- switch (obs_property_list_format(pn)) {
353
- case obs_combo_format::OBS_COMBO_FORMAT_INT:
354
- obs_data_set_int(data, name, obs_data_get_default_int(data, name));
355
- break;
356
- case obs_combo_format::OBS_COMBO_FORMAT_FLOAT:
357
- obs_data_set_double(data, name, obs_data_get_default_double(data, name));
358
- break;
359
- case obs_combo_format::OBS_COMBO_FORMAT_STRING:
360
- obs_data_set_string(data, name, obs_data_get_default_string(data, name));
361
- break;
362
- }
363
- break;
364
- }
365
- obs_property_set_enabled(pn, true);
366
- } while (obs_property_next(&pn));
367
- }
368
- break;
369
- #pragma endregion Default
370
- case Recording:
371
+ {
372
+ obs_property_t* pn = obs_properties_first(props);
373
+ do {
374
+ const char* name = obs_property_name(pn);
375
+
376
+ // Do not reset Video Adapter or API.
377
+ if ((strcmp(name, AMF_H264_VIDEOAPI) == 0) || (strcmp(name, AMF_H264_VIDEOADAPTER) == 0))
378
+ continue;
379
+
380
+ switch (obs_property_get_type(pn)) {
381
+ case obs_property_type::OBS_PROPERTY_BOOL:
382
+ obs_data_set_bool(data, name, obs_data_get_default_bool(data, name));
383
+ break;
384
+ case obs_property_type::OBS_PROPERTY_FLOAT:
385
+ obs_data_set_double(data, name, obs_data_get_default_double(data, name));
386
+ break;
387
+ case obs_property_type::OBS_PROPERTY_INT:
388
+ obs_data_set_int(data, name, obs_data_get_default_int(data, name));
389
+ break;
390
+ case obs_property_type::OBS_PROPERTY_TEXT:
391
+ obs_data_set_string(data, name, obs_data_get_default_string(data, name));
392
+ break;
393
+ case obs_property_type::OBS_PROPERTY_LIST:
394
+ switch (obs_property_list_format(pn)) {
395
+ case obs_combo_format::OBS_COMBO_FORMAT_INT:
396
+ obs_data_set_int(data, name, obs_data_get_default_int(data, name));
397
+ break;
398
+ case obs_combo_format::OBS_COMBO_FORMAT_FLOAT:
399
+ obs_data_set_double(data, name, obs_data_get_default_double(data, name));
400
+ break;
401
+ case obs_combo_format::OBS_COMBO_FORMAT_STRING:
402
+ obs_data_set_string(data, name, obs_data_get_default_string(data, name));
403
+ break;
404
+ }
405
+ break;
406
+ }
407
+ obs_property_set_enabled(pn, true);
408
+ } while (obs_property_next(&pn));
409
+ }
410
+ break;
411
+ #pragma endregion Default
412
+ case Presets::Recording:
413
#pragma region Recording
414
// Static Properties
415
//obs_data_set_int(data, AMF_H264_USAGE, VCEUsage_Transcoding);
416
- obs_data_set_int(data, AMF_H264_PROFILE, VCEProfile_High);
417
+ obs_data_set_int(data, AMF_H264_PROFILE, static_cast<int32_t>(H264Profile::High));
418
obs_property_set_enabled(obs_properties_get(props, AMF_H264_PROFILE), false);
419
- obs_data_set_int(data, AMF_H264_PROFILELEVEL, VCEProfileLevel_Automatic);
420
+ obs_data_set_int(data, AMF_H264_PROFILELEVEL, static_cast<int32_t>(H264ProfileLevel::Automatic));
421
obs_property_set_enabled(obs_properties_get(props, AMF_H264_PROFILELEVEL), false);
422
//obs_data_set_int(data, AMF_H264_MAXIMUMLTRFRAMES, obs_data_get_default_int(data, AMF_H264_MAXIMUMLTRFRAMES));
423
424
// Rate Control Properties
425
- obs_data_set_int(data, AMF_H264_RATECONTROLMETHOD, VCERateControlMethod_VariableBitrate_LatencyConstrained);
426
+ obs_data_set_int(data, AMF_H264_RATECONTROLMETHOD, static_cast<int32_t>(H264RateControlMethod::VariableBitrate_LatencyConstrained));
427
obs_property_set_enabled(obs_properties_get(props, AMF_H264_RATECONTROLMETHOD), false);
428
if (obs_data_get_int(data, AMF_H264_BITRATE_TARGET) < 10000)
429
obs_data_set_int(data, AMF_H264_BITRATE_TARGET, 10000);
430
obs_property_int_set_limits(obs_properties_get(props, AMF_H264_BITRATE_TARGET), 10000, 100000, 1);
431
- //obs_data_set_int(data, AMF_H264_BITRATE_PEAK, VCECapabilities::GetInstance()->GetEncoderCaps(VCEEncoderType_AVC)->maxBitrate / (obs_data_get_bool(data, AMF_H264_UNLOCK_PROPERTIES) ? 1 : 1000));
432
- obs_data_set_int(data, AMF_H264_QP_MINIMUM, 0);
433
+ obs_data_default_single(props, data, AMF_H264_QP_MINIMUM);
434
obs_property_set_enabled(obs_properties_get(props, AMF_H264_QP_MINIMUM), false);
435
- obs_data_set_int(data, AMF_H264_QP_MAXIMUM, 51);
436
+ obs_data_default_single(props, data, AMF_H264_QP_MAXIMUM);
437
obs_property_set_enabled(obs_properties_get(props, AMF_H264_QP_MAXIMUM), false);
438
- /*obs_data_set_int(data, AMF_H264_QP_IFRAME, 0);
439
- obs_data_set_int(data, AMF_H264_QP_PFRAME, 0);
440
- obs_data_set_int(data, AMF_H264_QP_BFRAME, 0);*/
441
obs_data_set_int(data, AMF_H264_BFRAME_DELTAQP, 0);
442
obs_property_set_enabled(obs_properties_get(props, AMF_H264_BFRAME_DELTAQP), false);
443
obs_data_set_int(data, AMF_H264_BFRAME_REFERENCEDELTAQP, 0);
444
obs_property_set_enabled(obs_properties_get(props, AMF_H264_BFRAME_REFERENCEDELTAQP), false);
445
- //obs_data_set_int(data, AMF_H264_VBVBUFFER, 0);
446
- //obs_property_set_enabled(obs_properties_get(props, AMF_H264_VBVBUFFER), false);
447
- //obs_data_set_double(data, AMF_H264_VBVBUFFER_STRICTNESS, 0);
448
- //obs_property_set_enabled(obs_properties_get(props, AMF_H264_VBVBUFFER_STRICTNESS), false);
449
- //obs_data_set_double(data, AMF_H264_VBVBUFFER_FULLNESS, 0);
450
- //obs_property_set_enabled(obs_properties_get(props, AMF_H264_VBVBUFFER_FULLNESS), false);
451
- //obs_data_set_int(data, AMF_H264_MAXIMUMACCESSUNITSIZE, 0);
452
obs_data_set_int(data, AMF_H264_FILLERDATA, 0);
453
obs_property_set_enabled(obs_properties_get(props, AMF_H264_FILLERDATA), false);
454
- //obs_data_set_int(data, AMF_H264_FRAMESKIPPING, 0);
455
- //obs_data_set_int(data, AMF_H264_ENFORCEHRDCOMPATIBILITY, 0);
456
457
// Frame Control Properties
458
obs_data_set_double(data, AMF_H264_KEYFRAME_INTERVAL, 1);
459
obs_property_set_enabled(obs_properties_get(props, AMF_H264_KEYFRAME_INTERVAL), false);
460
- //obs_data_set_int(data, AMF_H264_IDR_PERIOD, 60);
461
- //obs_data_set_int(data, AMF_H264_HEADER_INSERTION_SPACING, 0);
462
- //obs_data_set_int(data, AMF_H264_BFrame_PATTERN, obs_data_get_default_int(data, AMF_H264_BFrame_PATTERN));
463
- //obs_data_set_int(data, AMF_H264_BFrame_REFERENCE, obs_data_get_default_int(data, AMF_H264_BFrame_REFERENCE));
464
- //obs_data_set_int(data, AMF_H264_SLICESPERFRAME, 0);
465
- //obs_data_set_int(data, AMF_H264_INTRAREFRESHNUMMBSPERSLOT, 0);
466
467
// Miscellaneous Properties
468
- //obs_data_set_int(data, AMF_H264_QUALITY_PRESET, VCEQualityPreset_Quality);
469
- obs_data_set_int(data, AMF_H264_SCANTYPE, VCEScanType_Progressive);
470
+ obs_data_set_int(data, AMF_H264_SCANTYPE, static_cast<int32_t>(H264ScanType::Progressive));
471
obs_property_set_enabled(obs_properties_get(props, AMF_H264_SCANTYPE), false);
472
obs_data_set_int(data, AMF_H264_MOTIONESTIMATION, 3);
473
obs_property_set_enabled(obs_properties_get(props, AMF_H264_MOTIONESTIMATION), false);
474
- //obs_data_set_int(data, AMF_H264_CABAC, 0);
475
break;
476
#pragma endregion Recording
477
- case HighQuality:
478
+ case Presets::HighQuality:
479
#pragma region High Quality
480
// Static Properties
481
- //obs_data_set_int(data, AMF_H264_USAGE, VCEUsage_Transcoding);
482
- obs_data_set_int(data, AMF_H264_PROFILE, VCEProfile_High);
483
+ obs_data_set_int(data, AMF_H264_PROFILE, static_cast<int32_t>(H264Profile::High));
484
obs_property_set_enabled(obs_properties_get(props, AMF_H264_PROFILE), false);
485
- obs_data_set_int(data, AMF_H264_PROFILELEVEL, VCEProfileLevel_Automatic);
486
+ obs_data_set_int(data, AMF_H264_PROFILELEVEL, static_cast<int32_t>(H264ProfileLevel::Automatic));
487
obs_property_set_enabled(obs_properties_get(props, AMF_H264_PROFILELEVEL), false);
488
- //obs_data_set_int(data, AMF_H264_MAXIMUMLTRFRAMES, obs_data_get_default_int(data, AMF_H264_MAXIMUMLTRFRAMES));
489
490
// Rate Control Properties
491
- obs_data_set_int(data, AMF_H264_RATECONTROLMETHOD, VCERateControlMethod_ConstantQP);
492
+ obs_data_set_int(data, AMF_H264_RATECONTROLMETHOD, static_cast<int32_t>(H264RateControlMethod::ConstantQP));
493
obs_property_set_enabled(obs_properties_get(props, AMF_H264_RATECONTROLMETHOD), false);
494
- //obs_data_set_int(data, AMF_H264_BITRATE_TARGET, 35000 * (obs_data_get_bool(data, AMF_H264_UNLOCK_PROPERTIES) ? 1000 : 1));
495
- //obs_data_set_int(data, AMF_H264_BITRATE_PEAK, VCECapabilities::GetInstance()->GetEncoderCaps(VCEEncoderType_AVC)->maxBitrate / (obs_data_get_bool(data, AMF_H264_UNLOCK_PROPERTIES) ? 1 : 1000));
496
- /*obs_data_set_int(data, AMF_H264_QP_MINIMUM, 0);
497
- obs_data_set_int(data, AMF_H264_QP_MAXIMUM, 51);*/
498
obs_data_set_int(data, AMF_H264_QP_IFRAME, 26);
499
obs_property_set_enabled(obs_properties_get(props, AMF_H264_QP_IFRAME), false);
500
obs_data_set_int(data, AMF_H264_QP_PFRAME, 24);
501
502
obs_property_set_enabled(obs_properties_get(props, AMF_H264_BFRAME_DELTAQP), false);
503
obs_data_set_int(data, AMF_H264_BFRAME_REFERENCEDELTAQP, -2);
504
obs_property_set_enabled(obs_properties_get(props, AMF_H264_BFRAME_REFERENCEDELTAQP), false);
505
- //obs_data_set_int(data, AMF_H264_VBVBUFFER, 0);
506
- //obs_property_set_enabled(obs_properties_get(props, AMF_H264_VBVBUFFER), false);
507
- //obs_data_set_double(data, AMF_H264_VBVBUFFER_STRICTNESS, 0);
508
- //obs_property_set_enabled(obs_properties_get(props, AMF_H264_VBVBUFFER_STRICTNESS), false);
509
- //obs_data_set_double(data, AMF_H264_VBVBUFFER_FULLNESS, 0);
510
- //obs_property_set_enabled(obs_properties_get(props, AMF_H264_VBVBUFFER_FULLNESS), false);
511
- //obs_data_set_int(data, AMF_H264_MAXIMUMACCESSUNITSIZE, 0);
512
- //obs_data_set_int(data, AMF_H264_FILLERDATA, 0);
513
- //obs_data_set_int(data, AMF_H264_FRAMESKIPPING, 0);
514
- //obs_data_set_int(data, AMF_H264_ENFORCEHRDCOMPATIBILITY, 0);
515
516
// Frame Control Properties
517
obs_data_set_double(data, AMF_H264_KEYFRAME_INTERVAL, 1);
518
obs_property_set_enabled(obs_properties_get(props, AMF_H264_KEYFRAME_INTERVAL), false);
519
- //obs_data_set_int(data, AMF_H264_IDR_PERIOD, 60);
520
- //obs_data_set_int(data, AMF_H264_HEADER_INSERTION_SPACING, 0);
521
- //obs_data_set_int(data, AMF_H264_BFrame_PATTERN, obs_data_get_default_int(data, AMF_H264_BFrame_PATTERN));
522
- //obs_data_set_int(data, AMF_H264_BFrame_REFERENCE, obs_data_get_default_int(data, AMF_H264_BFrame_REFERENCE));
523
- //obs_data_set_int(data, AMF_H264_SLICESPERFRAME, 0);
524
- //obs_data_set_int(data, AMF_H264_INTRAREFRESHNUMMBSPERSLOT, 0);
525
526
// Miscellaneous Properties
527
- //obs_data_set_int(data, AMF_H264_QUALITY_PRESET, VCEQualityPreset_Quality);
528
- obs_data_set_int(data, AMF_H264_SCANTYPE, VCEScanType_Progressive);
529
+ obs_data_set_int(data, AMF_H264_SCANTYPE, static_cast<int32_t>(H264ScanType::Progressive));
530
obs_property_set_enabled(obs_properties_get(props, AMF_H264_SCANTYPE), false);
531
obs_data_set_int(data, AMF_H264_MOTIONESTIMATION, 3);
532
obs_property_set_enabled(obs_properties_get(props, AMF_H264_MOTIONESTIMATION), false);
533
- //obs_data_set_int(data, AMF_H264_CABAC, 0);
534
break;
535
#pragma endregion High Quality
536
- case Indistinguishable:
537
+ case Presets::Indistinguishable:
538
#pragma region Indistinguishable
539
// Static Properties
540
- //obs_data_set_int(data, AMF_H264_USAGE, VCEUsage_Transcoding);
541
- obs_data_set_int(data, AMF_H264_PROFILE, VCEProfile_High);
542
+ obs_data_set_int(data, AMF_H264_PROFILE, static_cast<int32_t>(H264Profile::High));
543
obs_property_set_enabled(obs_properties_get(props, AMF_H264_PROFILE), false);
544
- obs_data_set_int(data, AMF_H264_PROFILELEVEL, VCEProfileLevel_Automatic);
545
+ obs_data_set_int(data, AMF_H264_PROFILELEVEL, static_cast<int32_t>(H264ProfileLevel::Automatic));
546
obs_property_set_enabled(obs_properties_get(props, AMF_H264_PROFILELEVEL), false);
547
- //obs_data_set_int(data, AMF_H264_MAXIMUMLTRFRAMES, obs_data_get_default_int(data, AMF_H264_MAXIMUMLTRFRAMES));
548
549
// Rate Control Properties
550
- obs_data_set_int(data, AMF_H264_RATECONTROLMETHOD, VCERateControlMethod_ConstantQP);
551
+ obs_data_set_int(data, AMF_H264_RATECONTROLMETHOD, static_cast<int32_t>(H264RateControlMethod::ConstantQP));
552
obs_property_set_enabled(obs_properties_get(props, AMF_H264_RATECONTROLMETHOD), false);
553
- //obs_data_set_int(data, AMF_H264_BITRATE_TARGET, 35000 * (obs_data_get_bool(data, AMF_H264_UNLOCK_PROPERTIES) ? 1000 : 1));
554
- //obs_data_set_int(data, AMF_H264_BITRATE_PEAK, VCECapabilities::GetInstance()->GetEncoderCaps(VCEEncoderType_AVC)->maxBitrate / (obs_data_get_bool(data, AMF_H264_UNLOCK_PROPERTIES) ? 1 : 1000));
555
- /*obs_data_set_int(data, AMF_H264_QP_MINIMUM, 0);
556
- obs_data_set_int(data, AMF_H264_QP_MAXIMUM, 51);*/
557
obs_data_set_int(data, AMF_H264_QP_IFRAME, 21);
558
obs_property_set_enabled(obs_properties_get(props, AMF_H264_QP_IFRAME), false);
559
obs_data_set_int(data, AMF_H264_QP_PFRAME, 19);
560
561
obs_property_set_enabled(obs_properties_get(props, AMF_H264_BFRAME_DELTAQP), false);
562
obs_data_set_int(data, AMF_H264_BFRAME_REFERENCEDELTAQP, -2);
563
obs_property_set_enabled(obs_properties_get(props, AMF_H264_BFRAME_REFERENCEDELTAQP), false);
564
- //obs_data_set_int(data, AMF_H264_VBVBUFFER, 0);
565
- //obs_property_set_enabled(obs_properties_get(props, AMF_H264_VBVBUFFER), false);
566
- //obs_data_set_double(data, AMF_H264_VBVBUFFER_STRICTNESS, 0);
567
- //obs_property_set_enabled(obs_properties_get(props, AMF_H264_VBVBUFFER_STRICTNESS), false);
568
- //obs_data_set_double(data, AMF_H264_VBVBUFFER_FULLNESS, 0);
569
- //obs_property_set_enabled(obs_properties_get(props, AMF_H264_VBVBUFFER_FULLNESS), false);
570
- //obs_data_set_int(data, AMF_H264_MAXIMUMACCESSUNITSIZE, 0);
571
- //obs_data_set_int(data, AMF_H264_FILLERDATA, 0);
572
- //obs_data_set_int(data, AMF_H264_FRAMESKIPPING, 0);
573
- //obs_data_set_int(data, AMF_H264_ENFORCEHRDCOMPATIBILITY, 0);
574
575
// Frame Control Properties
576
obs_data_set_double(data, AMF_H264_KEYFRAME_INTERVAL, 1);
577
obs_property_set_enabled(obs_properties_get(props, AMF_H264_KEYFRAME_INTERVAL), false);
578
- //obs_data_set_int(data, AMF_H264_IDR_PERIOD, 60);
579
- //obs_data_set_int(data, AMF_H264_HEADER_INSERTION_SPACING, 0);
580
- //obs_data_set_int(data, AMF_H264_BFRAME_PATTERN, obs_data_get_default_int(data, AMF_H264_BFRAME_PATTERN));
581
- //obs_data_set_int(data, AMF_H264_BFRAME_REFERENCE, obs_data_get_default_int(data, AMF_H264_BFRAME_REFERENCE));
582
- //obs_data_set_int(data, AMF_H264_SLICESPERFRAME, 0);
583
- //obs_data_set_int(data, AMF_H264_INTRAREFRESHNUMMBSPERSLOT, 0);
584
585
// Miscellaneous Properties
586
- //obs_data_set_int(data, AMF_H264_QUALITY_PRESET, VCEQualityPreset_Quality);
587
- obs_data_set_int(data, AMF_H264_SCANTYPE, VCEScanType_Progressive);
588
+ obs_data_set_int(data, AMF_H264_SCANTYPE, static_cast<int32_t>(H264ScanType::Progressive));
589
obs_property_set_enabled(obs_properties_get(props, AMF_H264_SCANTYPE), false);
590
obs_data_set_int(data, AMF_H264_MOTIONESTIMATION, 3);
591
obs_property_set_enabled(obs_properties_get(props, AMF_H264_MOTIONESTIMATION), false);
592
- //obs_data_set_int(data, AMF_H264_CABAC, 0);
593
break;
594
#pragma endregion Indistinguishable
595
- case Lossless:
596
+ case Presets::Lossless:
597
#pragma region Lossless
598
// Static Properties
599
- //obs_data_set_int(data, AMF_H264_USAGE, VCEUsage_Transcoding);
600
- obs_data_set_int(data, AMF_H264_PROFILE, VCEProfile_High);
601
+ obs_data_set_int(data, AMF_H264_PROFILE, static_cast<int32_t>(H264Profile::High));
602
obs_property_set_enabled(obs_properties_get(props, AMF_H264_PROFILE), false);
603
- obs_data_set_int(data, AMF_H264_PROFILELEVEL, VCEProfileLevel_Automatic);
604
+ obs_data_set_int(data, AMF_H264_PROFILELEVEL, static_cast<int32_t>(H264ProfileLevel::Automatic));
605
obs_property_set_enabled(obs_properties_get(props, AMF_H264_PROFILELEVEL), false);
606
- //obs_data_set_int(data, AMF_H264_MAXIMUMLTRFRAMES, 0);
607
608
// Rate Control Properties
609
- obs_data_set_int(data, AMF_H264_RATECONTROLMETHOD, VCERateControlMethod_ConstantQP);
610
+ obs_data_set_int(data, AMF_H264_RATECONTROLMETHOD, static_cast<int32_t>(H264RateControlMethod::ConstantQP));
611
obs_property_set_enabled(obs_properties_get(props, AMF_H264_RATECONTROLMETHOD), false);
612
- //obs_data_set_int(data, AMF_H264_BITRATE_TARGET, 35000 * (obs_data_get_bool(data, AMF_H264_UNLOCK_PROPERTIES) ? 1000 : 1));
613
- //obs_data_set_int(data, AMF_H264_BITRATE_PEAK, VCECapabilities::GetInstance()->GetEncoderCaps(VCEEncoderType_AVC)->maxBitrate / (obs_data_get_bool(data, AMF_H264_UNLOCK_PROPERTIES) ? 1 : 1000));
614
- /*obs_data_set_int(data, AMF_H264_QP_MINIMUM, 0);
615
- obs_data_set_int(data, AMF_H264_QP_MAXIMUM, 51);*/
616
obs_data_set_int(data, AMF_H264_QP_IFRAME, 0);
617
obs_property_set_enabled(obs_properties_get(props, AMF_H264_QP_IFRAME), false);
618
obs_data_set_int(data, AMF_H264_QP_PFRAME, 0);
619
620
obs_property_set_enabled(obs_properties_get(props, AMF_H264_BFRAME_DELTAQP), false);
621
obs_data_set_int(data, AMF_H264_BFRAME_REFERENCEDELTAQP, 0);
622
obs_property_set_enabled(obs_properties_get(props, AMF_H264_BFRAME_REFERENCEDELTAQP), false);
623
- //obs_data_set_int(data, AMF_H264_VBVBUFFER, 0);
624
- //obs_property_set_enabled(obs_properties_get(props, AMF_H264_VBVBUFFER), false);
625
- //obs_data_set_double(data, AMF_H264_VBVBUFFER_STRICTNESS, 0);
626
- //obs_property_set_enabled(obs_properties_get(props, AMF_H264_VBVBUFFER_STRICTNESS), false);
627
- //obs_data_set_double(data, AMF_H264_VBVBUFFER_FULLNESS, 0);
628
- //obs_property_set_enabled(obs_properties_get(props, AMF_H264_VBVBUFFER_FULLNESS), false);
629
- //obs_data_set_int(data, AMF_H264_MAXIMUMACCESSUNITSIZE, 0);
630
- //obs_data_set_int(data, AMF_H264_FILLERDATA, 0);
631
- //obs_data_set_int(data, AMF_H264_FRAMESKIPPING, 0);
632
- //obs_data_set_int(data, AMF_H264_ENFORCEHRDCOMPATIBILITY, 0);
633
634
// Frame Control Properties
635
obs_data_set_double(data, AMF_H264_KEYFRAME_INTERVAL, 1);
636
obs_property_set_enabled(obs_properties_get(props, AMF_H264_KEYFRAME_INTERVAL), false);
637
- obs_data_set_int(data, AMF_H264_IDR_PERIOD, 30);
638
- obs_property_set_enabled(obs_properties_get(props, AMF_H264_IDR_PERIOD), false);
639
- //obs_data_set_int(data, AMF_H264_HEADER_INSERTION_SPACING, 0);
640
obs_data_set_int(data, AMF_H264_BFRAME_PATTERN, 0);
641
obs_property_set_enabled(obs_properties_get(props, AMF_H264_BFRAME_PATTERN), false);
642
obs_data_set_int(data, AMF_H264_BFRAME_REFERENCE, 0);
643
obs_property_set_enabled(obs_properties_get(props, AMF_H264_BFRAME_REFERENCE), false);
644
- //obs_data_set_int(data, AMF_H264_SLICESPERFRAME, 0);
645
- //obs_data_set_int(data, AMF_H264_INTRAREFRESHNUMMBSPERSLOT, 0);
646
647
// Miscellaneous Properties
648
- //obs_data_set_int(data, AMF_H264_QUALITY_PRESET, VCEQualityPreset_Quality);
649
- obs_data_set_int(data, AMF_H264_SCANTYPE, VCEScanType_Progressive);
650
+ obs_data_set_int(data, AMF_H264_SCANTYPE, static_cast<int32_t>(H264ScanType::Progressive));
651
obs_property_set_enabled(obs_properties_get(props, AMF_H264_SCANTYPE), false);
652
obs_data_set_int(data, AMF_H264_MOTIONESTIMATION, 3);
653
obs_property_set_enabled(obs_properties_get(props, AMF_H264_MOTIONESTIMATION), false);
654
- //obs_data_set_int(data, AMF_H264_CABAC, 0);
655
break;
656
#pragma endregion Lossless
657
- case Twitch:
658
+ case Presets::Twitch:
659
#pragma region Twitch
660
// Static Properties
661
- obs_data_set_int(data, AMF_H264_USAGE, VCEUsage_Transcoding);
662
+ obs_data_set_int(data, AMF_H264_USAGE, static_cast<int32_t>(H264Usage::Transcoding));
663
obs_property_set_enabled(obs_properties_get(props, AMF_H264_USAGE), false);
664
- obs_data_set_int(data, AMF_H264_PROFILE, VCEProfile_Main);
665
+ obs_data_set_int(data, AMF_H264_PROFILE, static_cast<int32_t>(H264Profile::Main));
666
obs_property_set_enabled(obs_properties_get(props, AMF_H264_PROFILE), false);
667
- obs_data_set_int(data, AMF_H264_PROFILELEVEL, VCEProfileLevel_Automatic);
668
+ obs_data_set_int(data, AMF_H264_PROFILELEVEL, static_cast<int32_t>(H264ProfileLevel::Automatic));
669
obs_property_set_enabled(obs_properties_get(props, AMF_H264_PROFILELEVEL), false);
670
- //obs_data_set_int(data, AMF_H264_MAXIMUMLTRFRAMES, obs_data_get);
671
672
// Rate Control Properties
673
- obs_data_set_int(data, AMF_H264_RATECONTROLMETHOD, VCERateControlMethod_ConstantBitrate);
674
+ obs_data_set_int(data, AMF_H264_RATECONTROLMETHOD, static_cast<int32_t>(H264RateControlMethod::ConstantBitrate));
675
obs_property_set_enabled(obs_properties_get(props, AMF_H264_RATECONTROLMETHOD), false);
676
- if (obs_data_get_int(data, AMF_H264_BITRATE_TARGET) < 1000)
677
- obs_data_set_int(data, AMF_H264_BITRATE_TARGET, 1000);
678
- if (obs_data_get_int(data, AMF_H264_BITRATE_TARGET) > 4000)
679
- obs_data_set_int(data, AMF_H264_BITRATE_TARGET, 4000);
680
- obs_property_int_set_limits(obs_properties_get(props, AMF_H264_BITRATE_TARGET), 1000, 4000, 1);
681
- //obs_data_set_int(data, AMF_H264_BITRATE_PEAK, VCECapabilities::GetInstance()->GetEncoderCaps(VCEEncoderType_AVC)->maxBitrate / (obs_data_get_bool(data, AMF_H264_UNLOCK_PROPERTIES) ? 1 : 1000));
682
- obs_data_set_int(data, AMF_H264_QP_MINIMUM, 0);
683
+ if (obs_data_get_int(data, AMF_H264_BITRATE_TARGET) < 500)
684
+ obs_data_set_int(data, AMF_H264_BITRATE_TARGET, 500);
685
+ obs_property_int_set_limits(obs_properties_get(props, AMF_H264_BITRATE_TARGET), 500, 100000, 1);
686
+ obs_data_default_single(props, data, AMF_H264_QP_MINIMUM);
687
obs_property_set_enabled(obs_properties_get(props, AMF_H264_QP_MINIMUM), false);
688
- obs_data_set_int(data, AMF_H264_QP_MAXIMUM, 51);
689
+ obs_data_default_single(props, data, AMF_H264_QP_MAXIMUM);
690
obs_property_set_enabled(obs_properties_get(props, AMF_H264_QP_MAXIMUM), false);
691
- /*obs_data_set_int(data, AMF_H264_QP_IFRAME, 0);
692
- obs_data_set_int(data, AMF_H264_QP_PFRAME, 0);
693
- obs_data_set_int(data, AMF_H264_QP_BFRAME, 0);*/
694
- obs_data_set_int(data, AMF_H264_BFRAME_DELTAQP, 0);
695
- obs_property_set_enabled(obs_properties_get(props, AMF_H264_BFRAME_DELTAQP), false);
696
- obs_data_set_int(data, AMF_H264_BFRAME_REFERENCEDELTAQP, 0);
697
- obs_property_set_enabled(obs_properties_get(props, AMF_H264_BFRAME_REFERENCEDELTAQP), false);
698
- //obs_data_set_int(data, AMF_H264_VBVBUFFER, 0);
699
- //obs_property_set_enabled(obs_properties_get(props, AMF_H264_VBVBUFFER), false);
700
- //obs_data_set_double(data, AMF_H264_VBVBUFFER_STRICTNESS, 80);
701
- //obs_property_set_enabled(obs_properties_get(props, AMF_H264_VBVBUFFER_STRICTNESS), false);
702
- //obs_data_set_double(data, AMF_H264_VBVBUFFER_FULLNESS, 100);
703
- //obs_property_set_enabled(obs_properties_get(props, AMF_H264_VBVBUFFER_FULLNESS), false);
704
- //obs_data_set_int(data, AMF_H264_MAXIMUMACCESSUNITSIZE, 0);
705
obs_data_set_int(data, AMF_H264_FILLERDATA, 1);
706
obs_property_set_enabled(obs_properties_get(props, AMF_H264_FILLERDATA), false);
707
- //obs_data_set_int(data, AMF_H264_FRAMESKIPPING, 0);
708
- //obs_data_set_int(data, AMF_H264_ENFORCEHRDCOMPATIBILITY, 0);
709
710
// Frame Control Properties
711
obs_data_set_double(data, AMF_H264_KEYFRAME_INTERVAL, 2);
712
obs_property_set_enabled(obs_properties_get(props, AMF_H264_KEYFRAME_INTERVAL), false);
713
- //obs_data_set_int(data, AMF_H264_IDR_PERIOD, 120);
714
- //obs_data_set_int(data, AMF_H264_HEADER_INSERTION_SPACING, 0);
715
- //obs_data_set_int(data, AMF_H264_BFRAME_PATTERN, 0);
716
- //obs_data_set_int(data, AMF_H264_BFRAME_REFERENCE, 0);
717
- //obs_data_set_int(data, AMF_H264_SLICESPERFRAME, 0);
718
- //obs_data_set_int(data, AMF_H264_INTRAREFRESHNUMMBSPERSLOT, 0);
719
720
// Miscellaneous Properties
721
- //obs_data_set_int(data, AMF_H264_QUALITY_PRESET, VCEQualityPreset_Quality);
722
- obs_data_set_int(data, AMF_H264_SCANTYPE, VCEScanType_Progressive);
723
+ obs_data_set_int(data, AMF_H264_SCANTYPE, static_cast<int32_t>(H264ScanType::Progressive));
724
obs_property_set_enabled(obs_properties_get(props, AMF_H264_SCANTYPE), false);
725
obs_data_set_int(data, AMF_H264_MOTIONESTIMATION, 3);
726
obs_property_set_enabled(obs_properties_get(props, AMF_H264_MOTIONESTIMATION), false);
727
- //obs_data_set_int(data, AMF_H264_CABAC, 0);
728
break;
729
#pragma endregion Twitch
730
- case YouTube:
731
+ case Presets::YouTube:
732
#pragma region YouTube
733
// Static Properties
734
- obs_data_set_int(data, AMF_H264_USAGE, VCEUsage_Transcoding);
735
+ obs_data_set_int(data, AMF_H264_USAGE, static_cast<int32_t>(H264Usage::Transcoding));
736
obs_property_set_enabled(obs_properties_get(props, AMF_H264_USAGE), false);
737
- obs_data_set_int(data, AMF_H264_PROFILE, VCEProfile_Main);
738
+ obs_data_set_int(data, AMF_H264_PROFILE, static_cast<int32_t>(H264Profile::Main));
739
obs_property_set_enabled(obs_properties_get(props, AMF_H264_PROFILE), false);
740
- obs_data_set_int(data, AMF_H264_PROFILELEVEL, VCEProfileLevel_Automatic);
741
+ obs_data_set_int(data, AMF_H264_PROFILELEVEL, static_cast<int32_t>(H264ProfileLevel::Automatic));
742
obs_property_set_enabled(obs_properties_get(props, AMF_H264_PROFILELEVEL), false);
743
- //obs_data_set_int(data, AMF_H264_MAXIMUMLTRFRAMES, obs_data_get);
744
745
// Rate Control Properties
746
- obs_data_set_int(data, AMF_H264_RATECONTROLMETHOD, VCERateControlMethod_ConstantBitrate);
747
+ obs_data_set_int(data, AMF_H264_RATECONTROLMETHOD, static_cast<int32_t>(H264RateControlMethod::ConstantBitrate));
748
obs_property_set_enabled(obs_properties_get(props, AMF_H264_RATECONTROLMETHOD), false);
749
- if (obs_data_get_int(data, AMF_H264_BITRATE_TARGET) < 1000)
750
- obs_data_set_int(data, AMF_H264_BITRATE_TARGET, 1000);
751
- if (obs_data_get_int(data, AMF_H264_BITRATE_PEAK) > 25000)
752
- obs_data_set_int(data, AMF_H264_BITRATE_PEAK, 25000);
753
- obs_property_int_set_limits(obs_properties_get(props, AMF_H264_BITRATE_TARGET), 1000, 25000, 1);
754
- obs_data_set_int(data, AMF_H264_QP_MINIMUM, 0);
755
+ if (obs_data_get_int(data, AMF_H264_BITRATE_TARGET) < 500)
756
+ obs_data_set_int(data, AMF_H264_BITRATE_TARGET, 500);
757
+ obs_property_int_set_limits(obs_properties_get(props, AMF_H264_BITRATE_TARGET), 500, 100000, 1);
758
+ obs_data_default_single(props, data, AMF_H264_QP_MINIMUM);
759
obs_property_set_enabled(obs_properties_get(props, AMF_H264_QP_MINIMUM), false);
760
- obs_data_set_int(data, AMF_H264_QP_MAXIMUM, 51);
761
+ obs_data_default_single(props, data, AMF_H264_QP_MAXIMUM);
762
obs_property_set_enabled(obs_properties_get(props, AMF_H264_QP_MAXIMUM), false);
763
- /*obs_data_set_int(data, AMF_H264_QP_IFRAME, 0);
764
- obs_data_set_int(data, AMF_H264_QP_PFRAME, 0);
765
- obs_data_set_int(data, AMF_H264_QP_BFRAME, 0);*/
766
- obs_data_set_int(data, AMF_H264_BFRAME_DELTAQP, 0);
767
- obs_property_set_enabled(obs_properties_get(props, AMF_H264_BFRAME_DELTAQP), false);
768
- obs_data_set_int(data, AMF_H264_BFRAME_REFERENCEDELTAQP, 0);
769
- obs_property_set_enabled(obs_properties_get(props, AMF_H264_BFRAME_REFERENCEDELTAQP), false);
770
- //obs_data_set_int(data, AMF_H264_VBVBUFFER, 0);
771
- //obs_property_set_enabled(obs_properties_get(props, AMF_H264_VBVBUFFER), false);
772
- //obs_data_set_double(data, AMF_H264_VBVBUFFER_STRICTNESS, 80);
773
- //obs_property_set_enabled(obs_properties_get(props, AMF_H264_VBVBUFFER_STRICTNESS), false);
774
- //obs_data_set_double(data, AMF_H264_VBVBUFFER_FULLNESS, 100);
775
- //obs_property_set_enabled(obs_properties_get(props, AMF_H264_VBVBUFFER_FULLNESS), false);
776
- //obs_data_set_int(data, AMF_H264_MAXIMUMACCESSUNITSIZE, 0);
777
obs_data_set_int(data, AMF_H264_FILLERDATA, 1);
778
obs_property_set_enabled(obs_properties_get(props, AMF_H264_FILLERDATA), false);
779
- //obs_data_set_int(data, AMF_H264_FRAMESKIPPING, 0);
780
- //obs_data_set_int(data, AMF_H264_ENFORCEHRDCOMPATIBILITY, 0);
781
782
// Frame Control Properties
783
obs_data_set_double(data, AMF_H264_KEYFRAME_INTERVAL, 2);
784
obs_property_set_enabled(obs_properties_get(props, AMF_H264_KEYFRAME_INTERVAL), false);
785
- //obs_data_set_int(data, AMF_H264_IDR_PERIOD, 120);
786
- //obs_data_set_int(data, AMF_H264_HEADER_INSERTION_SPACING, 0);
787
- //obs_data_set_int(data, AMF_H264_BFRAME_PATTERN, 0);
788
- //obs_data_set_int(data, AMF_H264_BFRAME_REFERENCE, 0);
789
- //obs_data_set_int(data, AMF_H264_SLICESPERFRAME, 0);
790
- //obs_data_set_int(data, AMF_H264_INTRAREFRESHNUMMBSPERSLOT, 0);
791
792
// Miscellaneous Properties
793
- //obs_data_set_int(data, AMF_H264_QUALITY_PRESET, VCEQualityPreset_Quality);
794
- obs_data_set_int(data, AMF_H264_SCANTYPE, VCEScanType_Progressive);
795
+ obs_data_set_int(data, AMF_H264_SCANTYPE, static_cast<int32_t>(H264ScanType::Progressive));
796
obs_property_set_enabled(obs_properties_get(props, AMF_H264_SCANTYPE), false);
797
obs_data_set_int(data, AMF_H264_MOTIONESTIMATION, 3);
798
obs_property_set_enabled(obs_properties_get(props, AMF_H264_MOTIONESTIMATION), false);
799
- //obs_data_set_int(data, AMF_H264_CABAC, 0);
800
break;
801
#pragma endregion YouTube
802
}
803
804
//fill_api_list(p);
805
806
obs_data_set_string(data, AMF_H264_VIDEOAPI,
807
- obs_property_list_item_string(p, 0));
808
+ obs_property_list_item_string(p, 0));
809
curVideoAPI = obs_data_get_string(data, AMF_H264_VIDEOAPI);
810
}
811
if ((strcmp(lastVideoAPI, curVideoAPI) != 0)
812
813
814
// Reset Video Adapter to first in list.
815
obs_data_set_int(data, AMF_H264_VIDEOADAPTER,
816
- obs_property_list_item_int(obs_properties_get(props, AMF_H264_VIDEOADAPTER), 0));
817
+ obs_property_list_item_int(obs_properties_get(props, AMF_H264_VIDEOADAPTER), 0));
818
}
819
#pragma endregion Video API
820
821
822
{
823
auto api = Plugin::API::Base::GetAPIByName(obs_data_get_string(data, AMF_H264_VIDEOAPI));
824
auto adapter = api->GetAdapterById(curAdapterId & UINT_MAX, (curAdapterId >> 32) & UINT_MAX);
825
- devCaps = Plugin::AMD::VCECapabilities::GetInstance()->GetAdapterCapabilities(api, adapter, VCEEncoderType_AVC);
826
+ devCaps = Plugin::AMD::VCECapabilities::GetInstance()->GetAdapterCapabilities(api, adapter, H264EncoderType::AVC);
827
}
828
if (lastAdapterId != curAdapterId) {
829
obs_data_set_int(data, "last" vstr(AMF_H264_VIDEOADAPTER), curAdapterId);
830
831
obs_property_list_clear(p);
832
switch (devCaps.maxProfile) {
833
case 100:
834
- obs_property_list_add_int(p, "High", VCEProfile_High);
835
- obs_property_list_add_int(p, "Constrained High", VCEProfile_ConstrainedHigh);
836
+ obs_property_list_add_int(p, "High", (int32_t)H264Profile::High);
837
+ obs_property_list_add_int(p, "Constrained High", (int32_t)H264Profile::ConstrainedHigh);
838
case 77:
839
- obs_property_list_add_int(p, "Main", VCEProfile_Main);
840
+ obs_property_list_add_int(p, "Main", (int32_t)H264Profile::Main);
841
case 66:
842
- obs_property_list_add_int(p, "Baseline", VCEProfile_Baseline);
843
- obs_property_list_add_int(p, "Constrained Baseline", VCEProfile_ConstrainedBaseline);
844
+ obs_property_list_add_int(p, "Baseline", (int32_t)H264Profile::Baseline);
845
+ obs_property_list_add_int(p, "Constrained Baseline", (int32_t)H264Profile::ConstrainedBaseline);
846
break;
847
}
848
#pragma endregion Profile
849
850
#pragma region Profile Level
851
p = obs_properties_get(props, AMF_H264_PROFILELEVEL);
852
obs_property_list_clear(p);
853
- obs_property_list_add_int(p, TEXT_T(AMF_UTIL_AUTOMATIC), VCEProfileLevel_Automatic);
854
+ obs_property_list_add_int(p, TEXT_T(AMF_UTIL_AUTOMATIC), (int32_t)H264ProfileLevel::Automatic);
855
switch (devCaps.maxProfileLevel) {
856
- case 62:
857
- obs_property_list_add_int(p, "6.2", VCEProfileLevel_62);
858
- case 61:
859
- obs_property_list_add_int(p, "6.1", VCEProfileLevel_61);
860
- case 60:
861
- obs_property_list_add_int(p, "6.0", VCEProfileLevel_60);
862
case 52:
863
- obs_property_list_add_int(p, "5.2", VCEProfileLevel_52);
864
+ obs_property_list_add_int(p, "5.2", (int32_t)H264ProfileLevel::L52);
865
case 51:
866
- obs_property_list_add_int(p, "5.1", VCEProfileLevel_51);
867
+ obs_property_list_add_int(p, "5.1", (int32_t)H264ProfileLevel::L51);
868
case 50:
869
- obs_property_list_add_int(p, "5.0", VCEProfileLevel_50);
870
+ obs_property_list_add_int(p, "5.0", (int32_t)H264ProfileLevel::L50);
871
case 42: // Some VCE 2.0 Cards.
872
- obs_property_list_add_int(p, "4.2", VCEProfileLevel_42);
873
+ obs_property_list_add_int(p, "4.2", (int32_t)H264ProfileLevel::L42);
874
case 41: // Some APUs and VCE 1.0 Cards.
875
- obs_property_list_add_int(p, "4.1", VCEProfileLevel_41);
876
+ obs_property_list_add_int(p, "4.1", (int32_t)H264ProfileLevel::L41);
877
case 40: // These should in theory be supported by all VCE 1.0 devices and APUs.
878
- obs_property_list_add_int(p, "4.0", VCEProfileLevel_40);
879
+ obs_property_list_add_int(p, "4.0", (int32_t)H264ProfileLevel::L40);
880
case 32:
881
- obs_property_list_add_int(p, "3.2", VCEProfileLevel_32);
882
+ obs_property_list_add_int(p, "3.2", (int32_t)H264ProfileLevel::L32);
883
case 31:
884
- obs_property_list_add_int(p, "3.1", VCEProfileLevel_31);
885
+ obs_property_list_add_int(p, "3.1", (int32_t)H264ProfileLevel::L31);
886
case 30:
887
- obs_property_list_add_int(p, "3.0", VCEProfileLevel_30);
888
+ obs_property_list_add_int(p, "3.0", (int32_t)H264ProfileLevel::L30);
889
case 22:
890
- obs_property_list_add_int(p, "2.2", VCEProfileLevel_22);
891
+ obs_property_list_add_int(p, "2.2", (int32_t)H264ProfileLevel::L22);
892
case 21:
893
- obs_property_list_add_int(p, "2.1", VCEProfileLevel_21);
894
+ obs_property_list_add_int(p, "2.1", (int32_t)H264ProfileLevel::L21);
895
case 20:
896
- obs_property_list_add_int(p, "2.0", VCEProfileLevel_20);
897
+ obs_property_list_add_int(p, "2.0", (int32_t)H264ProfileLevel::L20);
898
case 13:
899
- obs_property_list_add_int(p, "1.3", VCEProfileLevel_13);
900
+ obs_property_list_add_int(p, "1.3", (int32_t)H264ProfileLevel::L13);
901
case 12:
902
- obs_property_list_add_int(p, "1.2", VCEProfileLevel_12);
903
+ obs_property_list_add_int(p, "1.2", (int32_t)H264ProfileLevel::L12);
904
case 11:
905
- obs_property_list_add_int(p, "1.1", VCEProfileLevel_11);
906
+ obs_property_list_add_int(p, "1.1", (int32_t)H264ProfileLevel::L11);
907
case 10:
908
default:
909
- obs_property_list_add_int(p, "1.0", VCEProfileLevel_10);
910
+ obs_property_list_add_int(p, "1.0", (int32_t)H264ProfileLevel::L10);
911
}
912
#pragma endregion Profile Level
913
914
obs_property_int_set_limits(obs_properties_get(props, AMF_H264_BITRATE_TARGET),
915
- 10, devCaps.maxBitrate / 1000, 1);
916
+ 10, devCaps.maxBitrate / 1000, 1);
917
obs_property_int_set_limits(obs_properties_get(props, AMF_H264_BITRATE_PEAK),
918
- 10, devCaps.maxBitrate / 1000, 1);
919
+ 10, devCaps.maxBitrate / 1000, 1);
920
obs_property_int_set_limits(obs_properties_get(props, AMF_H264_VBVBUFFER_SIZE),
921
- 1, 100000, 1);
922
+ 1, 100000, 1);
923
obs_property_float_set_limits(obs_properties_get(props, AMF_H264_KEYFRAME_INTERVAL),
924
- 1.0 / 144.0, 30, 1.0 / 144.0);
925
+ 1.0 / 144.0, 30, 1.0 / 144.0);
926
obs_property_int_set_limits(obs_properties_get(props, AMF_H264_IDR_PERIOD),
927
- 1, 1000, 1);
928
+ 1, 1000, 1);
929
930
- // Experimental
931
+ // Experimental
932
obs_property_int_set_limits(obs_properties_get(props, AMF_H264_MAXIMUMREFERENCEFRAMES),
933
- devCaps.minReferenceFrames, devCaps.maxReferenceFrames, 1);
934
+ devCaps.minReferenceFrames, devCaps.maxReferenceFrames, 1);
935
}
936
#pragma endregion Video Adapter
937
938
#pragma region View Mode
939
- uint32_t lastView = (uint32_t)obs_data_get_int(data, "last" vstr(AMF_H264_VIEW)),
940
- curView = (uint32_t)obs_data_get_int(data, AMF_H264_VIEW);
941
+ ViewMode lastView = static_cast<ViewMode>(obs_data_get_int(data, "last" vstr(AMF_H264_VIEW))),
942
+ curView = static_cast<ViewMode>(obs_data_get_int(data, AMF_H264_VIEW));
943
if (lastView != curView) {
944
- obs_data_set_int(data, "last" vstr(AMF_H264_VIEW), curView);
945
+ obs_data_set_int(data, "last" vstr(AMF_H264_VIEW), static_cast<int32_t>(curView));
946
result = true;
947
}
948
949
950
#pragma endregion Master
951
952
#pragma region Special Logic
953
- uint32_t ltrFrames = (uint32_t)obs_data_get_int(data, AMF_H264_MAXIMUMLTRFRAMES);
954
+ uint32_t ltrFrames = static_cast<uint32_t>(obs_data_get_int(data, AMF_H264_MAXIMUMLTRFRAMES));
955
bool usingLTRFrames = ltrFrames > 0;
956
957
// Key-frame Interval
958
959
vis_rcm_qp_b = false,
960
vis_rcm_fillerdata = false;
961
962
- VCERateControlMethod lastRCM = (VCERateControlMethod)obs_data_get_int(data, "last" vstr(AMF_H264_RATECONTROLMETHOD)),
963
- curRCM = (VCERateControlMethod)obs_data_get_int(data, AMF_H264_RATECONTROLMETHOD);
964
+ H264RateControlMethod lastRCM = static_cast<H264RateControlMethod>(obs_data_get_int(data, "last" vstr(AMF_H264_RATECONTROLMETHOD))),
965
+ curRCM = static_cast<H264RateControlMethod>(obs_data_get_int(data, AMF_H264_RATECONTROLMETHOD));
966
if (lastRCM != curRCM) {
967
- obs_data_set_int(data, "last" vstr(AMF_H264_RATECONTROLMETHOD), curRCM);
968
+ obs_data_set_int(data, "last" vstr(AMF_H264_RATECONTROLMETHOD), static_cast<int32_t>(curRCM));
969
result = true;
970
}
971
switch (curRCM) {
972
- case VCERateControlMethod_ConstantBitrate:
973
+ case H264RateControlMethod::ConstantBitrate:
974
vis_rcm_bitrate_target = true;
975
vis_rcm_fillerdata = true;
976
break;
977
- case VCERateControlMethod_VariableBitrate_PeakConstrained:
978
+ case H264RateControlMethod::VariableBitrate_PeakConstrained:
979
vis_rcm_bitrate_target = true;
980
vis_rcm_bitrate_peak = true;
981
break;
982
- case VCERateControlMethod_VariableBitrate_LatencyConstrained:
983
+ case H264RateControlMethod::VariableBitrate_LatencyConstrained:
984
vis_rcm_bitrate_target = true;
985
vis_rcm_bitrate_peak = true;
986
break;
987
- case VCERateControlMethod_ConstantQP:
988
+ case H264RateControlMethod::ConstantQP:
989
vis_rcm_qp = true;
990
vis_rcm_qp_b = (!usingLTRFrames) && devCaps.supportsBFrames && usingBFrames;
991
break;
992
993
#pragma endregion Rate Control
994
995
#pragma region VBV Buffer
996
- uint32_t vbvBufferMode = (uint32_t)obs_data_get_int(data, AMF_H264_VBVBUFFER);
997
+ uint32_t vbvBufferMode = static_cast<uint32_t>(obs_data_get_int(data, AMF_H264_VBVBUFFER));
998
bool vbvBufferVisible = vis_advanced;
999
1000
- uint32_t lastVBVBufferMode = (uint32_t)obs_data_get_int(data, "last" vstr(AMF_H264_VBVBUFFER));
1001
+ uint32_t lastVBVBufferMode = static_cast<uint32_t>(obs_data_get_int(data, "last" vstr(AMF_H264_VBVBUFFER)));
1002
if (lastVBVBufferMode != vbvBufferMode) {
1003
obs_data_set_int(data, "last" vstr(AMF_H264_VBVBUFFER), vbvBufferMode);
1004
result = true;
1005
1006
bool Plugin::Interface::H264Interface::update(void *data, obs_data_t *settings) {
1007
try {
1008
return static_cast<Plugin::Interface::H264Interface*>(data)->update(settings);
1009
+ } catch (std::exception e) {
1010
+ AMF_LOG_ERROR("%s", e.what());
1011
+ } catch (std::exception* e) {
1012
+ AMF_LOG_ERROR("%s", e->what());
1013
+ delete e;
1014
} catch (...) {
1015
- AMF_LOG_ERROR("Unable to update Encoder, see log for more information.");
1016
- return false;
1017
+ AMF_LOG_ERROR("Unknown Exception.");
1018
}
1019
+ return false;
1020
}
1021
1022
void Plugin::Interface::H264Interface::get_video_info(void *data, struct video_scale_info *info) {
1023
try {
1024
return static_cast<Plugin::Interface::H264Interface*>(data)->get_video_info(info);
1025
+ } catch (std::exception e) {
1026
+ AMF_LOG_ERROR("%s", e.what());
1027
+ } catch (std::exception* e) {
1028
+ AMF_LOG_ERROR("%s", e->what());
1029
+ delete e;
1030
} catch (...) {
1031
- AMF_LOG_ERROR("Unable to get video info, see log for more information.");
1032
+ AMF_LOG_ERROR("Unknown Exception.");
1033
+ return;
1034
}
1035
}
1036
1037
bool Plugin::Interface::H264Interface::get_extra_data(void *data, uint8_t** extra_data, size_t* size) {
1038
try {
1039
return static_cast<Plugin::Interface::H264Interface*>(data)->get_extra_data(extra_data, size);
1040
+ } catch (std::exception e) {
1041
+ AMF_LOG_ERROR("%s", e.what());
1042
+ } catch (std::exception* e) {
1043
+ AMF_LOG_ERROR("%s", e->what());
1044
+ delete e;
1045
} catch (...) {
1046
- AMF_LOG_ERROR("Unable to get extra data, see log for more information.");
1047
- return false;
1048
+ AMF_LOG_ERROR("Unknown Exception.");
1049
}
1050
+ return false;
1051
}
1052
1053
//////////////////////////////////////////////////////////////////////////
1054
1055
uint32_t m_cfgFPSnum = voi->fps_num;
1056
uint32_t m_cfgFPSden = voi->fps_den;
1057
1058
+ obs_data_transfer_settings(data);
1059
+
1060
//////////////////////////////////////////////////////////////////////////
1061
/// Initialize Encoder
1062
bool debug = obs_data_get_bool(data, AMF_H264_DEBUG);
1063
Plugin::AMD::AMF::GetInstance()->EnableDebugTrace(debug);
1064
1065
- VCEColorFormat surfFormat = VCEColorFormat_NV12;
1066
+ H264ColorFormat surfFormat = H264ColorFormat::NV12;
1067
switch (voi->format) {
1068
case VIDEO_FORMAT_NV12:
1069
- surfFormat = VCEColorFormat_NV12;
1070
+ surfFormat = H264ColorFormat::NV12;
1071
break;
1072
case VIDEO_FORMAT_I420:
1073
- surfFormat = VCEColorFormat_I420;
1074
+ surfFormat = H264ColorFormat::I420;
1075
break;
1076
case VIDEO_FORMAT_YUY2:
1077
- surfFormat = VCEColorFormat_YUY2;
1078
+ surfFormat = H264ColorFormat::YUY2;
1079
break;
1080
case VIDEO_FORMAT_RGBA:
1081
- surfFormat = VCEColorFormat_RGBA;
1082
+ surfFormat = H264ColorFormat::RGBA;
1083
break;
1084
case VIDEO_FORMAT_BGRA:
1085
- surfFormat = VCEColorFormat_BGRA;
1086
+ surfFormat = H264ColorFormat::BGRA;
1087
break;
1088
case VIDEO_FORMAT_Y800:
1089
- surfFormat = VCEColorFormat_GRAY;
1090
+ surfFormat = H264ColorFormat::GRAY;
1091
break;
1092
}
1093
- m_VideoEncoder = new VCEEncoder(VCEEncoderType_AVC, obs_data_get_string(data, AMF_H264_VIDEOAPI),
1094
- obs_data_get_int(data, AMF_H264_VIDEOADAPTER), !!obs_data_get_int(data, AMF_H264_OPENCL), surfFormat);
1095
+ m_VideoEncoder = new H264Encoder(H264EncoderType::AVC, obs_data_get_string(data, AMF_H264_VIDEOAPI),
1096
+ obs_data_get_int(data, AMF_H264_VIDEOADAPTER), !!obs_data_get_int(data, AMF_H264_OPENCL), surfFormat);
1097
1098
- /// Static Properties
1099
- m_VideoEncoder->SetUsage((VCEUsage)obs_data_get_int(data, AMF_H264_USAGE));
1100
- m_VideoEncoder->SetQualityPreset((VCEQualityPreset)obs_data_get_int(data, AMF_H264_QUALITY_PRESET));
1101
+ /// Static Properties
1102
+ m_VideoEncoder->SetUsage(static_cast<H264Usage>(obs_data_get_int(data, AMF_H264_USAGE)));
1103
+ m_VideoEncoder->SetQualityPreset(static_cast<H264QualityPreset>(obs_data_get_int(data, AMF_H264_QUALITY_PRESET)));
1104
1105
/// Frame
1106
- m_VideoEncoder->SetColorProfile(voi->colorspace == VIDEO_CS_709 ? VCEColorProfile_709 : VCEColorProfile_601);
1107
+ m_VideoEncoder->SetColorProfile(voi->colorspace == VIDEO_CS_709 ? H264ColorProfile::Rec709 : H264ColorProfile::Rec601);
1108
try { m_VideoEncoder->SetFullRangeColorEnabled(voi->range == VIDEO_RANGE_FULL); } catch (...) {}
1109
m_VideoEncoder->SetResolution(m_cfgWidth, m_cfgHeight);
1110
m_VideoEncoder->SetFrameRate(m_cfgFPSnum, m_cfgFPSden);
1111
- m_VideoEncoder->SetScanType((VCEScanType)obs_data_get_int(data, AMF_H264_SCANTYPE)); /// Progressive or Interlaced
1112
+ m_VideoEncoder->SetScanType(static_cast<H264ScanType>(obs_data_get_int(data, AMF_H264_SCANTYPE)));
1113
1114
/// Profile & Level
1115
- m_VideoEncoder->SetProfile((VCEProfile)obs_data_get_int(data, AMF_H264_PROFILE));
1116
- m_VideoEncoder->SetProfileLevel((VCEProfileLevel)obs_data_get_int(data, AMF_H264_PROFILELEVEL));
1117
+ m_VideoEncoder->SetProfile(static_cast<H264Profile>(obs_data_get_int(data, AMF_H264_PROFILE)));
1118
+ m_VideoEncoder->SetProfileLevel(static_cast<H264ProfileLevel>(obs_data_get_int(data, AMF_H264_PROFILELEVEL)));
1119
1120
#pragma region Experimental
1121
/// Long Term Reference
1122
- if ((uint32_t)obs_data_get_int(data, AMF_H264_MAXIMUMLTRFRAMES) > 0)
1123
- m_VideoEncoder->SetBFramePattern(VCEBFramePattern_None);
1124
- m_VideoEncoder->SetMaximumLongTermReferenceFrames((uint32_t)obs_data_get_int(data, AMF_H264_MAXIMUMLTRFRAMES));
1125
+ if (static_cast<uint32_t>(obs_data_get_int(data, AMF_H264_MAXIMUMLTRFRAMES) > 0))
1126
+ m_VideoEncoder->SetBFramePattern(H264BFramePattern::None);
1127
+ m_VideoEncoder->SetMaximumLongTermReferenceFrames(static_cast<uint32_t>(obs_data_get_int(data, AMF_H264_MAXIMUMLTRFRAMES)));
1128
1129
#pragma endregion Experimental
1130
1131
1132
const char* p_str = obs_data_get_string(data, "profile");
1133
if (strcmp(p_str, "") != 0) {
1134
if (strcmp(p_str, "constrained_baseline")) {
1135
- m_VideoEncoder->SetProfile(VCEProfile_ConstrainedBaseline);
1136
+ m_VideoEncoder->SetProfile(H264Profile::ConstrainedBaseline);
1137
} else if (strcmp(p_str, "baseline")) {
1138
- m_VideoEncoder->SetProfile(VCEProfile_Baseline);
1139
+ m_VideoEncoder->SetProfile(H264Profile::Baseline);
1140
} else if (strcmp(p_str, "main")) {
1141
- m_VideoEncoder->SetProfile(VCEProfile_Main);
1142
+ m_VideoEncoder->SetProfile(H264Profile::Main);
1143
} else if (strcmp(p_str, "constrained_high")) {
1144
- m_VideoEncoder->SetProfile(VCEProfile_ConstrainedHigh);
1145
+ m_VideoEncoder->SetProfile(H264Profile::ConstrainedHigh);
1146
} else if (strcmp(p_str, "high")) {
1147
- m_VideoEncoder->SetProfile(VCEProfile_High);
1148
+ m_VideoEncoder->SetProfile(H264Profile::High);
1149
}
1150
} else {
1151
switch (m_VideoEncoder->GetProfile()) {
1152
- case VCEProfile_ConstrainedBaseline:
1153
+ case H264Profile::ConstrainedBaseline:
1154
obs_data_set_string(data, "profile", "constrained_baseline");
1155
break;
1156
- case VCEProfile_Baseline:
1157
+ case H264Profile::Baseline:
1158
obs_data_set_string(data, "profile", "baseline");
1159
break;
1160
- case VCEProfile_Main:
1161
+ case H264Profile::Main:
1162
obs_data_set_string(data, "profile", "main");
1163
break;
1164
- case VCEProfile_ConstrainedHigh:
1165
+ case H264Profile::ConstrainedHigh:
1166
obs_data_set_string(data, "profile", "constrained_high");
1167
break;
1168
- case VCEProfile_High:
1169
+ case H264Profile::High:
1170
obs_data_set_string(data, "profile", "high");
1171
break;
1172
}
1173
1174
const char* preset = obs_data_get_string(data, "preset");
1175
if (strcmp(preset, "") != 0) {
1176
if (strcmp(preset, "speed") == 0) {
1177
- m_VideoEncoder->SetQualityPreset(VCEQualityPreset_Speed);
1178
+ m_VideoEncoder->SetQualityPreset(H264QualityPreset::Speed);
1179
} else if (strcmp(preset, "balanced") == 0) {
1180
- m_VideoEncoder->SetQualityPreset(VCEQualityPreset_Balanced);
1181
+ m_VideoEncoder->SetQualityPreset(H264QualityPreset::Balanced);
1182
} else if (strcmp(preset, "quality") == 0) {
1183
- m_VideoEncoder->SetQualityPreset(VCEQualityPreset_Quality);
1184
+ m_VideoEncoder->SetQualityPreset(H264QualityPreset::Quality);
1185
}
1186
- obs_data_set_int(data, AMF_H264_QUALITY_PRESET, m_VideoEncoder->GetQualityPreset());
1187
+ obs_data_set_int(data, AMF_H264_QUALITY_PRESET, (int32_t)m_VideoEncoder->GetQualityPreset());
1188
} else {
1189
switch (m_VideoEncoder->GetQualityPreset()) {
1190
- case VCEQualityPreset_Speed:
1191
+ case H264QualityPreset::Speed:
1192
obs_data_set_string(data, "preset", "speed");
1193
break;
1194
- case VCEQualityPreset_Balanced:
1195
+ case H264QualityPreset::Balanced:
1196
obs_data_set_string(data, "preset", "balanced");
1197
break;
1198
- case VCEQualityPreset_Quality:
1199
+ case H264QualityPreset::Quality:
1200
obs_data_set_string(data, "preset", "quality");
1201
break;
1202
}
1203
1204
auto api = Plugin::API::Base::GetAPIByName(obs_data_get_string(data, AMF_H264_VIDEOAPI));
1205
int64_t adapterId = obs_data_get_int(data, AMF_H264_VIDEOADAPTER);
1206
auto adapter = api->GetAdapterById(adapterId & UINT_MAX, (adapterId >> 32) & UINT_MAX);
1207
- auto devCaps = Plugin::AMD::VCECapabilities::GetInstance()->GetAdapterCapabilities(api, adapter, VCEEncoderType_AVC);
1208
+ auto devCaps = Plugin::AMD::VCECapabilities::GetInstance()->GetAdapterCapabilities(api, adapter, H264EncoderType::AVC);
1209
#pragma endregion Device Capabilities
1210
1211
#pragma region Rate Control
1212
// Rate Control Properties
1213
- m_VideoEncoder->SetRateControlMethod((VCERateControlMethod)obs_data_get_int(data, AMF_H264_RATECONTROLMETHOD));
1214
- m_VideoEncoder->SetMinimumQP((uint8_t)obs_data_get_int(data, AMF_H264_QP_MINIMUM));
1215
- m_VideoEncoder->SetMaximumQP((uint8_t)obs_data_get_int(data, AMF_H264_QP_MAXIMUM));
1216
- switch ((VCERateControlMethod)obs_data_get_int(data, AMF_H264_RATECONTROLMETHOD)) {
1217
- case VCERateControlMethod_ConstantBitrate:
1218
- m_VideoEncoder->SetTargetBitrate((uint32_t)obs_data_get_int(data, AMF_H264_BITRATE_TARGET) * 1000);
1219
- m_VideoEncoder->SetPeakBitrate(m_VideoEncoder->GetTargetBitrate());
1220
- break;
1221
- case VCERateControlMethod_VariableBitrate_PeakConstrained:
1222
- m_VideoEncoder->SetTargetBitrate((uint32_t)obs_data_get_int(data, AMF_H264_BITRATE_TARGET) * 1000);
1223
- m_VideoEncoder->SetPeakBitrate((uint32_t)obs_data_get_int(data, AMF_H264_BITRATE_PEAK) * 1000);
1224
- break;
1225
- case VCERateControlMethod_VariableBitrate_LatencyConstrained:
1226
- m_VideoEncoder->SetTargetBitrate((uint32_t)obs_data_get_int(data, AMF_H264_BITRATE_TARGET) * 1000);
1227
- m_VideoEncoder->SetPeakBitrate((uint32_t)obs_data_get_int(data, AMF_H264_BITRATE_PEAK) * 1000);
1228
- break;
1229
- case VCERateControlMethod_ConstantQP:
1230
- m_VideoEncoder->SetIFrameQP((uint8_t)obs_data_get_int(data, AMF_H264_QP_IFRAME));
1231
- m_VideoEncoder->SetPFrameQP((uint8_t)obs_data_get_int(data, AMF_H264_QP_PFRAME));
1232
- try {
1233
- m_VideoEncoder->SetBFrameQP((uint8_t)obs_data_get_int(data, AMF_H264_QP_BFRAME));
1234
- } catch (std::exception e) {} catch (...) {}
1235
- break;
1236
- }
1237
- if (obs_data_get_int(data, AMF_H264_VBVBUFFER) == 0) {
1238
- m_VideoEncoder->SetVBVBufferAutomatic(obs_data_get_double(data, AMF_H264_VBVBUFFER_STRICTNESS) / 100.0);
1239
+ if (m_VideoEncoder->GetUsage() != H264Usage::UltraLowLatency) {
1240
+ m_VideoEncoder->SetRateControlMethod(static_cast<H264RateControlMethod>(obs_data_get_int(data, AMF_H264_RATECONTROLMETHOD)));
1241
+ m_VideoEncoder->SetMinimumQP(static_cast<uint8_t>(obs_data_get_int(data, AMF_H264_QP_MINIMUM)));
1242
+ m_VideoEncoder->SetMaximumQP(static_cast<uint8_t>(obs_data_get_int(data, AMF_H264_QP_MAXIMUM)));
1243
+ switch (static_cast<H264RateControlMethod>(obs_data_get_int(data, AMF_H264_RATECONTROLMETHOD))) {
1244
+ case H264RateControlMethod::ConstantBitrate:
1245
+ m_VideoEncoder->SetTargetBitrate(static_cast<uint32_t>(obs_data_get_int(data, AMF_H264_BITRATE_TARGET) * 1000));
1246
+ m_VideoEncoder->SetPeakBitrate(m_VideoEncoder->GetTargetBitrate());
1247
+ break;
1248
+ case H264RateControlMethod::VariableBitrate_PeakConstrained:
1249
+ case H264RateControlMethod::VariableBitrate_LatencyConstrained:
1250
+ m_VideoEncoder->SetTargetBitrate(static_cast<uint32_t>(obs_data_get_int(data, AMF_H264_BITRATE_TARGET) * 1000));
1251
+ m_VideoEncoder->SetPeakBitrate(static_cast<uint32_t>(obs_data_get_int(data, AMF_H264_BITRATE_PEAK) * 1000));
1252
+ break;
1253
+ case H264RateControlMethod::ConstantQP:
1254
+ m_VideoEncoder->SetIFrameQP(static_cast<uint8_t>(obs_data_get_int(data, AMF_H264_QP_IFRAME)));
1255
+ m_VideoEncoder->SetPFrameQP(static_cast<uint8_t>(obs_data_get_int(data, AMF_H264_QP_PFRAME)));
1256
+ if (devCaps.supportsBFrames && m_VideoEncoder->GetUsage() != H264Usage::UltraLowLatency)
1257
+ try { m_VideoEncoder->SetBFrameQP(static_cast<uint8_t>(obs_data_get_int(data, AMF_H264_QP_BFRAME))); } catch (...) {}
1258
+ break;
1259
+ }
1260
+ if (obs_data_get_int(data, AMF_H264_VBVBUFFER) == 0) {
1261
+ m_VideoEncoder->SetVBVBufferAutomatic(obs_data_get_double(data, AMF_H264_VBVBUFFER_STRICTNESS) / 100.0);
1262
+ } else {
1263
+ m_VideoEncoder->SetVBVBufferSize(static_cast<uint32_t>(obs_data_get_int(data, AMF_H264_VBVBUFFER_SIZE) * 1000));
1264
+ }
1265
+ m_VideoEncoder->SetInitialVBVBufferFullness(obs_data_get_double(data, AMF_H264_VBVBUFFER_FULLNESS) / 100.0);
1266
+ m_VideoEncoder->SetFillerDataEnabled(!!obs_data_get_int(data, AMF_H264_FILLERDATA));
1267
+ m_VideoEncoder->SetFrameSkippingEnabled(!!obs_data_get_int(data, AMF_H264_FRAMESKIPPING));
1268
} else {
1269
- m_VideoEncoder->SetVBVBufferSize((uint32_t)obs_data_get_int(data, AMF_H264_VBVBUFFER_SIZE) * 1000);
1270
+ m_VideoEncoder->SetMinimumQP(static_cast<uint8_t>(obs_data_get_int(data, AMF_H264_QP_MINIMUM)));
1271
+ m_VideoEncoder->SetMaximumQP(static_cast<uint8_t>(obs_data_get_int(data, AMF_H264_QP_MAXIMUM)));
1272
+ m_VideoEncoder->SetTargetBitrate(static_cast<uint32_t>(obs_data_get_int(data, AMF_H264_BITRATE_TARGET) * 1000));
1273
+
1274
+ m_VideoEncoder->SetIFrameQP(static_cast<uint8_t>(obs_data_get_int(data, AMF_H264_QP_IFRAME)));
1275
+ m_VideoEncoder->SetPFrameQP(static_cast<uint8_t>(obs_data_get_int(data, AMF_H264_QP_PFRAME)));
1276
+
1277
+ if (obs_data_get_int(data, AMF_H264_VBVBUFFER) == 0) {
1278
+ m_VideoEncoder->SetVBVBufferSize(static_cast<uint32_t>(obs_data_get_int(data, AMF_H264_BITRATE_TARGET) * 1000));
1279
+ } else {
1280
+ m_VideoEncoder->SetVBVBufferSize(static_cast<uint32_t>(obs_data_get_int(data, AMF_H264_VBVBUFFER_SIZE) * 1000));
1281
+ }
1282
}
1283
- m_VideoEncoder->SetInitialVBVBufferFullness(obs_data_get_double(data, AMF_H264_VBVBUFFER_FULLNESS) / 100.0);
1284
- m_VideoEncoder->SetFillerDataEnabled(obs_data_get_int(data, AMF_H264_FILLERDATA) == 1);
1285
- m_VideoEncoder->SetFrameSkippingEnabled(obs_data_get_int(data, AMF_H264_FRAMESKIPPING) == 1);
1286
m_VideoEncoder->SetEnforceHRDRestrictionsEnabled(obs_data_get_int(data, AMF_H264_ENFORCEHRDCOMPATIBILITY) == 1);
1287
#pragma endregion Rate Control
1288
1289
// Key-frame Interval
1290
double_t framerate = (double_t)m_VideoEncoder->GetFrameRate().first / (double_t)m_VideoEncoder->GetFrameRate().second;
1291
- if (obs_data_get_int(data, AMF_H264_VIEW) == ViewMode::Master)
1292
- m_VideoEncoder->SetIDRPeriod((uint32_t)obs_data_get_int(data, AMF_H264_IDR_PERIOD));
1293
+ if (static_cast<ViewMode>(obs_data_get_int(data, AMF_H264_VIEW)) == ViewMode::Master)
1294
+ m_VideoEncoder->SetIDRPeriod(static_cast<uint32_t>(obs_data_get_int(data, AMF_H264_IDR_PERIOD)));
1295
else
1296
- m_VideoEncoder->SetIDRPeriod(max((uint32_t)(obs_data_get_double(data, AMF_H264_KEYFRAME_INTERVAL) * framerate), 1));
1297
+ m_VideoEncoder->SetIDRPeriod(max(static_cast<uint32_t>(obs_data_get_double(data, AMF_H264_KEYFRAME_INTERVAL) * framerate), 1));
1298
1299
#pragma region B-Frames
1300
if (devCaps.supportsBFrames) {
1301
try {
1302
- m_VideoEncoder->SetBFramePattern((VCEBFramePattern)obs_data_get_int(data, AMF_H264_BFRAME_PATTERN));
1303
- m_VideoEncoder->SetBFrameReferenceEnabled(!!obs_data_get_int(data, AMF_H264_BFRAME_REFERENCE));
1304
- } catch (std::exception e) {} catch (...) {}
1305
- try {
1306
- if (m_VideoEncoder->GetBFramePattern() != VCEBFramePattern_None) {
1307
- m_VideoEncoder->SetBFrameDeltaQP((int8_t)obs_data_get_int(data, AMF_H264_BFRAME_DELTAQP));
1308
- if (m_VideoEncoder->IsBFrameReferenceEnabled())
1309
- m_VideoEncoder->SetBFrameReferenceDeltaQP((int8_t)obs_data_get_int(data, AMF_H264_BFRAME_REFERENCEDELTAQP));
1310
- }
1311
- } catch (std::exception e) {} catch (...) {}
1312
+ m_VideoEncoder->SetBFramePattern(static_cast<H264BFramePattern>(obs_data_get_int(data, AMF_H264_BFRAME_PATTERN)));
1313
+ if (obs_data_get_int(data, AMF_H264_BFRAME_PATTERN) != 0)
1314
+ m_VideoEncoder->SetBFrameDeltaQP(static_cast<int8_t>(obs_data_get_int(data, AMF_H264_BFRAME_DELTAQP)));
1315
+ } catch (...) {}
1316
+
1317
+ // B-Frame Reference can't be used with anything else but Transcoding.
1318
+ if (m_VideoEncoder->GetUsage() == H264Usage::Transcoding) {
1319
+ try {
1320
+ m_VideoEncoder->SetBFrameReferenceEnabled(!!obs_data_get_int(data, AMF_H264_BFRAME_REFERENCE));
1321
+ if (!!obs_data_get_int(data, AMF_H264_BFRAME_REFERENCE))
1322
+ m_VideoEncoder->SetBFrameReferenceDeltaQP(static_cast<int8_t>(obs_data_get_int(data, AMF_H264_BFRAME_REFERENCEDELTAQP)));
1323
+ } catch (...) {}
1324
+ }
1325
}
1326
#pragma endregion B-Frames
1327
1328
- m_VideoEncoder->SetDeblockingFilterEnabled(!!obs_data_get_int(data, AMF_H264_DEBLOCKINGFILTER));
1329
+ if (m_VideoEncoder->GetUsage() == H264Usage::Transcoding)
1330
+ m_VideoEncoder->SetDeblockingFilterEnabled(!!obs_data_get_int(data, AMF_H264_DEBLOCKINGFILTER));
1331
1332
#pragma region Motion Estimation
1333
m_VideoEncoder->SetHalfPixelMotionEstimationEnabled(!!(obs_data_get_int(data, AMF_H264_MOTIONESTIMATION) & 1));
1334
1335
#pragma endregion Motion Estimation
1336
1337
#pragma region Experimental
1338
- try { m_VideoEncoder->SetCodingType((VCECodingType)obs_data_get_int(data, AMF_H264_CODINGTYPE)); } catch (std::exception e) {} catch (...) {}
1339
- try { m_VideoEncoder->SetWaitForTaskEnabled(!!obs_data_get_int(data, AMF_H264_WAITFORTASK)); } catch (std::exception e) {} catch (...) {}
1340
- try { m_VideoEncoder->SetPreAnalysisPassEnabled(!!obs_data_get_int(data, AMF_H264_PREANALYSISPASS)); } catch (std::exception e) {} catch (...) {}
1341
- try { m_VideoEncoder->SetVBAQEnabled(!!obs_data_get_int(data, AMF_H264_VBAQ)); } catch (std::exception e) {} catch (...) {}
1342
-
1343
- try { m_VideoEncoder->SetHeaderInsertionSpacing((uint32_t)obs_data_get_int(data, AMF_H264_HEADER_INSERTION_SPACING)); } catch (std::exception e) {} catch (...) {}
1344
- try { m_VideoEncoder->SetMaximumAccessUnitSize((uint32_t)obs_data_get_int(data, AMF_H264_MAXIMUMACCESSUNITSIZE)); } catch (std::exception e) {} catch (...) {}
1345
- try { m_VideoEncoder->SetMaximumReferenceFrames((uint32_t)obs_data_get_int(data, AMF_H264_MAXIMUMREFERENCEFRAMES)); } catch (std::exception e) {} catch (...) {}
1346
-
1347
- try { m_VideoEncoder->SetGOPSize((uint32_t)obs_data_get_int(data, AMF_H264_GOPSIZE)); } catch (std::exception e) {} catch (...) {}
1348
- try { m_VideoEncoder->SetGOPAlignmentEnabled(!!obs_data_get_int(data, AMF_H264_GOPALIGNMENT)); } catch (std::exception e) {} catch (...) {}
1349
-
1350
- try { m_VideoEncoder->SetIntraRefreshNumberOfStripes((uint32_t)obs_data_get_int(data, AMF_H264_INTRAREFRESH_NUMBEROFSTRIPES)); } catch (std::exception e) {} catch (...) {}
1351
- try { m_VideoEncoder->SetIntraRefreshMacroblocksPerSlot((uint32_t)obs_data_get_int(data, AMF_H264_INTRAREFRESH_MACROBLOCKSPERSLOT)); } catch (std::exception e) {} catch (...) {}
1352
-
1353
- try { m_VideoEncoder->SetSlicesPerFrame((uint32_t)obs_data_get_int(data, AMF_H264_SLICESPERFRAME)); } catch (std::exception e) {} catch (...) {}
1354
- try { m_VideoEncoder->SetSliceMode((VCESliceMode)obs_data_get_int(data, AMF_H264_SLICEMODE)); } catch (std::exception e) {} catch (...) {}
1355
- try { m_VideoEncoder->SetMaximumSliceSize((uint32_t)obs_data_get_int(data, AMF_H264_MAXIMUMSLICESIZE)); } catch (std::exception e) {} catch (...) {}
1356
- try { m_VideoEncoder->SetSliceControlMode((VCESliceControlMode)obs_data_get_int(data, AMF_H264_SLICECONTROLMODE)); } catch (std::exception e) {} catch (...) {}
1357
- try { m_VideoEncoder->SetSliceControlSize((uint32_t)obs_data_get_int(data, AMF_H264_SLICECONTROLSIZE)); } catch (std::exception e) {} catch (...) {}
1358
+ try { m_VideoEncoder->SetCodingType(static_cast<H264CodingType>(obs_data_get_int(data, AMF_H264_CODINGTYPE))); } catch (...) {}
1359
+ try { m_VideoEncoder->SetWaitForTaskEnabled(!!obs_data_get_int(data, AMF_H264_WAITFORTASK)); } catch (...) {}
1360
+ if (m_VideoEncoder->GetUsage() == H264Usage::Transcoding || m_VideoEncoder->GetUsage() == H264Usage::Webcam) {
1361
+ try { m_VideoEncoder->SetPreAnalysisPassEnabled(!!obs_data_get_int(data, AMF_H264_PREANALYSISPASS)); } catch (...) {}
1362
+ try { m_VideoEncoder->SetVBAQEnabled(!!obs_data_get_int(data, AMF_H264_VBAQ)); } catch (...) {}
1363
+ }
1364
+
1365
+ try { m_VideoEncoder->SetHeaderInsertionSpacing(static_cast<uint32_t>(obs_data_get_int(data, AMF_H264_HEADER_INSERTION_SPACING))); } catch (...) {}
1366
+ if (m_VideoEncoder->GetUsage() == H264Usage::Transcoding || m_VideoEncoder->GetUsage() == H264Usage::Webcam) {
1367
+ try { m_VideoEncoder->SetMaximumAccessUnitSize(static_cast<uint32_t>(obs_data_get_int(data, AMF_H264_MAXIMUMACCESSUNITSIZE))); } catch (...) {}
1368
+ }
1369
+ try { m_VideoEncoder->SetMaximumReferenceFrames(static_cast<uint32_t>(obs_data_get_int(data, AMF_H264_MAXIMUMREFERENCEFRAMES))); } catch (...) {}
1370
+
1371
+ if (m_VideoEncoder->GetUsage() == H264Usage::Transcoding || m_VideoEncoder->GetUsage() == H264Usage::Webcam) {
1372
+ try { m_VideoEncoder->SetGOPSize(static_cast<uint32_t>(obs_data_get_int(data, AMF_H264_GOPSIZE))); } catch (...) {}
1373
+ }
1374
+ try { m_VideoEncoder->SetGOPAlignmentEnabled(!!obs_data_get_int(data, AMF_H264_GOPALIGNMENT)); } catch (...) {}
1375
+
1376
+ try { m_VideoEncoder->SetIntraRefreshNumberOfStripes(static_cast<uint32_t>(obs_data_get_int(data, AMF_H264_INTRAREFRESH_NUMBEROFSTRIPES))); } catch (...) {}
1377
+ try { m_VideoEncoder->SetIntraRefreshMacroblocksPerSlot(static_cast<uint32_t>(obs_data_get_int(data, AMF_H264_INTRAREFRESH_MACROBLOCKSPERSLOT))); } catch (...) {}
1378
+
1379
+ try { m_VideoEncoder->SetSlicesPerFrame(static_cast<uint32_t>(obs_data_get_int(data, AMF_H264_SLICESPERFRAME))); } catch (...) {}
1380
+ try { m_VideoEncoder->SetSliceMode(static_cast<H264SliceMode>(obs_data_get_int(data, AMF_H264_SLICEMODE))); } catch (...) {}
1381
+ try { m_VideoEncoder->SetMaximumSliceSize(static_cast<uint32_t>(obs_data_get_int(data, AMF_H264_MAXIMUMSLICESIZE))); } catch (...) {}
1382
+ try { m_VideoEncoder->SetSliceControlMode(static_cast<H264SliceControlMode>(obs_data_get_int(data, AMF_H264_SLICECONTROLMODE))); } catch (...) {}
1383
+ try { m_VideoEncoder->SetSliceControlSize(static_cast<uint32_t>(obs_data_get_int(data, AMF_H264_SLICECONTROLSIZE))); } catch (...) {}
1384
#pragma endregion Experimental
1385
1386
if (m_VideoEncoder->IsStarted()) {
1387
1388
const char* t_str = obs_data_get_string(data, "rate_control");
1389
if (strcmp(t_str, "") != 0) {
1390
if (strcmp(t_str, "CBR") == 0) {
1391
- m_VideoEncoder->SetRateControlMethod(VCERateControlMethod_ConstantBitrate);
1392
+ m_VideoEncoder->SetRateControlMethod(H264RateControlMethod::ConstantBitrate);
1393
m_VideoEncoder->SetFillerDataEnabled(true);
1394
} else if (strcmp(t_str, "VBR") == 0) {
1395
- m_VideoEncoder->SetRateControlMethod(VCERateControlMethod_VariableBitrate_PeakConstrained);
1396
+ m_VideoEncoder->SetRateControlMethod(H264RateControlMethod::VariableBitrate_PeakConstrained);
1397
} else if (strcmp(t_str, "VBR_LAT") == 0) {
1398
- m_VideoEncoder->SetRateControlMethod(VCERateControlMethod_VariableBitrate_LatencyConstrained);
1399
+ m_VideoEncoder->SetRateControlMethod(H264RateControlMethod::VariableBitrate_LatencyConstrained);
1400
} else if (strcmp(t_str, "CQP") == 0) {
1401
- m_VideoEncoder->SetRateControlMethod(VCERateControlMethod_ConstantQP);
1402
+ m_VideoEncoder->SetRateControlMethod(H264RateControlMethod::ConstantQP);
1403
}
1404
1405
- obs_data_set_int(data, AMF_H264_RATECONTROLMETHOD, m_VideoEncoder->GetRateControlMethod());
1406
+ obs_data_set_int(data, AMF_H264_RATECONTROLMETHOD, (int32_t)m_VideoEncoder->GetRateControlMethod());
1407
} else {
1408
- switch (m_VideoEncoder->GetRateControlMethod()) {
1409
- case VCERateControlMethod_ConstantBitrate:
1410
- obs_data_set_string(data, "rate_control", "CBR");
1411
- break;
1412
- case VCERateControlMethod_VariableBitrate_PeakConstrained:
1413
- obs_data_set_string(data, "rate_control", "VBR");
1414
- break;
1415
- case VCERateControlMethod_VariableBitrate_LatencyConstrained:
1416
- obs_data_set_string(data, "rate_control", "VBR_LAT");
1417
- break;
1418
- case VCERateControlMethod_ConstantQP:
1419
- obs_data_set_string(data, "rate_control", "CQP");
1420
- break;
1421
- }
1422
+ if (m_VideoEncoder->GetUsage() != H264Usage::UltraLowLatency)
1423
+ switch (m_VideoEncoder->GetRateControlMethod()) {
1424
+ case H264RateControlMethod::ConstantBitrate:
1425
+ obs_data_set_string(data, "rate_control", "CBR");
1426
+ break;
1427
+ case H264RateControlMethod::VariableBitrate_PeakConstrained:
1428
+ obs_data_set_string(data, "rate_control", "VBR");
1429
+ break;
1430
+ case H264RateControlMethod::VariableBitrate_LatencyConstrained:
1431
+ obs_data_set_string(data, "rate_control", "VBR_LAT");
1432
+ break;
1433
+ case H264RateControlMethod::ConstantQP:
1434
+ obs_data_set_string(data, "rate_control", "CQP");
1435
+ break;
1436
+ }
1437
}
1438
1439
// Bitrate
1440
uint64_t bitrateOvr = obs_data_get_int(data, "bitrate") * 1000;
1441
if (bitrateOvr != -1) {
1442
if (m_VideoEncoder->GetTargetBitrate() > bitrateOvr)
1443
- m_VideoEncoder->SetTargetBitrate((uint32_t)bitrateOvr);
1444
+ m_VideoEncoder->SetTargetBitrate(static_cast<uint32_t>(bitrateOvr));
1445
1446
- if (m_VideoEncoder->GetPeakBitrate() > bitrateOvr)
1447
- m_VideoEncoder->SetPeakBitrate((uint32_t)bitrateOvr);
1448
+ if (m_VideoEncoder->GetUsage() != H264Usage::UltraLowLatency)
1449
+ if (m_VideoEncoder->GetPeakBitrate() > bitrateOvr)
1450
+ m_VideoEncoder->SetPeakBitrate(static_cast<uint32_t>(bitrateOvr));
1451
1452
obs_data_set_int(data, "bitrate", m_VideoEncoder->GetTargetBitrate() / 1000);
1453
1454
obs_data_set_int(data, AMF_H264_BITRATE_TARGET, m_VideoEncoder->GetTargetBitrate() / 1000);
1455
- obs_data_set_int(data, AMF_H264_BITRATE_PEAK, m_VideoEncoder->GetPeakBitrate() / 1000);
1456
+ if (m_VideoEncoder->GetUsage() != H264Usage::UltraLowLatency)
1457
+ obs_data_set_int(data, AMF_H264_BITRATE_PEAK, m_VideoEncoder->GetPeakBitrate() / 1000);
1458
} else {
1459
obs_data_set_int(data, "bitrate", m_VideoEncoder->GetTargetBitrate() / 1000);
1460
}
1461
1462
uint32_t fpsNum = m_VideoEncoder->GetFrameRate().first;
1463
uint32_t fpsDen = m_VideoEncoder->GetFrameRate().second;
1464
if (obs_data_get_int(data, "keyint_sec") != -1) {
1465
- m_VideoEncoder->SetIDRPeriod((uint32_t)(obs_data_get_int(data, "keyint_sec") * ((double_t)fpsNum / (double_t)fpsDen)));
1466
+ m_VideoEncoder->SetIDRPeriod(static_cast<uint32_t>(obs_data_get_int(data, "keyint_sec") * (static_cast<double_t>(fpsNum) / static_cast<double_t>(fpsDen))));
1467
1468
- obs_data_set_double(data, AMF_H264_KEYFRAME_INTERVAL, (double_t)obs_data_get_int(data, "keyint_sec"));
1469
- obs_data_set_int(data, AMF_H264_IDR_PERIOD, (uint32_t)(obs_data_get_int(data, "keyint_sec") * ((double_t)fpsNum / (double_t)fpsDen)));
1470
+ obs_data_set_double(data, AMF_H264_KEYFRAME_INTERVAL, static_cast<double_t>(obs_data_get_int(data, "keyint_sec")));
1471
+ obs_data_set_int(data, AMF_H264_IDR_PERIOD, static_cast<uint32_t>(obs_data_get_int(data, "keyint_sec") * (static_cast<double_t>(fpsNum) / static_cast<double_t>(fpsDen))));
1472
} else {
1473
- obs_data_set_int(data, "keyint_sec", (uint64_t)(m_VideoEncoder->GetIDRPeriod() / ((double_t)fpsNum / (double_t)fpsDen)));
1474
+ obs_data_set_int(data, "keyint_sec", static_cast<uint64_t>(m_VideoEncoder->GetIDRPeriod() / (static_cast<double_t>(fpsNum) / static_cast<double_t>(fpsDen))));
1475
}
1476
}
1477
#pragma endregion OBS Enforce Streaming Service Settings
1478
1479
// Verify
1480
m_VideoEncoder->LogProperties();
1481
- if (obs_data_get_int(data, AMF_H264_VIEW) >= ViewMode::Master)
1482
+ if (static_cast<ViewMode>(obs_data_get_int(data, AMF_H264_VIEW)) >= ViewMode::Master)
1483
AMF_LOG_ERROR("View Mode 'Master' is active, avoid giving anything but basic support. Error is most likely caused by user settings themselves.");
1484
}
1485
1486
obs-studio-0.17.0.tar.xz/plugins/enc-amf/Source/misc-util.cpp -> obs-studio-17.0.1.tar.xz/plugins/enc-amf/Source/misc-util.cpp
Changed
295
1
2
3
namespace Plugin {
4
namespace Utility {
5
- VCEProfileLevel inline GetMinimumProfileLevel(std::pair<uint32_t, uint32_t> frameSize, std::pair<uint32_t, uint32_t> frameRate) {
6
+ H264ProfileLevel inline GetMinimumProfileLevel(std::pair<uint32_t, uint32_t> frameSize, std::pair<uint32_t, uint32_t> frameRate) {
7
typedef std::pair<uint32_t, uint32_t> levelRestriction;
8
- typedef std::pair<VCEProfileLevel, levelRestriction> level;
9
+ typedef std::pair<H264ProfileLevel, levelRestriction> level;
10
11
static const level profileLevelLimit[] = { // [Level, [Samples, Samples_Per_Sec]]
12
- level(VCEProfileLevel_10, levelRestriction(25344, 380160)),
13
- level(VCEProfileLevel_11, levelRestriction(101376, 768000)),
14
- level(VCEProfileLevel_12, levelRestriction(101376, 1536000)),
15
- level(VCEProfileLevel_13, levelRestriction(101376, 3041280)),
16
- level(VCEProfileLevel_20, levelRestriction(101376, 3041280)),
17
- level(VCEProfileLevel_21, levelRestriction(202752, 5068800)),
18
- level(VCEProfileLevel_22, levelRestriction(414720, 5184000)),
19
- level(VCEProfileLevel_30, levelRestriction(414720, 10368000)),
20
- level(VCEProfileLevel_31, levelRestriction(921600, 27648000)),
21
- level(VCEProfileLevel_32, levelRestriction(1310720, 55296000)),
22
- //level(VCEProfileLevel_40, levelRestriction(2097152, 62914560)), // Technically identical to 4.1, but backwards compatible.
23
- level(VCEProfileLevel_41, levelRestriction(2097152, 62914560)),
24
- level(VCEProfileLevel_42, levelRestriction(2228224, 133693440)),
25
- level(VCEProfileLevel_50, levelRestriction(5652480, 150994944)),
26
- level(VCEProfileLevel_51, levelRestriction(9437184, 251658240)),
27
- level(VCEProfileLevel_52, levelRestriction(9437184, 530841600)),
28
- level((VCEProfileLevel)-1, levelRestriction(0, 0))
29
+ level(H264ProfileLevel::L10, levelRestriction(25344, 380160)),
30
+ level(H264ProfileLevel::L11, levelRestriction(101376, 768000)),
31
+ level(H264ProfileLevel::L12, levelRestriction(101376, 1536000)),
32
+ level(H264ProfileLevel::L13, levelRestriction(101376, 3041280)),
33
+ level(H264ProfileLevel::L20, levelRestriction(101376, 3041280)),
34
+ level(H264ProfileLevel::L21, levelRestriction(202752, 5068800)),
35
+ level(H264ProfileLevel::L22, levelRestriction(414720, 5184000)),
36
+ level(H264ProfileLevel::L30, levelRestriction(414720, 10368000)),
37
+ level(H264ProfileLevel::L31, levelRestriction(921600, 27648000)),
38
+ level(H264ProfileLevel::L32, levelRestriction(1310720, 55296000)),
39
+ //level(H264ProfileLevel::40, levelRestriction(2097152, 62914560)), // Technically identical to 4.1, but backwards compatible.
40
+ level(H264ProfileLevel::L41, levelRestriction(2097152, 62914560)),
41
+ level(H264ProfileLevel::L42, levelRestriction(2228224, 133693440)),
42
+ level(H264ProfileLevel::L50, levelRestriction(5652480, 150994944)),
43
+ level(H264ProfileLevel::L51, levelRestriction(9437184, 251658240)),
44
+ level(H264ProfileLevel::L52, levelRestriction(9437184, 530841600)),
45
+ level((H264ProfileLevel)-1, levelRestriction(0, 0))
46
};
47
48
uint32_t samples = frameSize.first * frameSize.second;
49
uint32_t samples_sec = (uint32_t)ceil((double_t)samples * ((double_t)frameRate.first / (double_t)frameRate.second));
50
51
level curLevel = profileLevelLimit[0];
52
- for (uint32_t index = 0; curLevel.first != -1; index++) {
53
+ for (uint32_t index = 0; (int32_t)curLevel.first != -1; index++) {
54
curLevel = profileLevelLimit[index];
55
56
if (samples > curLevel.second.first)
57
58
59
return curLevel.first;
60
}
61
- return VCEProfileLevel_52;
62
+ return H264ProfileLevel::L52;
63
}
64
65
#pragma region VCEEncoderType
66
- inline const char* VCEEncoderTypeAsString(VCEEncoderType type) {
67
+ inline const char* VCEEncoderTypeAsString(H264EncoderType type) {
68
const char* types[] = {
69
"AVC",
70
"SVC",
71
"HEVC"
72
};
73
- return types[type];
74
+ return types[(uint8_t)type];
75
}
76
- inline const wchar_t* VCEEncoderTypeAsAMF(VCEEncoderType type) {
77
+ inline const wchar_t* VCEEncoderTypeAsAMF(H264EncoderType type) {
78
const wchar_t* types[] = {
79
AMFVideoEncoderVCE_AVC,
80
AMFVideoEncoderVCE_SVC,
81
L"AMFVideoEncoderHW_HEVC"
82
};
83
- return types[type];
84
+ return types[(uint8_t)type];
85
}
86
#pragma endregion VCEEncoderType
87
#pragma region VCEMemoryType
88
- inline const char* MemoryTypeAsString(VCEMemoryType memoryType) {
89
+ inline const char* MemoryTypeAsString(H264MemoryType memoryType) {
90
static const char* memoryTypeToString[] = {
91
"Host",
92
"DirectX9",
93
"DirectX11",
94
"OpenGL"
95
};
96
- return memoryTypeToString[memoryType];
97
+ return memoryTypeToString[(uint8_t)memoryType];
98
}
99
- inline amf::AMF_MEMORY_TYPE MemoryTypeAsAMF(VCEMemoryType memoryType) {
100
+ inline amf::AMF_MEMORY_TYPE MemoryTypeAsAMF(H264MemoryType memoryType) {
101
static amf::AMF_MEMORY_TYPE memoryTypeToAMF[] = {
102
amf::AMF_MEMORY_HOST,
103
amf::AMF_MEMORY_DX9,
104
amf::AMF_MEMORY_DX11,
105
amf::AMF_MEMORY_OPENGL,
106
};
107
- return memoryTypeToAMF[memoryType];
108
+ return memoryTypeToAMF[(uint8_t)memoryType];
109
}
110
#pragma endregion VCEMemoryType
111
#pragma region VCESurfaceFormat
112
- inline const char* SurfaceFormatAsString(VCEColorFormat surfaceFormat) {
113
+ inline const char* SurfaceFormatAsString(H264ColorFormat surfaceFormat) {
114
static const char* surfaceFormatToString[] = {
115
"NV12",
116
"I420",
117
118
"RGBA",
119
"GRAY",
120
};
121
- return surfaceFormatToString[surfaceFormat];
122
+ return surfaceFormatToString[(uint8_t)surfaceFormat];
123
}
124
- inline amf::AMF_SURFACE_FORMAT SurfaceFormatAsAMF(VCEColorFormat surfaceFormat) {
125
+ inline amf::AMF_SURFACE_FORMAT SurfaceFormatAsAMF(H264ColorFormat surfaceFormat) {
126
static amf::AMF_SURFACE_FORMAT surfaceFormatToAMF[] = {
127
// 4:2:0 Formats
128
amf::AMF_SURFACE_NV12,
129
130
// Other
131
amf::AMF_SURFACE_GRAY8,
132
};
133
- return surfaceFormatToAMF[surfaceFormat];
134
+ return surfaceFormatToAMF[(uint8_t)surfaceFormat];
135
}
136
#pragma endregion VCESurfaceFormat
137
#pragma region VCEUsage
138
- inline const char* UsageAsString(VCEUsage usage) {
139
+ inline const char* UsageAsString(H264Usage usage) {
140
static const char* usageToString[] = {
141
"Transcoding",
142
"Ultra Low Latency",
143
"Low Latency",
144
"Webcam"
145
};
146
- return usageToString[usage];
147
+ return usageToString[(uint8_t)usage];
148
}
149
- inline AMF_VIDEO_ENCODER_USAGE_ENUM UsageAsAMF(VCEUsage usage) {
150
+ inline AMF_VIDEO_ENCODER_USAGE_ENUM UsageAsAMF(H264Usage usage) {
151
static AMF_VIDEO_ENCODER_USAGE_ENUM usageToAMF[] = {
152
AMF_VIDEO_ENCODER_USAGE_TRANSCONDING,
153
AMF_VIDEO_ENCODER_USAGE_ULTRA_LOW_LATENCY,
154
AMF_VIDEO_ENCODER_USAGE_LOW_LATENCY,
155
AMF_VIDEO_ENCODER_USAGE_WEBCAM,
156
};
157
- return usageToAMF[usage];
158
+ return usageToAMF[(uint8_t)usage];
159
}
160
- inline VCEUsage UsageFromAMF(uint32_t usage) {
161
- static VCEUsage usageFromAMF[] = {
162
- VCEUsage_Transcoding,
163
- VCEUsage_UltraLowLatency,
164
- VCEUsage_LowLatency,
165
- VCEUsage_Webcam,
166
+ inline H264Usage UsageFromAMF(uint32_t usage) {
167
+ static H264Usage usageFromAMF[] = {
168
+ H264Usage::Transcoding,
169
+ H264Usage::UltraLowLatency,
170
+ H264Usage::LowLatency,
171
+ H264Usage::Webcam,
172
};
173
- return usageFromAMF[usage];
174
+ return usageFromAMF[(uint8_t)usage];
175
}
176
#pragma endregion VCEUsage
177
#pragma region VCEQualityPreset
178
- inline const char* QualityPresetAsString(VCEQualityPreset preset) {
179
+ inline const char* QualityPresetAsString(H264QualityPreset preset) {
180
static const char* qualityPresetToString[] = {
181
"Speed",
182
"Balanced",
183
"Quality"
184
};
185
- return qualityPresetToString[preset];
186
+ return qualityPresetToString[(uint8_t)preset];
187
}
188
#pragma endregion VCEQualityPreset
189
#pragma region VCEProfile
190
- inline const char* ProfileAsString(VCEProfile profile) {
191
+ inline const char* ProfileAsString(H264Profile profile) {
192
switch (profile) {
193
- case VCEProfile_Baseline:
194
+ case H264Profile::Baseline:
195
return "Baseline";
196
- case VCEProfile_Main:
197
+ case H264Profile::Main:
198
return "Main";
199
- case VCEProfile_High:
200
+ case H264Profile::High:
201
return "High";
202
- case VCEProfile_ConstrainedBaseline:
203
+ case H264Profile::ConstrainedBaseline:
204
return "Constrained Baseline";
205
- case VCEProfile_ConstrainedHigh:
206
+ case H264Profile::ConstrainedHigh:
207
return "Constrained High";
208
}
209
210
211
}
212
#pragma endregion VCEProfile
213
#pragma region VCERateControlMethod
214
- inline const char* RateControlMethodAsString(VCERateControlMethod method) {
215
+ inline const char* RateControlMethodAsString(H264RateControlMethod method) {
216
static const char* rateControlMethodToString[] = {
217
"Constant Quantization Parameter (CQP)",
218
"Constant Bitrate (CBR)",
219
"Peak Constrained Variable Bitrate (VBR)",
220
"Latency Constrained Variable Bitrate (VBR_LAT)"
221
};
222
- return rateControlMethodToString[method];
223
+ return rateControlMethodToString[(uint8_t)method];
224
}
225
- inline AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_ENUM RateControlMethodAsAMF(VCERateControlMethod method) {
226
+ inline AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_ENUM RateControlMethodAsAMF(H264RateControlMethod method) {
227
static AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_ENUM CustomToAMF[] = {
228
AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP,
229
AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR,
230
AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR,
231
AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR,
232
};
233
- return CustomToAMF[method];
234
+ return CustomToAMF[(uint8_t)method];
235
}
236
- inline VCERateControlMethod RateControlMethodFromAMF(uint32_t method) {
237
- static VCERateControlMethod AMFToCustom[] = {
238
- VCERateControlMethod_ConstantQP,
239
- VCERateControlMethod_ConstantBitrate,
240
- VCERateControlMethod_VariableBitrate_PeakConstrained,
241
- VCERateControlMethod_VariableBitrate_LatencyConstrained,
242
+ inline H264RateControlMethod RateControlMethodFromAMF(uint32_t method) {
243
+ static H264RateControlMethod AMFToCustom[] = {
244
+ H264RateControlMethod::ConstantQP,
245
+ H264RateControlMethod::ConstantBitrate,
246
+ H264RateControlMethod::VariableBitrate_PeakConstrained,
247
+ H264RateControlMethod::VariableBitrate_LatencyConstrained,
248
};
249
- return AMFToCustom[method];
250
+ return AMFToCustom[(uint8_t)method];
251
}
252
#pragma endregion VCERateControlMethod
253
254
- inline const char* CodingTypeAsString(VCECodingType type) {
255
+ inline const char* CodingTypeAsString(H264CodingType type) {
256
switch (type) {
257
- case VCECodingType_CABAC:
258
+ case H264CodingType::CABAC:
259
return "CABAC";
260
- case VCECodingType_CALVC:
261
+ case H264CodingType::CALVC:
262
return "CALVC";
263
- case VCECodingType_Default:
264
+ case H264CodingType::Default:
265
return "Default";
266
}
267
return "MEMORY CORRUPTION";
268
}
269
- inline const char* SliceModeAsString(VCESliceMode mode) {
270
+ inline const char* SliceModeAsString(H264SliceMode mode) {
271
switch (mode) {
272
- case VCESliceMode_Horizontal:
273
+ case H264SliceMode::Horizontal:
274
return "Horizontal";
275
- case VCESliceMode_Vertical:
276
+ case H264SliceMode::Vertical:
277
return "Vertical";
278
}
279
return "MEMORY CORRUPTION";
280
}
281
- inline const char* SliceControlModeAsString(VCESliceControlMode mode) {
282
+ inline const char* SliceControlModeAsString(H264SliceControlMode mode) {
283
switch (mode) {
284
- case VCESliceControlMode_Off:
285
+ case H264SliceControlMode::Off:
286
return "Off";
287
- case VCESliceControlMode_Macroblock:
288
+ case H264SliceControlMode::Macroblock:
289
return "Macroblock";
290
- case VCESliceControlMode_Macroblock_Row:
291
+ case H264SliceControlMode::Macroblock_Row:
292
return "Macroblock Row";
293
}
294
return "MEMORY CORRUPTION";
295
obs-studio-0.17.0.tar.xz/plugins/image-source/data/locale/tr-TR.ini -> obs-studio-17.0.1.tar.xz/plugins/image-source/data/locale/tr-TR.ini
Changed
9
1
2
SlideShow.TransitionSpeed="Geçiş Hızı (milisaniye)"
3
SlideShow.SlideTime="Slaytlar Arası Süre (milisaniye)"
4
SlideShow.Files="Görüntü Dosyaları"
5
+SlideShow.Randomize="Rastgele Gösterim"
6
SlideShow.Transition="Geçiş"
7
SlideShow.Transition.Cut="Cut"
8
SlideShow.Transition.Fade="Fade"
9
obs-studio-0.17.0.tar.xz/plugins/linux-capture/data/locale/tr-TR.ini -> obs-studio-17.0.1.tar.xz/plugins/linux-capture/data/locale/tr-TR.ini
Changed
7
1
2
SwapRedBlue="Kırmızı ve maviyi değiştir"
3
LockX="Yakalama sırasında X sunucusunu kilitle"
4
IncludeXBorder="X Çerçevesini Dahil Et"
5
+ExcludeAlpha="Alpha kanalı olmayan doku biçimi kullan (Mesa geçici çözüm)"
6
7
obs-studio-0.17.0.tar.xz/plugins/mac-capture/data/locale/hu-HU.ini -> obs-studio-17.0.1.tar.xz/plugins/mac-capture/data/locale/hu-HU.ini
Changed
8
1
2
CoreAudio.InputCapture="Bemeneti hangrögzítés"
3
-CoreAudio.OutputCapture="Kimeneti hangrögzítés"
4
+CoreAudio.OutputCapture="Kimeneti hangrögzítő"
5
CoreAudio.Device="Eszköz"
6
CoreAudio.Device.Default="Alapértelmezett"
7
DisplayCapture="Kijelző felvétel"
8
obs-studio-0.17.0.tar.xz/plugins/mac-vth264/data/locale/hu-HU.ini -> obs-studio-17.0.1.tar.xz/plugins/mac-vth264/data/locale/hu-HU.ini
Changed
16
1
2
VTH264EncHW="Apple VT H264 hardveres kódoló"
3
VTH264EncSW="Apple VT H264 szoftveres kódoló"
4
VTEncoder="VideoToolbox H264 kódoló"
5
-Bitrate="Bitráta"
6
-UseMaxBitrate="Bitráta limit"
7
-MaxBitrate="Maximális bitráta"
8
-MaxBitrateWindow="Maximális bitrátaablak (másodperc)"
9
+Bitrate="Bitsebesség"
10
+UseMaxBitrate="Bitsebesség limit"
11
+MaxBitrate="Maximális bitsebesség"
12
+MaxBitrateWindow="Maximális bitsebességablak (másodperc)"
13
KeyframeIntervalSec="Kulcsképkocka időköze (másodperc, 0=auto)"
14
Profile="Profil"
15
None="(Nincs)"
16
obs-studio-0.17.0.tar.xz/plugins/mac-vth264/data/locale/tr-TR.ini -> obs-studio-17.0.1.tar.xz/plugins/mac-vth264/data/locale/tr-TR.ini
Changed
14
1
2
VTH264EncSW="Apple VT H264 Yazılım Kodlayıcı"
3
VTEncoder="VideoToolbox Kodlayıcı"
4
Bitrate="Bithızı"
5
+UseMaxBitrate="Bit hızını sınırla"
6
MaxBitrate="Maks bit hızı"
7
KeyframeIntervalSec="Anahtarkare Aralığı (saniye, 0=otomatik)"
8
Profile="Profil"
9
None="(Yok)"
10
DefaultEncoder="(Varsayılan Kodlayıcı)"
11
+UseBFrames="B-Frame kullan"
12
13
14
obs-studio-0.17.0.tar.xz/plugins/obs-browser/CMakeLists.txt -> obs-studio-17.0.1.tar.xz/plugins/obs-browser/CMakeLists.txt
Changed
171
1
2
obs-browser/main.cpp
3
obs-browser/main-source.cpp
4
shared/browser-source.cpp
5
- shared/base64.cpp)
6
+ shared/base64.cpp
7
+ shared/util.cpp)
8
9
set(obs-browser_HEADERS
10
shared/browser-manager.hpp
11
12
shared/browser-types.h
13
shared/base64.hpp
14
shared/browser-types.h
15
- shared/browser-version.h)
16
+ shared/browser-version.h
17
+ shared/util.hpp)
18
19
if (APPLE)
20
list(APPEND obs-browser_SOURCES
21
22
obs-browser/browser-render-handler.cpp
23
obs-browser/browser-source-base.cpp
24
obs-browser/browser-load-handler.cpp
25
- shared/browser-scheme.cpp)
26
+ obs-browser/browser-obs-bridge-base.cpp
27
+ shared/browser-scheme.cpp
28
+ fmt/format.cc)
29
30
list(APPEND obs-browser_HEADERS
31
shared/browser-client.hpp
32
33
obs-browser/browser-render-handler.hpp
34
obs-browser/browser-source-base.hpp
35
obs-browser/browser-load-handler.hpp
36
- shared/browser-scheme.hpp)
37
+ obs-browser/browser-obs-bridge-base.hpp
38
+ shared/browser-scheme.hpp
39
+ fmt/format.h)
40
41
endif(APPLE)
42
43
set(obs-browser_LIBRARIES
44
- libobs
45
- obs-frontend-api)
46
+ obs-frontend-api
47
+ ${OBS_JANSSON_IMPORT})
48
49
if (APPLE)
50
list(APPEND obs-browser_LIBRARIES
51
52
"obs-browser"
53
"shared")
54
55
+target_include_directories(obs-browser PUBLIC
56
+ ${OBS_JANSSON_INCLUDE_DIRS})
57
+
58
if (APPLE)
59
target_include_directories(obs-browser PUBLIC
60
"shared-apple")
61
-else(APPLE)
62
- target_include_directories_system(obs-browser PUBLIC ${CEF_INCLUDE_DIR})
63
+else (APPLE)
64
+ target_include_directories_system(obs-browser PUBLIC ${CEF_ROOT_DIR})
65
endif(APPLE)
66
67
+
68
if (APPLE)
69
set_xcode_property(obs-browser CLANG_CXX_LIBRARY "libc++")
70
endif(APPLE)
71
72
set(cef-isolation_SOURCES
73
cef-isolation/main.mm
74
cef-isolation/cef-isolated-client.mm
75
+ cef-isolation/browser-obs-bridge-mac.mm
76
cef-isolation/browser-handle.mm
77
cef-isolation/browser-render-handler.mm
78
cef-isolation/browser-texture-mac.mm
79
80
shared/browser-app.cpp
81
shared/browser-scheme.cpp
82
shared/base64.cpp
83
- obs-browser/browser-load-handler.cpp)
84
+ obs-browser/browser-load-handler.cpp
85
+ fmt/format.cc)
86
87
set(cef-isolation_HEADERS
88
shared-apple/cef-logging.h
89
90
cef-isolation/browser-render-handler.hpp
91
cef-isolation/browser-texture-mac.h
92
cef-isolation/service-connection-delegate.h
93
+ cef-isolation/browser-obs-bridge-mac.hpp
94
shared/browser-texture.hpp
95
shared/browser-client.hpp
96
shared/browser-task.hpp
97
98
obs-browser/browser-load-handler.hpp
99
shared/browser-scheme.hpp
100
shared/browser-types.h
101
+ shared/browser-obs-bridge.hpp
102
shared-apple/browser-bridges.h)
103
104
add_executable(cef-isolation
105
106
"shared"
107
"shared-apple")
108
109
- target_include_directories_system(cef-isolation PUBLIC ${CEF_INCLUDE_DIR})
110
+ target_include_directories_system(cef-isolation
111
+ PUBLIC
112
+ ${CEF_INCLUDE_DIR}
113
+ ${OBS_JANSSON_INCLUDE_DIRS})
114
115
target_link_libraries(cef-isolation
116
${CEF_LIBRARIES}
117
+ ${OBS_JANSSON_IMPORT}
118
${APPKIT_FRAMEWORK}
119
${IOSURFACE_FRAMEWORK})
120
121
122
123
set(cef-bootstrap_SOURCES
124
cef-bootstrap/main.cpp
125
- shared/browser-app.cpp)
126
+ shared/browser-app.cpp
127
+ fmt/format.cc)
128
129
set(cef-bootstrap_HEADERS
130
- shared/browser-app.hpp)
131
+ shared/browser-app.hpp
132
+ fmt/format.h)
133
134
add_executable(cef-bootstrap
135
${cef-bootstrap_SOURCES}
136
137
endif(APPLE AND XCODE)
138
139
target_include_directories(cef-bootstrap PRIVATE "shared")
140
-target_include_directories_system(cef-bootstrap PUBLIC ${CEF_INCLUDE_DIR})
141
+target_include_directories_system(cef-bootstrap
142
+ PUBLIC
143
+ ${CEF_ROOT_DIR}
144
+ ${OBS_JANSSON_INCLUDE_DIRS})
145
146
target_link_libraries(cef-bootstrap
147
- ${CEF_LIBRARIES})
148
+ ${CEF_LIBRARIES}
149
+ ${OBS_JANSSON_IMPORT})
150
151
if (APPLE)
152
153
154
OUTPUT_NAME "CEF"
155
MACOSX_BUNDLE TRUE
156
BUILD_WITH_INSTALL_RPATH TRUE
157
- INSTALL_RPATH "@loader_path/../Frameworks"
158
+ INSTALL_RPATH "@executable_path/.."
159
MACOSX_BUNDLE_BUNDLE_NAME "CEF Helper"
160
MACOSX_BUNDLE_GUI_IDENTIFIER "org.catchexception.cef.cef-isolation")
161
162
163
OUTPUT_NAME "CEF Helper"
164
MACOSX_BUNDLE TRUE
165
BUILD_WITH_INSTALL_RPATH TRUE
166
- INSTALL_RPATH "@loader_path/../../../"
167
+ INSTALL_RPATH "@executable_path/../../../.."
168
MACOSX_BUNDLE_BUNDLE_NAME "CEF Helper"
169
MACOSX_BUNDLE_GUI_IDENTIFIER "org.catchexception.cef.cef-bootstrap")
170
171
obs-studio-0.17.0.tar.xz/plugins/obs-browser/FindCEF.cmake -> obs-studio-17.0.1.tar.xz/plugins/obs-browser/FindCEF.cmake
Changed
10
1
2
3
find_library(CEFWRAPPER_LIBRARY
4
NAMES cef_dll_wrapper libcef_dll_wrapper
5
- PATHS ${CEF_ROOT_DIR}/build/libcef_dll)
6
+ PATHS ${CEF_ROOT_DIR}/build/libcef_dll ${CEF_ROOT_DIR}/build/libcef_dll_wrapper)
7
8
if (NOT CEF_LIBRARY)
9
message(FATAL_ERROR "Could not find the CEF shared library" )
10
obs-studio-0.17.0.tar.xz/plugins/obs-browser/README.md -> obs-studio-17.0.1.tar.xz/plugins/obs-browser/README.md
Changed
52
1
2
3
### Register for scene change callbacks
4
```
5
-/**
6
- * onSceneChange gets callbacks when the scene is changed
7
- *
8
- * @param {string} sceneName - The name of the scene that was changed to.
9
- */
10
-window.obsstudio.onSceneChange = function(sceneName) {
11
-
12
-};
13
+window.addEventListener('obsSceneChanged', function(evt) {
14
+ var t = document.createTextNode(evt.detail.name);
15
+ document.body.appendChild(t);
16
+});
17
+```
18
+#### Other events that are available
19
+* obsStreamingStarting
20
+* obsStreamingStarted
21
+* obsStreamingStopping
22
+* obsStreamingStopped
23
+* obsRecordingStarting
24
+* obsRecordingStarted
25
+* obsRecordingStopping
26
+* obsRecordingStopped
27
+
28
+### Get the current scene
29
+```
30
+window.obsstudio.getCurrentScene(function(data) {console.log(data);});
31
```
32
33
## Building on OSX
34
35
### Building CEF
36
#### Getting
37
* Download CEF Mac 64 from [https://cefbuilds.com/](https://cefbuilds.com/)
38
- * At the time of writing this I used build 2704
39
+ * At the time of writing this I used build 2883
40
* Extract and cd into the folder
41
42
#### Setting Up Project
43
44
echo "add_subdirectory(obs-browser)" >> ./plugins/CMakeLists.txt
45
mkdir build
46
cd ./build
47
-cmake -D CMAKE_PREFIX_PATH=/usr/local/opt/qt5/lib/cmake -D CEF_ROOT_DIR=/Users/username/Development/cef_binary_3.2704.1434.gec3e9ed_macosx64 -G Xcode ..
48
+cmake -D CMAKE_PREFIX_PATH=/usr/local/opt/qt5/lib/cmake -D CEF_ROOT_DIR=/Users/username/Development/cef_binary_3.2883.1540.gedbfb20_macosx64 -D BUILD_BROWSER=yes -G Xcode ..
49
open obs-studio.xcodeproj/
50
```
51
52
obs-studio-17.0.1.tar.xz/plugins/obs-browser/cef-isolation/browser-obs-bridge-mac.hpp
Added
17
1
2
+#pragma once
3
+
4
+#include "cef-isolation.h"
5
+#include "browser-obs-bridge.hpp"
6
+
7
+class BrowserOBSBridgeMac : public BrowserOBSBridge
8
+{
9
+public:
10
+ BrowserOBSBridgeMac(id<CEFIsolationService> cefIsolationService);
11
+
12
+ const char* GetCurrentSceneJSONData() override;
13
+
14
+private:
15
+ id<CEFIsolationService> cefIsolationService;
16
+};
17
obs-studio-17.0.1.tar.xz/plugins/obs-browser/cef-isolation/browser-obs-bridge-mac.mm
Added
12
1
2
+#include "browser-obs-bridge-mac.hpp"
3
+
4
+BrowserOBSBridgeMac::BrowserOBSBridgeMac(id<CEFIsolationService> cefIsolationService)
5
+: cefIsolationService(cefIsolationService)
6
+{}
7
+
8
+const char* BrowserOBSBridgeMac::GetCurrentSceneJSONData()
9
+{
10
+ return [cefIsolationService getCurrentSceneJSONData];
11
+}
12
obs-studio-0.17.0.tar.xz/plugins/obs-browser/cef-isolation/browser-render-handler.hpp -> obs-studio-17.0.1.tar.xz/plugins/obs-browser/cef-isolation/browser-render-handler.hpp
Changed
9
1
2
3
BrowserRenderHandler(std::shared_ptr<BrowserHandle> &browserHandle);
4
5
-
6
public: /* CefRenderHandler overrides */
7
8
virtual bool GetViewRect(CefRefPtr<CefBrowser> browser, CefRect &rect)
9
obs-studio-0.17.0.tar.xz/plugins/obs-browser/cef-isolation/cef-isolated-client.mm -> obs-studio-17.0.1.tar.xz/plugins/obs-browser/cef-isolation/cef-isolated-client.mm
Changed
72
1
2
******************************************************************************/
3
4
#import <Cocoa/Cocoa.h>
5
+#import <Foundation/Foundation.h>
6
7
#include <include/cef_app.h>
8
#include <include/cef_browser.h>
9
10
11
#import "cef-isolated-client.h"
12
13
+#import "browser-obs-bridge-mac.hpp"
14
+
15
@implementation CEFIsolatedClient
16
17
- (id)init
18
19
new BrowserHandle(browserSettings.width,
20
browserSettings.height, _server));
21
22
+ BrowserOBSBridge *browserOBSBridge = new BrowserOBSBridgeMac(_server);
23
+
24
sync_on_cef_ui(^{
25
26
CefRefPtr<BrowserRenderHandler> browserRenderHandler =
27
28
new BrowserLoadHandler(std::string([browserSettings.css UTF8String]));
29
30
CefRefPtr<BrowserClient> browserClient =
31
- new BrowserClient(browserRenderHandler.get(),loadHandler);
32
+ new BrowserClient(browserRenderHandler.get(),loadHandler, browserOBSBridge);
33
34
CefWindowInfo windowInfo;
35
windowInfo.view = nullptr;
36
37
return;
38
}
39
40
- host->HandleKeyEventBeforeTextInputClient(nsEvent);
41
-
42
- NSTextInputContext *inputContext =
43
- host->GetNSTextInputContext();
44
- [inputContext handleEvent:nsEvent];
45
-
46
- host->HandleKeyEventAfterTextInputClient(nsEvent);
47
+ host->SendKeyEvent(keyEvent);
48
}
49
}];
50
}
51
52
}];
53
}
54
55
+-(void)dispatchJSEvent:(const char *)eventName data:(const char *)jsonString
56
+{
57
+ [self sendEventToAllBrowsers:^(SharedBrowserHandle browserHandle)
58
+ {
59
+ CefRefPtr<CefBrowser> browser = browserHandle->GetBrowser();
60
+
61
+ CefRefPtr<CefProcessMessage> msg = CefProcessMessage::Create("DispatchJSEvent");
62
+ CefRefPtr<CefListValue> args = msg->GetArgumentList();
63
+ args->SetString(0, eventName);
64
+ args->SetString(1, jsonString);
65
66
+ browser->SendProcessMessage(PID_RENDERER, msg);
67
+ }];
68
+}
69
70
- (void)destroyBrowser:(const int)browserIdentifier {
71
if (map.count(browserIdentifier) == 1) {
72
obs-studio-17.0.1.tar.xz/plugins/obs-browser/fmt
Added
2
1
+(directory)
2
obs-studio-17.0.1.tar.xz/plugins/obs-browser/fmt/format.cc
Added
937
1
2
+/*
3
+ Formatting library for C++
4
+
5
+ Copyright (c) 2012 - 2016, Victor Zverovich
6
+ All rights reserved.
7
+
8
+ Redistribution and use in source and binary forms, with or without
9
+ modification, are permitted provided that the following conditions are met:
10
+
11
+ 1. Redistributions of source code must retain the above copyright notice, this
12
+ list of conditions and the following disclaimer.
13
+ 2. Redistributions in binary form must reproduce the above copyright notice,
14
+ this list of conditions and the following disclaimer in the documentation
15
+ and/or other materials provided with the distribution.
16
+
17
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ */
28
+
29
+#include "format.h"
30
+
31
+#include <string.h>
32
+
33
+#include <cctype>
34
+#include <cerrno>
35
+#include <climits>
36
+#include <cmath>
37
+#include <cstdarg>
38
+#include <cstddef> // for std::ptrdiff_t
39
+
40
+#if defined(_WIN32) && defined(__MINGW32__)
41
+# include <cstring>
42
+#endif
43
+
44
+#if FMT_USE_WINDOWS_H
45
+# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
46
+# include <windows.h>
47
+# else
48
+# define NOMINMAX
49
+# include <windows.h>
50
+# undef NOMINMAX
51
+# endif
52
+#endif
53
+
54
+using fmt::internal::Arg;
55
+
56
+#if FMT_EXCEPTIONS
57
+# define FMT_TRY try
58
+# define FMT_CATCH(x) catch (x)
59
+#else
60
+# define FMT_TRY if (true)
61
+# define FMT_CATCH(x) if (false)
62
+#endif
63
+
64
+#ifdef _MSC_VER
65
+# pragma warning(push)
66
+# pragma warning(disable: 4127) // conditional expression is constant
67
+# pragma warning(disable: 4702) // unreachable code
68
+// Disable deprecation warning for strerror. The latter is not called but
69
+// MSVC fails to detect it.
70
+# pragma warning(disable: 4996)
71
+#endif
72
+
73
+// Dummy implementations of strerror_r and strerror_s called if corresponding
74
+// system functions are not available.
75
+static inline fmt::internal::Null<> strerror_r(int, char *, ...) {
76
+ return fmt::internal::Null<>();
77
+}
78
+static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) {
79
+ return fmt::internal::Null<>();
80
+}
81
+
82
+namespace fmt {
83
+namespace {
84
+
85
+#ifndef _MSC_VER
86
+# define FMT_SNPRINTF snprintf
87
+#else // _MSC_VER
88
+inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
89
+ va_list args;
90
+ va_start(args, format);
91
+ int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
92
+ va_end(args);
93
+ return result;
94
+}
95
+# define FMT_SNPRINTF fmt_snprintf
96
+#endif // _MSC_VER
97
+
98
+#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
99
+# define FMT_SWPRINTF snwprintf
100
+#else
101
+# define FMT_SWPRINTF swprintf
102
+#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
103
+
104
+// Checks if a value fits in int - used to avoid warnings about comparing
105
+// signed and unsigned integers.
106
+template <bool IsSigned>
107
+struct IntChecker {
108
+ template <typename T>
109
+ static bool fits_in_int(T value) {
110
+ unsigned max = INT_MAX;
111
+ return value <= max;
112
+ }
113
+ static bool fits_in_int(bool) { return true; }
114
+};
115
+
116
+template <>
117
+struct IntChecker<true> {
118
+ template <typename T>
119
+ static bool fits_in_int(T value) {
120
+ return value >= INT_MIN && value <= INT_MAX;
121
+ }
122
+ static bool fits_in_int(int) { return true; }
123
+};
124
+
125
+const char RESET_COLOR[] = "\x1b[0m";
126
+
127
+typedef void (*FormatFunc)(Writer &, int, StringRef);
128
+
129
+// Portable thread-safe version of strerror.
130
+// Sets buffer to point to a string describing the error code.
131
+// This can be either a pointer to a string stored in buffer,
132
+// or a pointer to some static immutable string.
133
+// Returns one of the following values:
134
+// 0 - success
135
+// ERANGE - buffer is not large enough to store the error message
136
+// other - failure
137
+// Buffer should be at least of size 1.
138
+int safe_strerror(
139
+ int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
140
+ FMT_ASSERT(buffer != 0 && buffer_size != 0, "invalid buffer");
141
+
142
+ class StrError {
143
+ private:
144
+ int error_code_;
145
+ char *&buffer_;
146
+ std::size_t buffer_size_;
147
+
148
+ // A noop assignment operator to avoid bogus warnings.
149
+ void operator=(const StrError &) {}
150
+
151
+ // Handle the result of XSI-compliant version of strerror_r.
152
+ int handle(int result) {
153
+ // glibc versions before 2.13 return result in errno.
154
+ return result == -1 ? errno : result;
155
+ }
156
+
157
+ // Handle the result of GNU-specific version of strerror_r.
158
+ int handle(char *message) {
159
+ // If the buffer is full then the message is probably truncated.
160
+ if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)
161
+ return ERANGE;
162
+ buffer_ = message;
163
+ return 0;
164
+ }
165
+
166
+ // Handle the case when strerror_r is not available.
167
+ int handle(internal::Null<>) {
168
+ return fallback(strerror_s(buffer_, buffer_size_, error_code_));
169
+ }
170
+
171
+ // Fallback to strerror_s when strerror_r is not available.
172
+ int fallback(int result) {
173
+ // If the buffer is full then the message is probably truncated.
174
+ return result == 0 && strlen(buffer_) == buffer_size_ - 1 ?
175
+ ERANGE : result;
176
+ }
177
+
178
+ // Fallback to strerror if strerror_r and strerror_s are not available.
179
+ int fallback(internal::Null<>) {
180
+ errno = 0;
181
+ buffer_ = strerror(error_code_);
182
+ return errno;
183
+ }
184
+
185
+ public:
186
+ StrError(int err_code, char *&buf, std::size_t buf_size)
187
+ : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
188
+
189
+ int run() {
190
+ strerror_r(0, 0, ""); // Suppress a warning about unused strerror_r.
191
+ return handle(strerror_r(error_code_, buffer_, buffer_size_));
192
+ }
193
+ };
194
+ return StrError(error_code, buffer, buffer_size).run();
195
+}
196
+
197
+void format_error_code(Writer &out, int error_code,
198
+ StringRef message) FMT_NOEXCEPT {
199
+ // Report error code making sure that the output fits into
200
+ // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
201
+ // bad_alloc.
202
+ out.clear();
203
+ static const char SEP[] = ": ";
204
+ static const char ERROR_STR[] = "error ";
205
+ // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
206
+ std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
207
+ typedef internal::IntTraits<int>::MainType MainType;
208
+ MainType abs_value = static_cast<MainType>(error_code);
209
+ if (internal::is_negative(error_code)) {
210
+ abs_value = 0 - abs_value;
211
+ ++error_code_size;
212
+ }
213
+ error_code_size += internal::count_digits(abs_value);
214
+ if (message.size() <= internal::INLINE_BUFFER_SIZE - error_code_size)
215
+ out << message << SEP;
216
+ out << ERROR_STR << error_code;
217
+ assert(out.size() <= internal::INLINE_BUFFER_SIZE);
218
+}
219
+
220
+void report_error(FormatFunc func, int error_code,
221
+ StringRef message) FMT_NOEXCEPT {
222
+ MemoryWriter full_message;
223
+ func(full_message, error_code, message);
224
+ // Use Writer::data instead of Writer::c_str to avoid potential memory
225
+ // allocation.
226
+ std::fwrite(full_message.data(), full_message.size(), 1, stderr);
227
+ std::fputc('\n', stderr);
228
+}
229
+
230
+// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
231
+class IsZeroInt : public ArgVisitor<IsZeroInt, bool> {
232
+ public:
233
+ template <typename T>
234
+ bool visit_any_int(T value) { return value == 0; }
235
+};
236
+
237
+// Checks if an argument is a valid printf width specifier and sets
238
+// left alignment if it is negative.
239
+class WidthHandler : public ArgVisitor<WidthHandler, unsigned> {
240
+ private:
241
+ FormatSpec &spec_;
242
+
243
+ FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler);
244
+
245
+ public:
246
+ explicit WidthHandler(FormatSpec &spec) : spec_(spec) {}
247
+
248
+ void report_unhandled_arg() {
249
+ FMT_THROW(FormatError("width is not integer"));
250
+ }
251
+
252
+ template <typename T>
253
+ unsigned visit_any_int(T value) {
254
+ typedef typename internal::IntTraits<T>::MainType UnsignedType;
255
+ UnsignedType width = static_cast<UnsignedType>(value);
256
+ if (internal::is_negative(value)) {
257
+ spec_.align_ = ALIGN_LEFT;
258
+ width = 0 - width;
259
+ }
260
+ if (width > INT_MAX)
261
+ FMT_THROW(FormatError("number is too big"));
262
+ return static_cast<unsigned>(width);
263
+ }
264
+};
265
+
266
+class PrecisionHandler : public ArgVisitor<PrecisionHandler, int> {
267
+ public:
268
+ void report_unhandled_arg() {
269
+ FMT_THROW(FormatError("precision is not integer"));
270
+ }
271
+
272
+ template <typename T>
273
+ int visit_any_int(T value) {
274
+ if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
275
+ FMT_THROW(FormatError("number is too big"));
276
+ return static_cast<int>(value);
277
+ }
278
+};
279
+
280
+template <typename T, typename U>
281
+struct is_same {
282
+ enum { value = 0 };
283
+};
284
+
285
+template <typename T>
286
+struct is_same<T, T> {
287
+ enum { value = 1 };
288
+};
289
+
290
+// An argument visitor that converts an integer argument to T for printf,
291
+// if T is an integral type. If T is void, the argument is converted to
292
+// corresponding signed or unsigned type depending on the type specifier:
293
+// 'd' and 'i' - signed, other - unsigned)
294
+template <typename T = void>
295
+class ArgConverter : public ArgVisitor<ArgConverter<T>, void> {
296
+ private:
297
+ internal::Arg &arg_;
298
+ wchar_t type_;
299
+
300
+ FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter);
301
+
302
+ public:
303
+ ArgConverter(internal::Arg &arg, wchar_t type)
304
+ : arg_(arg), type_(type) {}
305
+
306
+ void visit_bool(bool value) {
307
+ if (type_ != 's')
308
+ visit_any_int(value);
309
+ }
310
+
311
+ template <typename U>
312
+ void visit_any_int(U value) {
313
+ bool is_signed = type_ == 'd' || type_ == 'i';
314
+ using internal::Arg;
315
+ typedef typename internal::Conditional<
316
+ is_same<T, void>::value, U, T>::type TargetType;
317
+ if (sizeof(TargetType) <= sizeof(int)) {
318
+ // Extra casts are used to silence warnings.
319
+ if (is_signed) {
320
+ arg_.type = Arg::INT;
321
+ arg_.int_value = static_cast<int>(static_cast<TargetType>(value));
322
+ } else {
323
+ arg_.type = Arg::UINT;
324
+ typedef typename internal::MakeUnsigned<TargetType>::Type Unsigned;
325
+ arg_.uint_value = static_cast<unsigned>(static_cast<Unsigned>(value));
326
+ }
327
+ } else {
328
+ if (is_signed) {
329
+ arg_.type = Arg::LONG_LONG;
330
+ // glibc's printf doesn't sign extend arguments of smaller types:
331
+ // std::printf("%lld", -42); // prints "4294967254"
332
+ // but we don't have to do the same because it's a UB.
333
+ arg_.long_long_value = static_cast<LongLong>(value);
334
+ } else {
335
+ arg_.type = Arg::ULONG_LONG;
336
+ arg_.ulong_long_value =
337
+ static_cast<typename internal::MakeUnsigned<U>::Type>(value);
338
+ }
339
+ }
340
+ }
341
+};
342
+
343
+// Converts an integer argument to char for printf.
344
+class CharConverter : public ArgVisitor<CharConverter, void> {
345
+ private:
346
+ internal::Arg &arg_;
347
+
348
+ FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter);
349
+
350
+ public:
351
+ explicit CharConverter(internal::Arg &arg) : arg_(arg) {}
352
+
353
+ template <typename T>
354
+ void visit_any_int(T value) {
355
+ arg_.type = internal::Arg::CHAR;
356
+ arg_.int_value = static_cast<char>(value);
357
+ }
358
+};
359
+} // namespace
360
+
361
+namespace internal {
362
+
363
+template <typename Char>
364
+class PrintfArgFormatter :
365
+ public ArgFormatterBase<PrintfArgFormatter<Char>, Char> {
366
+
367
+ void write_null_pointer() {
368
+ this->spec().type_ = 0;
369
+ this->write("(nil)");
370
+ }
371
+
372
+ typedef ArgFormatterBase<PrintfArgFormatter<Char>, Char> Base;
373
+
374
+ public:
375
+ PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
376
+ : ArgFormatterBase<PrintfArgFormatter<Char>, Char>(w, s) {}
377
+
378
+ void visit_bool(bool value) {
379
+ FormatSpec &fmt_spec = this->spec();
380
+ if (fmt_spec.type_ != 's')
381
+ return this->visit_any_int(value);
382
+ fmt_spec.type_ = 0;
383
+ this->write(value);
384
+ }
385
+
386
+ void visit_char(int value) {
387
+ const FormatSpec &fmt_spec = this->spec();
388
+ BasicWriter<Char> &w = this->writer();
389
+ if (fmt_spec.type_ && fmt_spec.type_ != 'c')
390
+ w.write_int(value, fmt_spec);
391
+ typedef typename BasicWriter<Char>::CharPtr CharPtr;
392
+ CharPtr out = CharPtr();
393
+ if (fmt_spec.width_ > 1) {
394
+ Char fill = ' ';
395
+ out = w.grow_buffer(fmt_spec.width_);
396
+ if (fmt_spec.align_ != ALIGN_LEFT) {
397
+ std::fill_n(out, fmt_spec.width_ - 1, fill);
398
+ out += fmt_spec.width_ - 1;
399
+ } else {
400
+ std::fill_n(out + 1, fmt_spec.width_ - 1, fill);
401
+ }
402
+ } else {
403
+ out = w.grow_buffer(1);
404
+ }
405
+ *out = static_cast<Char>(value);
406
+ }
407
+
408
+ void visit_cstring(const char *value) {
409
+ if (value)
410
+ Base::visit_cstring(value);
411
+ else if (this->spec().type_ == 'p')
412
+ write_null_pointer();
413
+ else
414
+ this->write("(null)");
415
+ }
416
+
417
+ void visit_pointer(const void *value) {
418
+ if (value)
419
+ return Base::visit_pointer(value);
420
+ this->spec().type_ = 0;
421
+ write_null_pointer();
422
+ }
423
+
424
+ void visit_custom(Arg::CustomValue c) {
425
+ BasicFormatter<Char> formatter(ArgList(), this->writer());
426
+ const Char format_str[] = {'}', 0};
427
+ const Char *format = format_str;
428
+ c.format(&formatter, c.value, &format);
429
+ }
430
+};
431
+} // namespace internal
432
+} // namespace fmt
433
+
434
+FMT_FUNC void fmt::SystemError::init(
435
+ int err_code, CStringRef format_str, ArgList args) {
436
+ error_code_ = err_code;
437
+ MemoryWriter w;
438
+ internal::format_system_error(w, err_code, format(format_str, args));
439
+ std::runtime_error &base = *this;
440
+ base = std::runtime_error(w.str());
441
+}
442
+
443
+template <typename T>
444
+int fmt::internal::CharTraits<char>::format_float(
445
+ char *buffer, std::size_t size, const char *format,
446
+ unsigned width, int precision, T value) {
447
+ if (width == 0) {
448
+ return precision < 0 ?
449
+ FMT_SNPRINTF(buffer, size, format, value) :
450
+ FMT_SNPRINTF(buffer, size, format, precision, value);
451
+ }
452
+ return precision < 0 ?
453
+ FMT_SNPRINTF(buffer, size, format, width, value) :
454
+ FMT_SNPRINTF(buffer, size, format, width, precision, value);
455
+}
456
+
457
+template <typename T>
458
+int fmt::internal::CharTraits<wchar_t>::format_float(
459
+ wchar_t *buffer, std::size_t size, const wchar_t *format,
460
+ unsigned width, int precision, T value) {
461
+ if (width == 0) {
462
+ return precision < 0 ?
463
+ FMT_SWPRINTF(buffer, size, format, value) :
464
+ FMT_SWPRINTF(buffer, size, format, precision, value);
465
+ }
466
+ return precision < 0 ?
467
+ FMT_SWPRINTF(buffer, size, format, width, value) :
468
+ FMT_SWPRINTF(buffer, size, format, width, precision, value);
469
+}
470
+
471
+template <typename T>
472
+const char fmt::internal::BasicData<T>::DIGITS[] =
473
+ "0001020304050607080910111213141516171819"
474
+ "2021222324252627282930313233343536373839"
475
+ "4041424344454647484950515253545556575859"
476
+ "6061626364656667686970717273747576777879"
477
+ "8081828384858687888990919293949596979899";
478
+
479
+#define FMT_POWERS_OF_10(factor) \
480
+ factor * 10, \
481
+ factor * 100, \
482
+ factor * 1000, \
483
+ factor * 10000, \
484
+ factor * 100000, \
485
+ factor * 1000000, \
486
+ factor * 10000000, \
487
+ factor * 100000000, \
488
+ factor * 1000000000
489
+
490
+template <typename T>
491
+const uint32_t fmt::internal::BasicData<T>::POWERS_OF_10_32[] = {
492
+ 0, FMT_POWERS_OF_10(1)
493
+};
494
+
495
+template <typename T>
496
+const uint64_t fmt::internal::BasicData<T>::POWERS_OF_10_64[] = {
497
+ 0,
498
+ FMT_POWERS_OF_10(1),
499
+ FMT_POWERS_OF_10(fmt::ULongLong(1000000000)),
500
+ // Multiply several constants instead of using a single long long constant
501
+ // to avoid warnings about C++98 not supporting long long.
502
+ fmt::ULongLong(1000000000) * fmt::ULongLong(1000000000) * 10
503
+};
504
+
505
+FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) {
506
+ (void)type;
507
+ if (std::isprint(static_cast<unsigned char>(code))) {
508
+ FMT_THROW(fmt::FormatError(
509
+ fmt::format("unknown format code '{}' for {}", code, type)));
510
+ }
511
+ FMT_THROW(fmt::FormatError(
512
+ fmt::format("unknown format code '\\x{:02x}' for {}",
513
+ static_cast<unsigned>(code), type)));
514
+}
515
+
516
+#if FMT_USE_WINDOWS_H
517
+
518
+FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
519
+ static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
520
+ if (s.size() > INT_MAX)
521
+ FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG));
522
+ int s_size = static_cast<int>(s.size());
523
+ int length = MultiByteToWideChar(
524
+ CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, 0, 0);
525
+ if (length == 0)
526
+ FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
527
+ buffer_.resize(length + 1);
528
+ length = MultiByteToWideChar(
529
+ CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
530
+ if (length == 0)
531
+ FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
532
+ buffer_[length] = 0;
533
+}
534
+
535
+FMT_FUNC fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) {
536
+ if (int error_code = convert(s)) {
537
+ FMT_THROW(WindowsError(error_code,
538
+ "cannot convert string from UTF-16 to UTF-8"));
539
+ }
540
+}
541
+
542
+FMT_FUNC int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) {
543
+ if (s.size() > INT_MAX)
544
+ return ERROR_INVALID_PARAMETER;
545
+ int s_size = static_cast<int>(s.size());
546
+ int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, 0, 0, 0, 0);
547
+ if (length == 0)
548
+ return GetLastError();
549
+ buffer_.resize(length + 1);
550
+ length = WideCharToMultiByte(
551
+ CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, 0, 0);
552
+ if (length == 0)
553
+ return GetLastError();
554
+ buffer_[length] = 0;
555
+ return 0;
556
+}
557
+
558
+FMT_FUNC void fmt::WindowsError::init(
559
+ int err_code, CStringRef format_str, ArgList args) {
560
+ error_code_ = err_code;
561
+ MemoryWriter w;
562
+ internal::format_windows_error(w, err_code, format(format_str, args));
563
+ std::runtime_error &base = *this;
564
+ base = std::runtime_error(w.str());
565
+}
566
+
567
+FMT_FUNC void fmt::internal::format_windows_error(
568
+ fmt::Writer &out, int error_code,
569
+ fmt::StringRef message) FMT_NOEXCEPT {
570
+ FMT_TRY {
571
+ MemoryBuffer<wchar_t, INLINE_BUFFER_SIZE> buffer;
572
+ buffer.resize(INLINE_BUFFER_SIZE);
573
+ for (;;) {
574
+ wchar_t *system_message = &buffer[0];
575
+ int result = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
576
+ 0, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
577
+ system_message, static_cast<uint32_t>(buffer.size()), 0);
578
+ if (result != 0) {
579
+ UTF16ToUTF8 utf8_message;
580
+ if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
581
+ out << message << ": " << utf8_message;
582
+ return;
583
+ }
584
+ break;
585
+ }
586
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
587
+ break; // Can't get error message, report error code instead.
588
+ buffer.resize(buffer.size() * 2);
589
+ }
590
+ } FMT_CATCH(...) {}
591
+ fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32.
592
+}
593
+
594
+#endif // FMT_USE_WINDOWS_H
595
+
596
+FMT_FUNC void fmt::internal::format_system_error(
597
+ fmt::Writer &out, int error_code,
598
+ fmt::StringRef message) FMT_NOEXCEPT {
599
+ FMT_TRY {
600
+ MemoryBuffer<char, INLINE_BUFFER_SIZE> buffer;
601
+ buffer.resize(INLINE_BUFFER_SIZE);
602
+ for (;;) {
603
+ char *system_message = &buffer[0];
604
+ int result = safe_strerror(error_code, system_message, buffer.size());
605
+ if (result == 0) {
606
+ out << message << ": " << system_message;
607
+ return;
608
+ }
609
+ if (result != ERANGE)
610
+ break; // Can't get error message, report error code instead.
611
+ buffer.resize(buffer.size() * 2);
612
+ }
613
+ } FMT_CATCH(...) {}
614
+ fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32.
615
+}
616
+
617
+template <typename Char>
618
+void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
619
+ if (!map_.empty())
620
+ return;
621
+ typedef internal::NamedArg<Char> NamedArg;
622
+ const NamedArg *named_arg = 0;
623
+ bool use_values =
624
+ args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE;
625
+ if (use_values) {
626
+ for (unsigned i = 0;/*nothing*/; ++i) {
627
+ internal::Arg::Type arg_type = args.type(i);
628
+ switch (arg_type) {
629
+ case internal::Arg::NONE:
630
+ return;
631
+ case internal::Arg::NAMED_ARG:
632
+ named_arg = static_cast<const NamedArg*>(args.values_[i].pointer);
633
+ map_.push_back(Pair(named_arg->name, *named_arg));
634
+ break;
635
+ default:
636
+ /*nothing*/;
637
+ }
638
+ }
639
+ return;
640
+ }
641
+ for (unsigned i = 0; i != ArgList::MAX_PACKED_ARGS; ++i) {
642
+ internal::Arg::Type arg_type = args.type(i);
643
+ if (arg_type == internal::Arg::NAMED_ARG) {
644
+ named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
645
+ map_.push_back(Pair(named_arg->name, *named_arg));
646
+ }
647
+ }
648
+ for (unsigned i = ArgList::MAX_PACKED_ARGS;/*nothing*/; ++i) {
649
+ switch (args.args_[i].type) {
650
+ case internal::Arg::NONE:
651
+ return;
652
+ case internal::Arg::NAMED_ARG:
653
+ named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
654
+ map_.push_back(Pair(named_arg->name, *named_arg));
655
+ break;
656
+ default:
657
+ /*nothing*/;
658
+ }
659
+ }
660
+}
661
+
662
+template <typename Char>
663
+void fmt::internal::FixedBuffer<Char>::grow(std::size_t) {
664
+ FMT_THROW(std::runtime_error("buffer overflow"));
665
+}
666
+
667
+FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
668
+ unsigned arg_index, const char *&error) {
669
+ Arg arg = args_[arg_index];
670
+ switch (arg.type) {
671
+ case Arg::NONE:
672
+ error = "argument index out of range";
673
+ break;
674
+ case Arg::NAMED_ARG:
675
+ arg = *static_cast<const internal::Arg*>(arg.pointer);
676
+ break;
677
+ default:
678
+ /*nothing*/;
679
+ }
680
+ return arg;
681
+}
682
+
683
+template <typename Char>
684
+void fmt::internal::PrintfFormatter<Char>::parse_flags(
685
+ FormatSpec &spec, const Char *&s) {
686
+ for (;;) {
687
+ switch (*s++) {
688
+ case '-':
689
+ spec.align_ = ALIGN_LEFT;
690
+ break;
691
+ case '+':
692
+ spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
693
+ break;
694
+ case '0':
695
+ spec.fill_ = '0';
696
+ break;
697
+ case ' ':
698
+ spec.flags_ |= SIGN_FLAG;
699
+ break;
700
+ case '#':
701
+ spec.flags_ |= HASH_FLAG;
702
+ break;
703
+ default:
704
+ --s;
705
+ return;
706
+ }
707
+ }
708
+}
709
+
710
+template <typename Char>
711
+Arg fmt::internal::PrintfFormatter<Char>::get_arg(
712
+ const Char *s, unsigned arg_index) {
713
+ (void)s;
714
+ const char *error = 0;
715
+ Arg arg = arg_index == UINT_MAX ?
716
+ next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
717
+ if (error)
718
+ FMT_THROW(FormatError(!*s ? "invalid format string" : error));
719
+ return arg;
720
+}
721
+
722
+template <typename Char>
723
+unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
724
+ const Char *&s, FormatSpec &spec) {
725
+ unsigned arg_index = UINT_MAX;
726
+ Char c = *s;
727
+ if (c >= '0' && c <= '9') {
728
+ // Parse an argument index (if followed by '$') or a width possibly
729
+ // preceded with '0' flag(s).
730
+ unsigned value = parse_nonnegative_int(s);
731
+ if (*s == '$') { // value is an argument index
732
+ ++s;
733
+ arg_index = value;
734
+ } else {
735
+ if (c == '0')
736
+ spec.fill_ = '0';
737
+ if (value != 0) {
738
+ // Nonzero value means that we parsed width and don't need to
739
+ // parse it or flags again, so return now.
740
+ spec.width_ = value;
741
+ return arg_index;
742
+ }
743
+ }
744
+ }
745
+ parse_flags(spec, s);
746
+ // Parse width.
747
+ if (*s >= '0' && *s <= '9') {
748
+ spec.width_ = parse_nonnegative_int(s);
749
+ } else if (*s == '*') {
750
+ ++s;
751
+ spec.width_ = WidthHandler(spec).visit(get_arg(s));
752
+ }
753
+ return arg_index;
754
+}
755
+
756
+template <typename Char>
757
+void fmt::internal::PrintfFormatter<Char>::format(
758
+ BasicWriter<Char> &writer, BasicCStringRef<Char> format_str) {
759
+ const Char *start = format_str.c_str();
760
+ const Char *s = start;
761
+ while (*s) {
762
+ Char c = *s++;
763
+ if (c != '%') continue;
764
+ if (*s == c) {
765
+ write(writer, start, s);
766
+ start = ++s;
767
+ continue;
768
+ }
769
+ write(writer, start, s - 1);
770
+
771
+ FormatSpec spec;
772
+ spec.align_ = ALIGN_RIGHT;
773
+
774
+ // Parse argument index, flags and width.
775
+ unsigned arg_index = parse_header(s, spec);
776
+
777
+ // Parse precision.
778
+ if (*s == '.') {
779
+ ++s;
780
+ if ('0' <= *s && *s <= '9') {
781
+ spec.precision_ = static_cast<int>(parse_nonnegative_int(s));
782
+ } else if (*s == '*') {
783
+ ++s;
784
+ spec.precision_ = PrecisionHandler().visit(get_arg(s));
785
+ }
786
+ }
787
+
788
+ Arg arg = get_arg(s, arg_index);
789
+ if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg))
790
+ spec.flags_ &= ~to_unsigned<int>(HASH_FLAG);
791
+ if (spec.fill_ == '0') {
792
+ if (arg.type <= Arg::LAST_NUMERIC_TYPE)
793
+ spec.align_ = ALIGN_NUMERIC;
794
+ else
795
+ spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
796
+ }
797
+
798
+ // Parse length and convert the argument to the required type.
799
+ switch (*s++) {
800
+ case 'h':
801
+ if (*s == 'h')
802
+ ArgConverter<signed char>(arg, *++s).visit(arg);
803
+ else
804
+ ArgConverter<short>(arg, *s).visit(arg);
805
+ break;
806
+ case 'l':
807
+ if (*s == 'l')
808
+ ArgConverter<fmt::LongLong>(arg, *++s).visit(arg);
809
+ else
810
+ ArgConverter<long>(arg, *s).visit(arg);
811
+ break;
812
+ case 'j':
813
+ ArgConverter<intmax_t>(arg, *s).visit(arg);
814
+ break;
815
+ case 'z':
816
+ ArgConverter<std::size_t>(arg, *s).visit(arg);
817
+ break;
818
+ case 't':
819
+ ArgConverter<std::ptrdiff_t>(arg, *s).visit(arg);
820
+ break;
821
+ case 'L':
822
+ // printf produces garbage when 'L' is omitted for long double, no
823
+ // need to do the same.
824
+ break;
825
+ default:
826
+ --s;
827
+ ArgConverter<void>(arg, *s).visit(arg);
828
+ }
829
+
830
+ // Parse type.
831
+ if (!*s)
832
+ FMT_THROW(FormatError("invalid format string"));
833
+ spec.type_ = static_cast<char>(*s++);
834
+ if (arg.type <= Arg::LAST_INTEGER_TYPE) {
835
+ // Normalize type.
836
+ switch (spec.type_) {
837
+ case 'i': case 'u':
838
+ spec.type_ = 'd';
839
+ break;
840
+ case 'c':
841
+ // TODO: handle wchar_t
842
+ CharConverter(arg).visit(arg);
843
+ break;
844
+ }
845
+ }
846
+
847
+ start = s;
848
+
849
+ // Format argument.
850
+ internal::PrintfArgFormatter<Char>(writer, spec).visit(arg);
851
+ }
852
+ write(writer, start, s);
853
+}
854
+
855
+FMT_FUNC void fmt::report_system_error(
856
+ int error_code, fmt::StringRef message) FMT_NOEXCEPT {
857
+ // 'fmt::' is for bcc32.
858
+ fmt::report_error(internal::format_system_error, error_code, message);
859
+}
860
+
861
+#if FMT_USE_WINDOWS_H
862
+FMT_FUNC void fmt::report_windows_error(
863
+ int error_code, fmt::StringRef message) FMT_NOEXCEPT {
864
+ // 'fmt::' is for bcc32.
865
+ fmt::report_error(internal::format_windows_error, error_code, message);
866
+}
867
+#endif
868
+
869
+FMT_FUNC void fmt::print(std::FILE *f, CStringRef format_str, ArgList args) {
870
+ MemoryWriter w;
871
+ w.write(format_str, args);
872
+ std::fwrite(w.data(), 1, w.size(), f);
873
+}
874
+
875
+FMT_FUNC void fmt::print(CStringRef format_str, ArgList args) {
876
+ print(stdout, format_str, args);
877
+}
878
+
879
+FMT_FUNC void fmt::print_colored(Color c, CStringRef format, ArgList args) {
880
+ char escape[] = "\x1b[30m";
881
+ escape[3] = static_cast<char>('0' + c);
882
+ std::fputs(escape, stdout);
883
+ print(format, args);
884
+ std::fputs(RESET_COLOR, stdout);
885
+}
886
+
887
+FMT_FUNC int fmt::fprintf(std::FILE *f, CStringRef format, ArgList args) {
888
+ MemoryWriter w;
889
+ printf(w, format, args);
890
+ std::size_t size = w.size();
891
+ return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size);
892
+}
893
+
894
+#ifndef FMT_HEADER_ONLY
895
+
896
+template struct fmt::internal::BasicData<void>;
897
+
898
+// Explicit instantiations for char.
899
+
900
+template void fmt::internal::FixedBuffer<char>::grow(std::size_t);
901
+
902
+template void fmt::internal::ArgMap<char>::init(const fmt::ArgList &args);
903
+
904
+template void fmt::internal::PrintfFormatter<char>::format(
905
+ BasicWriter<char> &writer, CStringRef format);
906
+
907
+template int fmt::internal::CharTraits<char>::format_float(
908
+ char *buffer, std::size_t size, const char *format,
909
+ unsigned width, int precision, double value);
910
+
911
+template int fmt::internal::CharTraits<char>::format_float(
912
+ char *buffer, std::size_t size, const char *format,
913
+ unsigned width, int precision, long double value);
914
+
915
+// Explicit instantiations for wchar_t.
916
+
917
+template void fmt::internal::FixedBuffer<wchar_t>::grow(std::size_t);
918
+
919
+template void fmt::internal::ArgMap<wchar_t>::init(const fmt::ArgList &args);
920
+
921
+template void fmt::internal::PrintfFormatter<wchar_t>::format(
922
+ BasicWriter<wchar_t> &writer, WCStringRef format);
923
+
924
+template int fmt::internal::CharTraits<wchar_t>::format_float(
925
+ wchar_t *buffer, std::size_t size, const wchar_t *format,
926
+ unsigned width, int precision, double value);
927
+
928
+template int fmt::internal::CharTraits<wchar_t>::format_float(
929
+ wchar_t *buffer, std::size_t size, const wchar_t *format,
930
+ unsigned width, int precision, long double value);
931
+
932
+#endif // FMT_HEADER_ONLY
933
+
934
+#ifdef _MSC_VER
935
+# pragma warning(pop)
936
+#endif
937
obs-studio-17.0.1.tar.xz/plugins/obs-browser/fmt/format.h
Added
3834
1
2
+/*
3
+ Formatting library for C++
4
+
5
+ Copyright (c) 2012 - 2016, Victor Zverovich
6
+ All rights reserved.
7
+
8
+ Redistribution and use in source and binary forms, with or without
9
+ modification, are permitted provided that the following conditions are met:
10
+
11
+ 1. Redistributions of source code must retain the above copyright notice, this
12
+ list of conditions and the following disclaimer.
13
+ 2. Redistributions in binary form must reproduce the above copyright notice,
14
+ this list of conditions and the following disclaimer in the documentation
15
+ and/or other materials provided with the distribution.
16
+
17
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ */
28
+
29
+#ifndef FMT_FORMAT_H_
30
+#define FMT_FORMAT_H_
31
+
32
+#include <cassert>
33
+#include <clocale>
34
+#include <cmath>
35
+#include <cstdio>
36
+#include <cstring>
37
+#include <limits>
38
+#include <memory>
39
+#include <stdexcept>
40
+#include <string>
41
+#include <vector>
42
+#include <utility>
43
+
44
+#ifdef _SECURE_SCL
45
+# define FMT_SECURE_SCL _SECURE_SCL
46
+#else
47
+# define FMT_SECURE_SCL 0
48
+#endif
49
+
50
+#if FMT_SECURE_SCL
51
+# include <iterator>
52
+#endif
53
+
54
+#if defined(_MSC_VER) && _MSC_VER <= 1500
55
+typedef unsigned __int32 uint32_t;
56
+typedef unsigned __int64 uint64_t;
57
+typedef __int64 intmax_t;
58
+#else
59
+#include <stdint.h>
60
+#endif
61
+
62
+#if !defined(FMT_HEADER_ONLY) && defined(_WIN32)
63
+# ifdef FMT_EXPORT
64
+# define FMT_API __declspec(dllexport)
65
+# elif defined(FMT_SHARED)
66
+# define FMT_API __declspec(dllimport)
67
+# endif
68
+#endif
69
+#ifndef FMT_API
70
+# define FMT_API
71
+#endif
72
+
73
+#ifdef __GNUC__
74
+# define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
75
+# define FMT_GCC_EXTENSION __extension__
76
+# if FMT_GCC_VERSION >= 406
77
+# pragma GCC diagnostic push
78
+// Disable the warning about "long long" which is sometimes reported even
79
+// when using __extension__.
80
+# pragma GCC diagnostic ignored "-Wlong-long"
81
+// Disable the warning about declaration shadowing because it affects too
82
+// many valid cases.
83
+# pragma GCC diagnostic ignored "-Wshadow"
84
+// Disable the warning about implicit conversions that may change the sign of
85
+// an integer; silencing it otherwise would require many explicit casts.
86
+# pragma GCC diagnostic ignored "-Wsign-conversion"
87
+# endif
88
+# if __cplusplus >= 201103L || defined __GXX_EXPERIMENTAL_CXX0X__
89
+# define FMT_HAS_GXX_CXX11 1
90
+# endif
91
+#else
92
+# define FMT_GCC_EXTENSION
93
+#endif
94
+
95
+#if defined(__INTEL_COMPILER)
96
+# define FMT_ICC_VERSION __INTEL_COMPILER
97
+#elif defined(__ICL)
98
+# define FMT_ICC_VERSION __ICL
99
+#endif
100
+
101
+#if defined(__clang__) && !defined(FMT_ICC_VERSION)
102
+# pragma clang diagnostic push
103
+# pragma clang diagnostic ignored "-Wdocumentation"
104
+#endif
105
+
106
+#ifdef __GNUC_LIBSTD__
107
+# define FMT_GNUC_LIBSTD_VERSION (__GNUC_LIBSTD__ * 100 + __GNUC_LIBSTD_MINOR__)
108
+#endif
109
+
110
+#ifdef __has_feature
111
+# define FMT_HAS_FEATURE(x) __has_feature(x)
112
+#else
113
+# define FMT_HAS_FEATURE(x) 0
114
+#endif
115
+
116
+#ifdef __has_builtin
117
+# define FMT_HAS_BUILTIN(x) __has_builtin(x)
118
+#else
119
+# define FMT_HAS_BUILTIN(x) 0
120
+#endif
121
+
122
+#ifdef __has_cpp_attribute
123
+# define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
124
+#else
125
+# define FMT_HAS_CPP_ATTRIBUTE(x) 0
126
+#endif
127
+
128
+#ifndef FMT_USE_VARIADIC_TEMPLATES
129
+// Variadic templates are available in GCC since version 4.4
130
+// (http://gcc.gnu.org/projects/cxx0x.html) and in Visual C++
131
+// since version 2013.
132
+# define FMT_USE_VARIADIC_TEMPLATES \
133
+ (FMT_HAS_FEATURE(cxx_variadic_templates) || \
134
+ (FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1800)
135
+#endif
136
+
137
+#ifndef FMT_USE_RVALUE_REFERENCES
138
+// Don't use rvalue references when compiling with clang and an old libstdc++
139
+// as the latter doesn't provide std::move.
140
+# if defined(FMT_GNUC_LIBSTD_VERSION) && FMT_GNUC_LIBSTD_VERSION <= 402
141
+# define FMT_USE_RVALUE_REFERENCES 0
142
+# else
143
+# define FMT_USE_RVALUE_REFERENCES \
144
+ (FMT_HAS_FEATURE(cxx_rvalue_references) || \
145
+ (FMT_GCC_VERSION >= 403 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1600)
146
+# endif
147
+#endif
148
+
149
+#if FMT_USE_RVALUE_REFERENCES
150
+# include <utility> // for std::move
151
+#endif
152
+
153
+// Check if exceptions are disabled.
154
+#if defined(__GNUC__) && !defined(__EXCEPTIONS)
155
+# define FMT_EXCEPTIONS 0
156
+#endif
157
+#if defined(_MSC_VER) && !_HAS_EXCEPTIONS
158
+# define FMT_EXCEPTIONS 0
159
+#endif
160
+#ifndef FMT_EXCEPTIONS
161
+# define FMT_EXCEPTIONS 1
162
+#endif
163
+
164
+#ifndef FMT_THROW
165
+# if FMT_EXCEPTIONS
166
+# define FMT_THROW(x) throw x
167
+# else
168
+# define FMT_THROW(x) assert(false)
169
+# endif
170
+#endif
171
+
172
+// Define FMT_USE_NOEXCEPT to make fmt use noexcept (C++11 feature).
173
+#ifndef FMT_USE_NOEXCEPT
174
+# define FMT_USE_NOEXCEPT 0
175
+#endif
176
+
177
+#ifndef FMT_NOEXCEPT
178
+# if FMT_EXCEPTIONS
179
+# if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \
180
+ (FMT_GCC_VERSION >= 408 && FMT_HAS_GXX_CXX11) || \
181
+ _MSC_VER >= 1900
182
+# define FMT_NOEXCEPT noexcept
183
+# else
184
+# define FMT_NOEXCEPT throw()
185
+# endif
186
+# else
187
+# define FMT_NOEXCEPT
188
+# endif
189
+#endif
190
+
191
+// A macro to disallow the copy constructor and operator= functions
192
+// This should be used in the private: declarations for a class
193
+#ifndef FMT_USE_DELETED_FUNCTIONS
194
+# define FMT_USE_DELETED_FUNCTIONS 0
195
+#endif
196
+
197
+#if FMT_USE_DELETED_FUNCTIONS || FMT_HAS_FEATURE(cxx_deleted_functions) || \
198
+ (FMT_GCC_VERSION >= 404 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1800
199
+# define FMT_DELETED_OR_UNDEFINED = delete
200
+# define FMT_DISALLOW_COPY_AND_ASSIGN(TypeName) \
201
+ TypeName(const TypeName&) = delete; \
202
+ TypeName& operator=(const TypeName&) = delete
203
+#else
204
+# define FMT_DELETED_OR_UNDEFINED
205
+# define FMT_DISALLOW_COPY_AND_ASSIGN(TypeName) \
206
+ TypeName(const TypeName&); \
207
+ TypeName& operator=(const TypeName&)
208
+#endif
209
+
210
+#ifndef FMT_USE_USER_DEFINED_LITERALS
211
+// All compilers which support UDLs also support variadic templates. This
212
+// makes the fmt::literals implementation easier. However, an explicit check
213
+// for variadic templates is added here just in case.
214
+// For Intel's compiler both it and the system gcc/msc must support UDLs.
215
+# define FMT_USE_USER_DEFINED_LITERALS \
216
+ FMT_USE_VARIADIC_TEMPLATES && FMT_USE_RVALUE_REFERENCES && \
217
+ (FMT_HAS_FEATURE(cxx_user_literals) || \
218
+ (FMT_GCC_VERSION >= 407 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1900) && \
219
+ (!defined(FMT_ICC_VERSION) || FMT_ICC_VERSION >= 1500)
220
+#endif
221
+
222
+#ifndef FMT_ASSERT
223
+# define FMT_ASSERT(condition, message) assert((condition) && message)
224
+#endif
225
+
226
+
227
+#if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clz)
228
+# define FMT_BUILTIN_CLZ(n) __builtin_clz(n)
229
+#endif
230
+
231
+#if FMT_GCC_VERSION >= 400 || FMT_HAS_BUILTIN(__builtin_clzll)
232
+# define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)
233
+#endif
234
+
235
+// Some compilers masquerade as both MSVC and GCC-likes or
236
+// otherwise support __builtin_clz and __builtin_clzll, so
237
+// only define FMT_BUILTIN_CLZ using the MSVC intrinsics
238
+// if the clz and clzll builtins are not available.
239
+#if defined(_MSC_VER) && !defined(FMT_BUILTIN_CLZLL)
240
+# include <intrin.h> // _BitScanReverse, _BitScanReverse64
241
+
242
+namespace fmt {
243
+namespace internal {
244
+# pragma intrinsic(_BitScanReverse)
245
+inline uint32_t clz(uint32_t x) {
246
+ unsigned long r = 0;
247
+ _BitScanReverse(&r, x);
248
+
249
+ assert(x != 0);
250
+ // Static analysis complains about using uninitialized data
251
+ // "r", but the only way that can happen is if "x" is 0,
252
+ // which the callers guarantee to not happen.
253
+# pragma warning(suppress: 6102)
254
+ return 31 - r;
255
+}
256
+# define FMT_BUILTIN_CLZ(n) fmt::internal::clz(n)
257
+
258
+# ifdef _WIN64
259
+# pragma intrinsic(_BitScanReverse64)
260
+# endif
261
+
262
+inline uint32_t clzll(uint64_t x) {
263
+ unsigned long r = 0;
264
+# ifdef _WIN64
265
+ _BitScanReverse64(&r, x);
266
+# else
267
+ // Scan the high 32 bits.
268
+ if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32)))
269
+ return 63 - (r + 32);
270
+
271
+ // Scan the low 32 bits.
272
+ _BitScanReverse(&r, static_cast<uint32_t>(x));
273
+# endif
274
+
275
+ assert(x != 0);
276
+ // Static analysis complains about using uninitialized data
277
+ // "r", but the only way that can happen is if "x" is 0,
278
+ // which the callers guarantee to not happen.
279
+# pragma warning(suppress: 6102)
280
+ return 63 - r;
281
+}
282
+# define FMT_BUILTIN_CLZLL(n) fmt::internal::clzll(n)
283
+}
284
+}
285
+#endif
286
+
287
+namespace fmt {
288
+namespace internal {
289
+struct DummyInt {
290
+ int data[2];
291
+ operator int() const { return 0; }
292
+};
293
+typedef std::numeric_limits<fmt::internal::DummyInt> FPUtil;
294
+
295
+// Dummy implementations of system functions such as signbit and ecvt called
296
+// if the latter are not available.
297
+inline DummyInt signbit(...) { return DummyInt(); }
298
+inline DummyInt _ecvt_s(...) { return DummyInt(); }
299
+inline DummyInt isinf(...) { return DummyInt(); }
300
+inline DummyInt _finite(...) { return DummyInt(); }
301
+inline DummyInt isnan(...) { return DummyInt(); }
302
+inline DummyInt _isnan(...) { return DummyInt(); }
303
+
304
+// A helper function to suppress bogus "conditional expression is constant"
305
+// warnings.
306
+template <typename T>
307
+inline T check(T value) { return value; }
308
+}
309
+} // namespace fmt
310
+
311
+namespace std {
312
+// Standard permits specialization of std::numeric_limits. This specialization
313
+// is used to resolve ambiguity between isinf and std::isinf in glibc:
314
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=48891
315
+// and the same for isnan and signbit.
316
+template <>
317
+class numeric_limits<fmt::internal::DummyInt> :
318
+ public std::numeric_limits<int> {
319
+ public:
320
+ // Portable version of isinf.
321
+ template <typename T>
322
+ static bool isinfinity(T x) {
323
+ using namespace fmt::internal;
324
+ // The resolution "priority" is:
325
+ // isinf macro > std::isinf > ::isinf > fmt::internal::isinf
326
+ if (check(sizeof(isinf(x)) == sizeof(bool) ||
327
+ sizeof(isinf(x)) == sizeof(int))) {
328
+ return isinf(x) != 0;
329
+ }
330
+ return !_finite(static_cast<double>(x));
331
+ }
332
+
333
+ // Portable version of isnan.
334
+ template <typename T>
335
+ static bool isnotanumber(T x) {
336
+ using namespace fmt::internal;
337
+ if (check(sizeof(isnan(x)) == sizeof(bool) ||
338
+ sizeof(isnan(x)) == sizeof(int))) {
339
+ return isnan(x) != 0;
340
+ }
341
+ return _isnan(static_cast<double>(x)) != 0;
342
+ }
343
+
344
+ // Portable version of signbit.
345
+ static bool isnegative(double x) {
346
+ using namespace fmt::internal;
347
+ if (check(sizeof(signbit(x)) == sizeof(int)))
348
+ return signbit(x) != 0;
349
+ if (x < 0) return true;
350
+ if (!isnotanumber(x)) return false;
351
+ int dec = 0, sign = 0;
352
+ char buffer[2]; // The buffer size must be >= 2 or _ecvt_s will fail.
353
+ _ecvt_s(buffer, sizeof(buffer), x, 0, &dec, &sign);
354
+ return sign != 0;
355
+ }
356
+};
357
+} // namespace std
358
+
359
+namespace fmt {
360
+
361
+// Fix the warning about long long on older versions of GCC
362
+// that don't support the diagnostic pragma.
363
+FMT_GCC_EXTENSION typedef long long LongLong;
364
+FMT_GCC_EXTENSION typedef unsigned long long ULongLong;
365
+
366
+#if FMT_USE_RVALUE_REFERENCES
367
+using std::move;
368
+#endif
369
+
370
+template <typename Char>
371
+class BasicWriter;
372
+
373
+typedef BasicWriter<char> Writer;
374
+typedef BasicWriter<wchar_t> WWriter;
375
+
376
+template <typename Char>
377
+class ArgFormatter;
378
+
379
+template <typename CharType,
380
+ typename ArgFormatter = fmt::ArgFormatter<CharType> >
381
+class BasicFormatter;
382
+
383
+/**
384
+ \rst
385
+ A string reference. It can be constructed from a C string or ``std::string``.
386
+
387
+ You can use one of the following typedefs for common character types:
388
+
389
+ +------------+-------------------------+
390
+ | Type | Definition |
391
+ +============+=========================+
392
+ | StringRef | BasicStringRef<char> |
393
+ +------------+-------------------------+
394
+ | WStringRef | BasicStringRef<wchar_t> |
395
+ +------------+-------------------------+
396
+
397
+ This class is most useful as a parameter type to allow passing
398
+ different types of strings to a function, for example::
399
+
400
+ template <typename... Args>
401
+ std::string format(StringRef format_str, const Args & ... args);
402
+
403
+ format("{}", 42);
404
+ format(std::string("{}"), 42);
405
+ \endrst
406
+ */
407
+template <typename Char>
408
+class BasicStringRef {
409
+ private:
410
+ const Char *data_;
411
+ std::size_t size_;
412
+
413
+ public:
414
+ /** Constructs a string reference object from a C string and a size. */
415
+ BasicStringRef(const Char *s, std::size_t size) : data_(s), size_(size) {}
416
+
417
+ /**
418
+ \rst
419
+ Constructs a string reference object from a C string computing
420
+ the size with ``std::char_traits<Char>::length``.
421
+ \endrst
422
+ */
423
+ BasicStringRef(const Char *s)
424
+ : data_(s), size_(std::char_traits<Char>::length(s)) {}
425
+
426
+ /**
427
+ \rst
428
+ Constructs a string reference from an ``std::string`` object.
429
+ \endrst
430
+ */
431
+ BasicStringRef(const std::basic_string<Char> &s)
432
+ : data_(s.c_str()), size_(s.size()) {}
433
+
434
+ /**
435
+ \rst
436
+ Converts a string reference to an ``std::string`` object.
437
+ \endrst
438
+ */
439
+ std::basic_string<Char> to_string() const {
440
+ return std::basic_string<Char>(data_, size_);
441
+ }
442
+
443
+ /** Returns a pointer to the string data. */
444
+ const Char *data() const { return data_; }
445
+
446
+ /** Returns the string size. */
447
+ std::size_t size() const { return size_; }
448
+
449
+ // Lexicographically compare this string reference to other.
450
+ int compare(BasicStringRef other) const {
451
+ std::size_t size = size_ < other.size_ ? size_ : other.size_;
452
+ int result = std::char_traits<Char>::compare(data_, other.data_, size);
453
+ if (result == 0)
454
+ result = size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1);
455
+ return result;
456
+ }
457
+
458
+ friend bool operator==(BasicStringRef lhs, BasicStringRef rhs) {
459
+ return lhs.compare(rhs) == 0;
460
+ }
461
+ friend bool operator!=(BasicStringRef lhs, BasicStringRef rhs) {
462
+ return lhs.compare(rhs) != 0;
463
+ }
464
+ friend bool operator<(BasicStringRef lhs, BasicStringRef rhs) {
465
+ return lhs.compare(rhs) < 0;
466
+ }
467
+ friend bool operator<=(BasicStringRef lhs, BasicStringRef rhs) {
468
+ return lhs.compare(rhs) <= 0;
469
+ }
470
+ friend bool operator>(BasicStringRef lhs, BasicStringRef rhs) {
471
+ return lhs.compare(rhs) > 0;
472
+ }
473
+ friend bool operator>=(BasicStringRef lhs, BasicStringRef rhs) {
474
+ return lhs.compare(rhs) >= 0;
475
+ }
476
+};
477
+
478
+typedef BasicStringRef<char> StringRef;
479
+typedef BasicStringRef<wchar_t> WStringRef;
480
+
481
+/**
482
+ \rst
483
+ A reference to a null terminated string. It can be constructed from a C
484
+ string or ``std::string``.
485
+
486
+ You can use one of the following typedefs for common character types:
487
+
488
+ +-------------+--------------------------+
489
+ | Type | Definition |
490
+ +=============+==========================+
491
+ | CStringRef | BasicCStringRef<char> |
492
+ +-------------+--------------------------+
493
+ | WCStringRef | BasicCStringRef<wchar_t> |
494
+ +-------------+--------------------------+
495
+
496
+ This class is most useful as a parameter type to allow passing
497
+ different types of strings to a function, for example::
498
+
499
+ template <typename... Args>
500
+ std::string format(CStringRef format_str, const Args & ... args);
501
+
502
+ format("{}", 42);
503
+ format(std::string("{}"), 42);
504
+ \endrst
505
+ */
506
+template <typename Char>
507
+class BasicCStringRef {
508
+ private:
509
+ const Char *data_;
510
+
511
+ public:
512
+ /** Constructs a string reference object from a C string. */
513
+ BasicCStringRef(const Char *s) : data_(s) {}
514
+
515
+ /**
516
+ \rst
517
+ Constructs a string reference from an ``std::string`` object.
518
+ \endrst
519
+ */
520
+ BasicCStringRef(const std::basic_string<Char> &s) : data_(s.c_str()) {}
521
+
522
+ /** Returns the pointer to a C string. */
523
+ const Char *c_str() const { return data_; }
524
+};
525
+
526
+typedef BasicCStringRef<char> CStringRef;
527
+typedef BasicCStringRef<wchar_t> WCStringRef;
528
+
529
+/**
530
+ A formatting error such as invalid format string.
531
+*/
532
+class FormatError : public std::runtime_error {
533
+ public:
534
+ explicit FormatError(CStringRef message)
535
+ : std::runtime_error(message.c_str()) {}
536
+};
537
+
538
+namespace internal {
539
+
540
+// MakeUnsigned<T>::Type gives an unsigned type corresponding to integer type T.
541
+template <typename T>
542
+struct MakeUnsigned { typedef T Type; };
543
+
544
+#define FMT_SPECIALIZE_MAKE_UNSIGNED(T, U) \
545
+ template <> \
546
+ struct MakeUnsigned<T> { typedef U Type; }
547
+
548
+FMT_SPECIALIZE_MAKE_UNSIGNED(char, unsigned char);
549
+FMT_SPECIALIZE_MAKE_UNSIGNED(signed char, unsigned char);
550
+FMT_SPECIALIZE_MAKE_UNSIGNED(short, unsigned short);
551
+FMT_SPECIALIZE_MAKE_UNSIGNED(int, unsigned);
552
+FMT_SPECIALIZE_MAKE_UNSIGNED(long, unsigned long);
553
+FMT_SPECIALIZE_MAKE_UNSIGNED(LongLong, ULongLong);
554
+
555
+// Casts nonnegative integer to unsigned.
556
+template <typename Int>
557
+inline typename MakeUnsigned<Int>::Type to_unsigned(Int value) {
558
+ FMT_ASSERT(value >= 0, "negative value");
559
+ return static_cast<typename MakeUnsigned<Int>::Type>(value);
560
+}
561
+
562
+// The number of characters to store in the MemoryBuffer object itself
563
+// to avoid dynamic memory allocation.
564
+enum { INLINE_BUFFER_SIZE = 500 };
565
+
566
+#if FMT_SECURE_SCL
567
+// Use checked iterator to avoid warnings on MSVC.
568
+template <typename T>
569
+inline stdext::checked_array_iterator<T*> make_ptr(T *ptr, std::size_t size) {
570
+ return stdext::checked_array_iterator<T*>(ptr, size);
571
+}
572
+#else
573
+template <typename T>
574
+inline T *make_ptr(T *ptr, std::size_t) { return ptr; }
575
+#endif
576
+} // namespace internal
577
+
578
+/**
579
+ \rst
580
+ A buffer supporting a subset of ``std::vector``'s operations.
581
+ \endrst
582
+ */
583
+template <typename T>
584
+class Buffer {
585
+ private:
586
+ FMT_DISALLOW_COPY_AND_ASSIGN(Buffer);
587
+
588
+ protected:
589
+ T *ptr_;
590
+ std::size_t size_;
591
+ std::size_t capacity_;
592
+
593
+ Buffer(T *ptr = 0, std::size_t capacity = 0)
594
+ : ptr_(ptr), size_(0), capacity_(capacity) {}
595
+
596
+ /**
597
+ \rst
598
+ Increases the buffer capacity to hold at least *size* elements updating
599
+ ``ptr_`` and ``capacity_``.
600
+ \endrst
601
+ */
602
+ virtual void grow(std::size_t size) = 0;
603
+
604
+ public:
605
+ virtual ~Buffer() {}
606
+
607
+ /** Returns the size of this buffer. */
608
+ std::size_t size() const { return size_; }
609
+
610
+ /** Returns the capacity of this buffer. */
611
+ std::size_t capacity() const { return capacity_; }
612
+
613
+ /**
614
+ Resizes the buffer. If T is a POD type new elements may not be initialized.
615
+ */
616
+ void resize(std::size_t new_size) {
617
+ if (new_size > capacity_)
618
+ grow(new_size);
619
+ size_ = new_size;
620
+ }
621
+
622
+ /**
623
+ \rst
624
+ Reserves space to store at least *capacity* elements.
625
+ \endrst
626
+ */
627
+ void reserve(std::size_t capacity) {
628
+ if (capacity > capacity_)
629
+ grow(capacity);
630
+ }
631
+
632
+ void clear() FMT_NOEXCEPT { size_ = 0; }
633
+
634
+ void push_back(const T &value) {
635
+ if (size_ == capacity_)
636
+ grow(size_ + 1);
637
+ ptr_[size_++] = value;
638
+ }
639
+
640
+ /** Appends data to the end of the buffer. */
641
+ template <typename U>
642
+ void append(const U *begin, const U *end);
643
+
644
+ T &operator[](std::size_t index) { return ptr_[index]; }
645
+ const T &operator[](std::size_t index) const { return ptr_[index]; }
646
+};
647
+
648
+template <typename T>
649
+template <typename U>
650
+void Buffer<T>::append(const U *begin, const U *end) {
651
+ std::size_t new_size = size_ + internal::to_unsigned(end - begin);
652
+ if (new_size > capacity_)
653
+ grow(new_size);
654
+ std::uninitialized_copy(begin, end,
655
+ internal::make_ptr(ptr_, capacity_) + size_);
656
+ size_ = new_size;
657
+}
658
+
659
+namespace internal {
660
+
661
+// A memory buffer for trivially copyable/constructible types with the first SIZE
662
+// elements stored in the object itself.
663
+template <typename T, std::size_t SIZE, typename Allocator = std::allocator<T> >
664
+class MemoryBuffer : private Allocator, public Buffer<T> {
665
+ private:
666
+ T data_[SIZE];
667
+
668
+ // Deallocate memory allocated by the buffer.
669
+ void deallocate() {
670
+ if (this->ptr_ != data_) Allocator::deallocate(this->ptr_, this->capacity_);
671
+ }
672
+
673
+ protected:
674
+ void grow(std::size_t size);
675
+
676
+ public:
677
+ explicit MemoryBuffer(const Allocator &alloc = Allocator())
678
+ : Allocator(alloc), Buffer<T>(data_, SIZE) {}
679
+ ~MemoryBuffer() { deallocate(); }
680
+
681
+#if FMT_USE_RVALUE_REFERENCES
682
+ private:
683
+ // Move data from other to this buffer.
684
+ void move(MemoryBuffer &other) {
685
+ Allocator &this_alloc = *this, &other_alloc = other;
686
+ this_alloc = std::move(other_alloc);
687
+ this->size_ = other.size_;
688
+ this->capacity_ = other.capacity_;
689
+ if (other.ptr_ == other.data_) {
690
+ this->ptr_ = data_;
691
+ std::uninitialized_copy(other.data_, other.data_ + this->size_,
692
+ make_ptr(data_, this->capacity_));
693
+ } else {
694
+ this->ptr_ = other.ptr_;
695
+ // Set pointer to the inline array so that delete is not called
696
+ // when deallocating.
697
+ other.ptr_ = other.data_;
698
+ }
699
+ }
700
+
701
+ public:
702
+ MemoryBuffer(MemoryBuffer &&other) {
703
+ move(other);
704
+ }
705
+
706
+ MemoryBuffer &operator=(MemoryBuffer &&other) {
707
+ assert(this != &other);
708
+ deallocate();
709
+ move(other);
710
+ return *this;
711
+ }
712
+#endif
713
+
714
+ // Returns a copy of the allocator associated with this buffer.
715
+ Allocator get_allocator() const { return *this; }
716
+};
717
+
718
+template <typename T, std::size_t SIZE, typename Allocator>
719
+void MemoryBuffer<T, SIZE, Allocator>::grow(std::size_t size) {
720
+ std::size_t new_capacity = this->capacity_ + this->capacity_ / 2;
721
+ if (size > new_capacity)
722
+ new_capacity = size;
723
+ T *new_ptr = this->allocate(new_capacity);
724
+ // The following code doesn't throw, so the raw pointer above doesn't leak.
725
+ std::uninitialized_copy(this->ptr_, this->ptr_ + this->size_,
726
+ make_ptr(new_ptr, new_capacity));
727
+ std::size_t old_capacity = this->capacity_;
728
+ T *old_ptr = this->ptr_;
729
+ this->capacity_ = new_capacity;
730
+ this->ptr_ = new_ptr;
731
+ // deallocate may throw (at least in principle), but it doesn't matter since
732
+ // the buffer already uses the new storage and will deallocate it in case
733
+ // of exception.
734
+ if (old_ptr != data_)
735
+ Allocator::deallocate(old_ptr, old_capacity);
736
+}
737
+
738
+// A fixed-size buffer.
739
+template <typename Char>
740
+class FixedBuffer : public fmt::Buffer<Char> {
741
+ public:
742
+ FixedBuffer(Char *array, std::size_t size) : fmt::Buffer<Char>(array, size) {}
743
+
744
+ protected:
745
+ FMT_API void grow(std::size_t size);
746
+};
747
+
748
+template <typename Char>
749
+class BasicCharTraits {
750
+ public:
751
+#if FMT_SECURE_SCL
752
+ typedef stdext::checked_array_iterator<Char*> CharPtr;
753
+#else
754
+ typedef Char *CharPtr;
755
+#endif
756
+ static Char cast(int value) { return static_cast<Char>(value); }
757
+};
758
+
759
+template <typename Char>
760
+class CharTraits;
761
+
762
+template <>
763
+class CharTraits<char> : public BasicCharTraits<char> {
764
+ private:
765
+ // Conversion from wchar_t to char is not allowed.
766
+ static char convert(wchar_t);
767
+
768
+ public:
769
+ static char convert(char value) { return value; }
770
+
771
+ // Formats a floating-point number.
772
+ template <typename T>
773
+ FMT_API static int format_float(char *buffer, std::size_t size,
774
+ const char *format, unsigned width, int precision, T value);
775
+};
776
+
777
+template <>
778
+class CharTraits<wchar_t> : public BasicCharTraits<wchar_t> {
779
+ public:
780
+ static wchar_t convert(char value) { return value; }
781
+ static wchar_t convert(wchar_t value) { return value; }
782
+
783
+ template <typename T>
784
+ FMT_API static int format_float(wchar_t *buffer, std::size_t size,
785
+ const wchar_t *format, unsigned width, int precision, T value);
786
+};
787
+
788
+// Checks if a number is negative - used to avoid warnings.
789
+template <bool IsSigned>
790
+struct SignChecker {
791
+ template <typename T>
792
+ static bool is_negative(T value) { return value < 0; }
793
+};
794
+
795
+template <>
796
+struct SignChecker<false> {
797
+ template <typename T>
798
+ static bool is_negative(T) { return false; }
799
+};
800
+
801
+// Returns true if value is negative, false otherwise.
802
+// Same as (value < 0) but doesn't produce warnings if T is an unsigned type.
803
+template <typename T>
804
+inline bool is_negative(T value) {
805
+ return SignChecker<std::numeric_limits<T>::is_signed>::is_negative(value);
806
+}
807
+
808
+// Selects uint32_t if FitsIn32Bits is true, uint64_t otherwise.
809
+template <bool FitsIn32Bits>
810
+struct TypeSelector { typedef uint32_t Type; };
811
+
812
+template <>
813
+struct TypeSelector<false> { typedef uint64_t Type; };
814
+
815
+template <typename T>
816
+struct IntTraits {
817
+ // Smallest of uint32_t and uint64_t that is large enough to represent
818
+ // all values of T.
819
+ typedef typename
820
+ TypeSelector<std::numeric_limits<T>::digits <= 32>::Type MainType;
821
+};
822
+
823
+FMT_API void report_unknown_type(char code, const char *type);
824
+
825
+// Static data is placed in this class template to allow header-only
826
+// configuration.
827
+template <typename T = void>
828
+struct FMT_API BasicData {
829
+ static const uint32_t POWERS_OF_10_32[];
830
+ static const uint64_t POWERS_OF_10_64[];
831
+ static const char DIGITS[];
832
+};
833
+
834
+typedef BasicData<> Data;
835
+
836
+#ifdef FMT_BUILTIN_CLZLL
837
+// Returns the number of decimal digits in n. Leading zeros are not counted
838
+// except for n == 0 in which case count_digits returns 1.
839
+inline unsigned count_digits(uint64_t n) {
840
+ // Based on http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
841
+ // and the benchmark https://github.com/localvoid/cxx-benchmark-count-digits.
842
+ int t = (64 - FMT_BUILTIN_CLZLL(n | 1)) * 1233 >> 12;
843
+ return to_unsigned(t) - (n < Data::POWERS_OF_10_64[t]) + 1;
844
+}
845
+#else
846
+// Fallback version of count_digits used when __builtin_clz is not available.
847
+inline unsigned count_digits(uint64_t n) {
848
+ unsigned count = 1;
849
+ for (;;) {
850
+ // Integer division is slow so do it for a group of four digits instead
851
+ // of for every digit. The idea comes from the talk by Alexandrescu
852
+ // "Three Optimization Tips for C++". See speed-test for a comparison.
853
+ if (n < 10) return count;
854
+ if (n < 100) return count + 1;
855
+ if (n < 1000) return count + 2;
856
+ if (n < 10000) return count + 3;
857
+ n /= 10000u;
858
+ count += 4;
859
+ }
860
+}
861
+#endif
862
+
863
+#ifdef FMT_BUILTIN_CLZ
864
+// Optional version of count_digits for better performance on 32-bit platforms.
865
+inline unsigned count_digits(uint32_t n) {
866
+ int t = (32 - FMT_BUILTIN_CLZ(n | 1)) * 1233 >> 12;
867
+ return to_unsigned(t) - (n < Data::POWERS_OF_10_32[t]) + 1;
868
+}
869
+#endif
870
+
871
+// A functor that doesn't add a thousands separator.
872
+struct NoThousandsSep {
873
+ template <typename Char>
874
+ void operator()(Char *) {}
875
+};
876
+
877
+// A functor that adds a thousands separator.
878
+class ThousandsSep {
879
+ private:
880
+ fmt::StringRef sep_;
881
+
882
+ // Index of a decimal digit with the least significant digit having index 0.
883
+ unsigned digit_index_;
884
+
885
+ public:
886
+ explicit ThousandsSep(fmt::StringRef sep) : sep_(sep), digit_index_(0) {}
887
+
888
+ template <typename Char>
889
+ void operator()(Char *&buffer) {
890
+ if (++digit_index_ % 3 != 0)
891
+ return;
892
+ buffer -= sep_.size();
893
+ std::uninitialized_copy(sep_.data(), sep_.data() + sep_.size(),
894
+ internal::make_ptr(buffer, sep_.size()));
895
+ }
896
+};
897
+
898
+// Formats a decimal unsigned integer value writing into buffer.
899
+// thousands_sep is a functor that is called after writing each char to
900
+// add a thousands separator if necessary.
901
+template <typename UInt, typename Char, typename ThousandsSep>
902
+inline void format_decimal(Char *buffer, UInt value, unsigned num_digits,
903
+ ThousandsSep thousands_sep) {
904
+ buffer += num_digits;
905
+ while (value >= 100) {
906
+ // Integer division is slow so do it for a group of two digits instead
907
+ // of for every digit. The idea comes from the talk by Alexandrescu
908
+ // "Three Optimization Tips for C++". See speed-test for a comparison.
909
+ unsigned index = static_cast<unsigned>((value % 100) * 2);
910
+ value /= 100;
911
+ *--buffer = Data::DIGITS[index + 1];
912
+ thousands_sep(buffer);
913
+ *--buffer = Data::DIGITS[index];
914
+ thousands_sep(buffer);
915
+ }
916
+ if (value < 10) {
917
+ *--buffer = static_cast<char>('0' + value);
918
+ return;
919
+ }
920
+ unsigned index = static_cast<unsigned>(value * 2);
921
+ *--buffer = Data::DIGITS[index + 1];
922
+ *--buffer = Data::DIGITS[index];
923
+}
924
+
925
+template <typename UInt, typename Char>
926
+inline void format_decimal(Char *buffer, UInt value, unsigned num_digits) {
927
+ return format_decimal(buffer, value, num_digits, NoThousandsSep());
928
+}
929
+
930
+#ifndef _WIN32
931
+# define FMT_USE_WINDOWS_H 0
932
+#elif !defined(FMT_USE_WINDOWS_H)
933
+# define FMT_USE_WINDOWS_H 1
934
+#endif
935
+
936
+// Define FMT_USE_WINDOWS_H to 0 to disable use of windows.h.
937
+// All the functionality that relies on it will be disabled too.
938
+#if FMT_USE_WINDOWS_H
939
+// A converter from UTF-8 to UTF-16.
940
+// It is only provided for Windows since other systems support UTF-8 natively.
941
+class UTF8ToUTF16 {
942
+ private:
943
+ MemoryBuffer<wchar_t, INLINE_BUFFER_SIZE> buffer_;
944
+
945
+ public:
946
+ FMT_API explicit UTF8ToUTF16(StringRef s);
947
+ operator WStringRef() const { return WStringRef(&buffer_[0], size()); }
948
+ size_t size() const { return buffer_.size() - 1; }
949
+ const wchar_t *c_str() const { return &buffer_[0]; }
950
+ std::wstring str() const { return std::wstring(&buffer_[0], size()); }
951
+};
952
+
953
+// A converter from UTF-16 to UTF-8.
954
+// It is only provided for Windows since other systems support UTF-8 natively.
955
+class UTF16ToUTF8 {
956
+ private:
957
+ MemoryBuffer<char, INLINE_BUFFER_SIZE> buffer_;
958
+
959
+ public:
960
+ UTF16ToUTF8() {}
961
+ FMT_API explicit UTF16ToUTF8(WStringRef s);
962
+ operator StringRef() const { return StringRef(&buffer_[0], size()); }
963
+ size_t size() const { return buffer_.size() - 1; }
964
+ const char *c_str() const { return &buffer_[0]; }
965
+ std::string str() const { return std::string(&buffer_[0], size()); }
966
+
967
+ // Performs conversion returning a system error code instead of
968
+ // throwing exception on conversion error. This method may still throw
969
+ // in case of memory allocation error.
970
+ FMT_API int convert(WStringRef s);
971
+};
972
+
973
+FMT_API void format_windows_error(fmt::Writer &out, int error_code,
974
+ fmt::StringRef message) FMT_NOEXCEPT;
975
+#endif
976
+
977
+FMT_API void format_system_error(fmt::Writer &out, int error_code,
978
+ fmt::StringRef message) FMT_NOEXCEPT;
979
+
980
+// A formatting argument value.
981
+struct Value {
982
+ template <typename Char>
983
+ struct StringValue {
984
+ const Char *value;
985
+ std::size_t size;
986
+ };
987
+
988
+ typedef void (*FormatFunc)(
989
+ void *formatter, const void *arg, void *format_str_ptr);
990
+
991
+ struct CustomValue {
992
+ const void *value;
993
+ FormatFunc format;
994
+ };
995
+
996
+ union {
997
+ int int_value;
998
+ unsigned uint_value;
999
+ LongLong long_long_value;
1000
+ ULongLong ulong_long_value;
1001
+ double double_value;
1002
+ long double long_double_value;
1003
+ const void *pointer;
1004
+ StringValue<char> string;
1005
+ StringValue<signed char> sstring;
1006
+ StringValue<unsigned char> ustring;
1007
+ StringValue<wchar_t> wstring;
1008
+ CustomValue custom;
1009
+ };
1010
+
1011
+ enum Type {
1012
+ NONE, NAMED_ARG,
1013
+ // Integer types should go first,
1014
+ INT, UINT, LONG_LONG, ULONG_LONG, BOOL, CHAR, LAST_INTEGER_TYPE = CHAR,
1015
+ // followed by floating-point types.
1016
+ DOUBLE, LONG_DOUBLE, LAST_NUMERIC_TYPE = LONG_DOUBLE,
1017
+ CSTRING, STRING, WSTRING, POINTER, CUSTOM
1018
+ };
1019
+};
1020
+
1021
+// A formatting argument. It is a trivially copyable/constructible type to
1022
+// allow storage in internal::MemoryBuffer.
1023
+struct Arg : Value {
1024
+ Type type;
1025
+};
1026
+
1027
+template <typename Char>
1028
+struct NamedArg;
1029
+
1030
+template <typename T = void>
1031
+struct Null {};
1032
+
1033
+// A helper class template to enable or disable overloads taking wide
1034
+// characters and strings in MakeValue.
1035
+template <typename T, typename Char>
1036
+struct WCharHelper {
1037
+ typedef Null<T> Supported;
1038
+ typedef T Unsupported;
1039
+};
1040
+
1041
+template <typename T>
1042
+struct WCharHelper<T, wchar_t> {
1043
+ typedef T Supported;
1044
+ typedef Null<T> Unsupported;
1045
+};
1046
+
1047
+typedef char Yes[1];
1048
+typedef char No[2];
1049
+
1050
+template <typename T>
1051
+T &get();
1052
+
1053
+// These are non-members to workaround an overload resolution bug in bcc32.
1054
+Yes &convert(fmt::ULongLong);
1055
+No &convert(...);
1056
+
1057
+template<typename T, bool ENABLE_CONVERSION>
1058
+struct ConvertToIntImpl {
1059
+ enum { value = ENABLE_CONVERSION };
1060
+};
1061
+
1062
+template<typename T, bool ENABLE_CONVERSION>
1063
+struct ConvertToIntImpl2 {
1064
+ enum { value = false };
1065
+};
1066
+
1067
+template<typename T>
1068
+struct ConvertToIntImpl2<T, true> {
1069
+ enum {
1070
+ // Don't convert numeric types.
1071
+ value = ConvertToIntImpl<T, !std::numeric_limits<T>::is_specialized>::value
1072
+ };
1073
+};
1074
+
1075
+template<typename T>
1076
+struct ConvertToInt {
1077
+ enum { enable_conversion = sizeof(convert(get<T>())) == sizeof(Yes) };
1078
+ enum { value = ConvertToIntImpl2<T, enable_conversion>::value };
1079
+};
1080
+
1081
+#define FMT_DISABLE_CONVERSION_TO_INT(Type) \
1082
+ template <> \
1083
+ struct ConvertToInt<Type> { enum { value = 0 }; }
1084
+
1085
+// Silence warnings about convering float to int.
1086
+FMT_DISABLE_CONVERSION_TO_INT(float);
1087
+FMT_DISABLE_CONVERSION_TO_INT(double);
1088
+FMT_DISABLE_CONVERSION_TO_INT(long double);
1089
+
1090
+template<bool B, class T = void>
1091
+struct EnableIf {};
1092
+
1093
+template<class T>
1094
+struct EnableIf<true, T> { typedef T type; };
1095
+
1096
+template<bool B, class T, class F>
1097
+struct Conditional { typedef T type; };
1098
+
1099
+template<class T, class F>
1100
+struct Conditional<false, T, F> { typedef F type; };
1101
+
1102
+// For bcc32 which doesn't understand ! in template arguments.
1103
+template<bool>
1104
+struct Not { enum { value = 0 }; };
1105
+
1106
+template<>
1107
+struct Not<false> { enum { value = 1 }; };
1108
+
1109
+// Makes an Arg object from any type.
1110
+template <typename Formatter>
1111
+class MakeValue : public Arg {
1112
+ public:
1113
+ typedef typename Formatter::Char Char;
1114
+
1115
+ private:
1116
+ // The following two methods are private to disallow formatting of
1117
+ // arbitrary pointers. If you want to output a pointer cast it to
1118
+ // "void *" or "const void *". In particular, this forbids formatting
1119
+ // of "[const] volatile char *" which is printed as bool by iostreams.
1120
+ // Do not implement!
1121
+ template <typename T>
1122
+ MakeValue(const T *value);
1123
+ template <typename T>
1124
+ MakeValue(T *value);
1125
+
1126
+ // The following methods are private to disallow formatting of wide
1127
+ // characters and strings into narrow strings as in
1128
+ // fmt::format("{}", L"test");
1129
+ // To fix this, use a wide format string: fmt::format(L"{}", L"test").
1130
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
1131
+ MakeValue(typename WCharHelper<wchar_t, Char>::Unsupported);
1132
+#endif
1133
+ MakeValue(typename WCharHelper<wchar_t *, Char>::Unsupported);
1134
+ MakeValue(typename WCharHelper<const wchar_t *, Char>::Unsupported);
1135
+ MakeValue(typename WCharHelper<const std::wstring &, Char>::Unsupported);
1136
+ MakeValue(typename WCharHelper<WStringRef, Char>::Unsupported);
1137
+
1138
+ void set_string(StringRef str) {
1139
+ string.value = str.data();
1140
+ string.size = str.size();
1141
+ }
1142
+
1143
+ void set_string(WStringRef str) {
1144
+ wstring.value = str.data();
1145
+ wstring.size = str.size();
1146
+ }
1147
+
1148
+ // Formats an argument of a custom type, such as a user-defined class.
1149
+ template <typename T>
1150
+ static void format_custom_arg(
1151
+ void *formatter, const void *arg, void *format_str_ptr) {
1152
+ format(*static_cast<Formatter*>(formatter),
1153
+ *static_cast<const Char**>(format_str_ptr),
1154
+ *static_cast<const T*>(arg));
1155
+ }
1156
+
1157
+ public:
1158
+ MakeValue() {}
1159
+
1160
+#define FMT_MAKE_VALUE_(Type, field, TYPE, rhs) \
1161
+ MakeValue(Type value) { field = rhs; } \
1162
+ static uint64_t type(Type) { return Arg::TYPE; }
1163
+
1164
+#define FMT_MAKE_VALUE(Type, field, TYPE) \
1165
+ FMT_MAKE_VALUE_(Type, field, TYPE, value)
1166
+
1167
+ FMT_MAKE_VALUE(bool, int_value, BOOL)
1168
+ FMT_MAKE_VALUE(short, int_value, INT)
1169
+ FMT_MAKE_VALUE(unsigned short, uint_value, UINT)
1170
+ FMT_MAKE_VALUE(int, int_value, INT)
1171
+ FMT_MAKE_VALUE(unsigned, uint_value, UINT)
1172
+
1173
+ MakeValue(long value) {
1174
+ // To minimize the number of types we need to deal with, long is
1175
+ // translated either to int or to long long depending on its size.
1176
+ if (check(sizeof(long) == sizeof(int)))
1177
+ int_value = static_cast<int>(value);
1178
+ else
1179
+ long_long_value = value;
1180
+ }
1181
+ static uint64_t type(long) {
1182
+ return sizeof(long) == sizeof(int) ? Arg::INT : Arg::LONG_LONG;
1183
+ }
1184
+
1185
+ MakeValue(unsigned long value) {
1186
+ if (check(sizeof(unsigned long) == sizeof(unsigned)))
1187
+ uint_value = static_cast<unsigned>(value);
1188
+ else
1189
+ ulong_long_value = value;
1190
+ }
1191
+ static uint64_t type(unsigned long) {
1192
+ return sizeof(unsigned long) == sizeof(unsigned) ?
1193
+ Arg::UINT : Arg::ULONG_LONG;
1194
+ }
1195
+
1196
+ FMT_MAKE_VALUE(LongLong, long_long_value, LONG_LONG)
1197
+ FMT_MAKE_VALUE(ULongLong, ulong_long_value, ULONG_LONG)
1198
+ FMT_MAKE_VALUE(float, double_value, DOUBLE)
1199
+ FMT_MAKE_VALUE(double, double_value, DOUBLE)
1200
+ FMT_MAKE_VALUE(long double, long_double_value, LONG_DOUBLE)
1201
+ FMT_MAKE_VALUE(signed char, int_value, INT)
1202
+ FMT_MAKE_VALUE(unsigned char, uint_value, UINT)
1203
+ FMT_MAKE_VALUE(char, int_value, CHAR)
1204
+
1205
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
1206
+ MakeValue(typename WCharHelper<wchar_t, Char>::Supported value) {
1207
+ int_value = value;
1208
+ }
1209
+ static uint64_t type(wchar_t) { return Arg::CHAR; }
1210
+#endif
1211
+
1212
+#define FMT_MAKE_STR_VALUE(Type, TYPE) \
1213
+ MakeValue(Type value) { set_string(value); } \
1214
+ static uint64_t type(Type) { return Arg::TYPE; }
1215
+
1216
+ FMT_MAKE_VALUE(char *, string.value, CSTRING)
1217
+ FMT_MAKE_VALUE(const char *, string.value, CSTRING)
1218
+ FMT_MAKE_VALUE(const signed char *, sstring.value, CSTRING)
1219
+ FMT_MAKE_VALUE(const unsigned char *, ustring.value, CSTRING)
1220
+ FMT_MAKE_STR_VALUE(const std::string &, STRING)
1221
+ FMT_MAKE_STR_VALUE(StringRef, STRING)
1222
+ FMT_MAKE_VALUE_(CStringRef, string.value, CSTRING, value.c_str())
1223
+
1224
+#define FMT_MAKE_WSTR_VALUE(Type, TYPE) \
1225
+ MakeValue(typename WCharHelper<Type, Char>::Supported value) { \
1226
+ set_string(value); \
1227
+ } \
1228
+ static uint64_t type(Type) { return Arg::TYPE; }
1229
+
1230
+ FMT_MAKE_WSTR_VALUE(wchar_t *, WSTRING)
1231
+ FMT_MAKE_WSTR_VALUE(const wchar_t *, WSTRING)
1232
+ FMT_MAKE_WSTR_VALUE(const std::wstring &, WSTRING)
1233
+ FMT_MAKE_WSTR_VALUE(WStringRef, WSTRING)
1234
+
1235
+ FMT_MAKE_VALUE(void *, pointer, POINTER)
1236
+ FMT_MAKE_VALUE(const void *, pointer, POINTER)
1237
+
1238
+ template <typename T>
1239
+ MakeValue(const T &value,
1240
+ typename EnableIf<Not<
1241
+ ConvertToInt<T>::value>::value, int>::type = 0) {
1242
+ custom.value = &value;
1243
+ custom.format = &format_custom_arg<T>;
1244
+ }
1245
+
1246
+ template <typename T>
1247
+ MakeValue(const T &value,
1248
+ typename EnableIf<ConvertToInt<T>::value, int>::type = 0) {
1249
+ int_value = value;
1250
+ }
1251
+
1252
+ template <typename T>
1253
+ static uint64_t type(const T &) {
1254
+ return ConvertToInt<T>::value ? Arg::INT : Arg::CUSTOM;
1255
+ }
1256
+
1257
+ // Additional template param `Char_` is needed here because make_type always
1258
+ // uses char.
1259
+ template <typename Char_>
1260
+ MakeValue(const NamedArg<Char_> &value) { pointer = &value; }
1261
+
1262
+ template <typename Char_>
1263
+ static uint64_t type(const NamedArg<Char_> &) { return Arg::NAMED_ARG; }
1264
+};
1265
+
1266
+template <typename Formatter>
1267
+class MakeArg : public Arg {
1268
+public:
1269
+ MakeArg() {
1270
+ type = Arg::NONE;
1271
+ }
1272
+
1273
+ template <typename T>
1274
+ MakeArg(const T &value)
1275
+ : Arg(MakeValue<Formatter>(value)) {
1276
+ type = static_cast<Arg::Type>(MakeValue<Formatter>::type(value));
1277
+ }
1278
+};
1279
+
1280
+template <typename Char>
1281
+struct NamedArg : Arg {
1282
+ BasicStringRef<Char> name;
1283
+
1284
+ template <typename T>
1285
+ NamedArg(BasicStringRef<Char> argname, const T &value)
1286
+ : Arg(MakeArg< BasicFormatter<Char> >(value)), name(argname) {}
1287
+};
1288
+
1289
+class RuntimeError : public std::runtime_error {
1290
+ protected:
1291
+ RuntimeError() : std::runtime_error("") {}
1292
+};
1293
+
1294
+template <typename Char>
1295
+class PrintfArgFormatter;
1296
+
1297
+template <typename Char>
1298
+class ArgMap;
1299
+} // namespace internal
1300
+
1301
+/** An argument list. */
1302
+class ArgList {
1303
+ private:
1304
+ // To reduce compiled code size per formatting function call, types of first
1305
+ // MAX_PACKED_ARGS arguments are passed in the types_ field.
1306
+ uint64_t types_;
1307
+ union {
1308
+ // If the number of arguments is less than MAX_PACKED_ARGS, the argument
1309
+ // values are stored in values_, otherwise they are stored in args_.
1310
+ // This is done to reduce compiled code size as storing larger objects
1311
+ // may require more code (at least on x86-64) even if the same amount of
1312
+ // data is actually copied to stack. It saves ~10% on the bloat test.
1313
+ const internal::Value *values_;
1314
+ const internal::Arg *args_;
1315
+ };
1316
+
1317
+ internal::Arg::Type type(unsigned index) const {
1318
+ unsigned shift = index * 4;
1319
+ uint64_t mask = 0xf;
1320
+ return static_cast<internal::Arg::Type>(
1321
+ (types_ & (mask << shift)) >> shift);
1322
+ }
1323
+
1324
+ template <typename Char>
1325
+ friend class internal::ArgMap;
1326
+
1327
+ public:
1328
+ // Maximum number of arguments with packed types.
1329
+ enum { MAX_PACKED_ARGS = 16 };
1330
+
1331
+ ArgList() : types_(0) {}
1332
+
1333
+ ArgList(ULongLong types, const internal::Value *values)
1334
+ : types_(types), values_(values) {}
1335
+ ArgList(ULongLong types, const internal::Arg *args)
1336
+ : types_(types), args_(args) {}
1337
+
1338
+ /** Returns the argument at specified index. */
1339
+ internal::Arg operator[](unsigned index) const {
1340
+ using internal::Arg;
1341
+ Arg arg;
1342
+ bool use_values = type(MAX_PACKED_ARGS - 1) == Arg::NONE;
1343
+ if (index < MAX_PACKED_ARGS) {
1344
+ Arg::Type arg_type = type(index);
1345
+ internal::Value &val = arg;
1346
+ if (arg_type != Arg::NONE)
1347
+ val = use_values ? values_[index] : args_[index];
1348
+ arg.type = arg_type;
1349
+ return arg;
1350
+ }
1351
+ if (use_values) {
1352
+ // The index is greater than the number of arguments that can be stored
1353
+ // in values, so return a "none" argument.
1354
+ arg.type = Arg::NONE;
1355
+ return arg;
1356
+ }
1357
+ for (unsigned i = MAX_PACKED_ARGS; i <= index; ++i) {
1358
+ if (args_[i].type == Arg::NONE)
1359
+ return args_[i];
1360
+ }
1361
+ return args_[index];
1362
+ }
1363
+};
1364
+
1365
+#define FMT_DISPATCH(call) static_cast<Impl*>(this)->call
1366
+
1367
+/**
1368
+ \rst
1369
+ An argument visitor based on the `curiously recurring template pattern
1370
+ <http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern>`_.
1371
+
1372
+ To use `~fmt::ArgVisitor` define a subclass that implements some or all of the
1373
+ visit methods with the same signatures as the methods in `~fmt::ArgVisitor`,
1374
+ for example, `~fmt::ArgVisitor::visit_int()`.
1375
+ Pass the subclass as the *Impl* template parameter. Then calling
1376
+ `~fmt::ArgVisitor::visit` for some argument will dispatch to a visit method
1377
+ specific to the argument type. For example, if the argument type is
1378
+ ``double`` then the `~fmt::ArgVisitor::visit_double()` method of a subclass
1379
+ will be called. If the subclass doesn't contain a method with this signature,
1380
+ then a corresponding method of `~fmt::ArgVisitor` will be called.
1381
+
1382
+ **Example**::
1383
+
1384
+ class MyArgVisitor : public fmt::ArgVisitor<MyArgVisitor, void> {
1385
+ public:
1386
+ void visit_int(int value) { fmt::print("{}", value); }
1387
+ void visit_double(double value) { fmt::print("{}", value ); }
1388
+ };
1389
+ \endrst
1390
+ */
1391
+template <typename Impl, typename Result>
1392
+class ArgVisitor {
1393
+ private:
1394
+ typedef internal::Arg Arg;
1395
+
1396
+ public:
1397
+ void report_unhandled_arg() {}
1398
+
1399
+ Result visit_unhandled_arg() {
1400
+ FMT_DISPATCH(report_unhandled_arg());
1401
+ return Result();
1402
+ }
1403
+
1404
+ /** Visits an ``int`` argument. **/
1405
+ Result visit_int(int value) {
1406
+ return FMT_DISPATCH(visit_any_int(value));
1407
+ }
1408
+
1409
+ /** Visits a ``long long`` argument. **/
1410
+ Result visit_long_long(LongLong value) {
1411
+ return FMT_DISPATCH(visit_any_int(value));
1412
+ }
1413
+
1414
+ /** Visits an ``unsigned`` argument. **/
1415
+ Result visit_uint(unsigned value) {
1416
+ return FMT_DISPATCH(visit_any_int(value));
1417
+ }
1418
+
1419
+ /** Visits an ``unsigned long long`` argument. **/
1420
+ Result visit_ulong_long(ULongLong value) {
1421
+ return FMT_DISPATCH(visit_any_int(value));
1422
+ }
1423
+
1424
+ /** Visits a ``bool`` argument. **/
1425
+ Result visit_bool(bool value) {
1426
+ return FMT_DISPATCH(visit_any_int(value));
1427
+ }
1428
+
1429
+ /** Visits a ``char`` or ``wchar_t`` argument. **/
1430
+ Result visit_char(int value) {
1431
+ return FMT_DISPATCH(visit_any_int(value));
1432
+ }
1433
+
1434
+ /** Visits an argument of any integral type. **/
1435
+ template <typename T>
1436
+ Result visit_any_int(T) {
1437
+ return FMT_DISPATCH(visit_unhandled_arg());
1438
+ }
1439
+
1440
+ /** Visits a ``double`` argument. **/
1441
+ Result visit_double(double value) {
1442
+ return FMT_DISPATCH(visit_any_double(value));
1443
+ }
1444
+
1445
+ /** Visits a ``long double`` argument. **/
1446
+ Result visit_long_double(long double value) {
1447
+ return FMT_DISPATCH(visit_any_double(value));
1448
+ }
1449
+
1450
+ /** Visits a ``double`` or ``long double`` argument. **/
1451
+ template <typename T>
1452
+ Result visit_any_double(T) {
1453
+ return FMT_DISPATCH(visit_unhandled_arg());
1454
+ }
1455
+
1456
+ /** Visits a null-terminated C string (``const char *``) argument. **/
1457
+ Result visit_cstring(const char *) {
1458
+ return FMT_DISPATCH(visit_unhandled_arg());
1459
+ }
1460
+
1461
+ /** Visits a string argument. **/
1462
+ Result visit_string(Arg::StringValue<char>) {
1463
+ return FMT_DISPATCH(visit_unhandled_arg());
1464
+ }
1465
+
1466
+ /** Visits a wide string argument. **/
1467
+ Result visit_wstring(Arg::StringValue<wchar_t>) {
1468
+ return FMT_DISPATCH(visit_unhandled_arg());
1469
+ }
1470
+
1471
+ /** Visits a pointer argument. **/
1472
+ Result visit_pointer(const void *) {
1473
+ return FMT_DISPATCH(visit_unhandled_arg());
1474
+ }
1475
+
1476
+ /** Visits an argument of a custom (user-defined) type. **/
1477
+ Result visit_custom(Arg::CustomValue) {
1478
+ return FMT_DISPATCH(visit_unhandled_arg());
1479
+ }
1480
+
1481
+ /**
1482
+ \rst
1483
+ Visits an argument dispatching to the appropriate visit method based on
1484
+ the argument type. For example, if the argument type is ``double`` then
1485
+ the `~fmt::ArgVisitor::visit_double()` method of the *Impl* class will be
1486
+ called.
1487
+ \endrst
1488
+ */
1489
+ Result visit(const Arg &arg) {
1490
+ switch (arg.type) {
1491
+ default:
1492
+ FMT_ASSERT(false, "invalid argument type");
1493
+ return Result();
1494
+ case Arg::INT:
1495
+ return FMT_DISPATCH(visit_int(arg.int_value));
1496
+ case Arg::UINT:
1497
+ return FMT_DISPATCH(visit_uint(arg.uint_value));
1498
+ case Arg::LONG_LONG:
1499
+ return FMT_DISPATCH(visit_long_long(arg.long_long_value));
1500
+ case Arg::ULONG_LONG:
1501
+ return FMT_DISPATCH(visit_ulong_long(arg.ulong_long_value));
1502
+ case Arg::BOOL:
1503
+ return FMT_DISPATCH(visit_bool(arg.int_value != 0));
1504
+ case Arg::CHAR:
1505
+ return FMT_DISPATCH(visit_char(arg.int_value));
1506
+ case Arg::DOUBLE:
1507
+ return FMT_DISPATCH(visit_double(arg.double_value));
1508
+ case Arg::LONG_DOUBLE:
1509
+ return FMT_DISPATCH(visit_long_double(arg.long_double_value));
1510
+ case Arg::CSTRING:
1511
+ return FMT_DISPATCH(visit_cstring(arg.string.value));
1512
+ case Arg::STRING:
1513
+ return FMT_DISPATCH(visit_string(arg.string));
1514
+ case Arg::WSTRING:
1515
+ return FMT_DISPATCH(visit_wstring(arg.wstring));
1516
+ case Arg::POINTER:
1517
+ return FMT_DISPATCH(visit_pointer(arg.pointer));
1518
+ case Arg::CUSTOM:
1519
+ return FMT_DISPATCH(visit_custom(arg.custom));
1520
+ }
1521
+ }
1522
+};
1523
+
1524
+enum Alignment {
1525
+ ALIGN_DEFAULT, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTER, ALIGN_NUMERIC
1526
+};
1527
+
1528
+// Flags.
1529
+enum {
1530
+ SIGN_FLAG = 1, PLUS_FLAG = 2, MINUS_FLAG = 4, HASH_FLAG = 8,
1531
+ CHAR_FLAG = 0x10 // Argument has char type - used in error reporting.
1532
+};
1533
+
1534
+// An empty format specifier.
1535
+struct EmptySpec {};
1536
+
1537
+// A type specifier.
1538
+template <char TYPE>
1539
+struct TypeSpec : EmptySpec {
1540
+ Alignment align() const { return ALIGN_DEFAULT; }
1541
+ unsigned width() const { return 0; }
1542
+ int precision() const { return -1; }
1543
+ bool flag(unsigned) const { return false; }
1544
+ char type() const { return TYPE; }
1545
+ char fill() const { return ' '; }
1546
+};
1547
+
1548
+// A width specifier.
1549
+struct WidthSpec {
1550
+ unsigned width_;
1551
+ // Fill is always wchar_t and cast to char if necessary to avoid having
1552
+ // two specialization of WidthSpec and its subclasses.
1553
+ wchar_t fill_;
1554
+
1555
+ WidthSpec(unsigned width, wchar_t fill) : width_(width), fill_(fill) {}
1556
+
1557
+ unsigned width() const { return width_; }
1558
+ wchar_t fill() const { return fill_; }
1559
+};
1560
+
1561
+// An alignment specifier.
1562
+struct AlignSpec : WidthSpec {
1563
+ Alignment align_;
1564
+
1565
+ AlignSpec(unsigned width, wchar_t fill, Alignment align = ALIGN_DEFAULT)
1566
+ : WidthSpec(width, fill), align_(align) {}
1567
+
1568
+ Alignment align() const { return align_; }
1569
+
1570
+ int precision() const { return -1; }
1571
+};
1572
+
1573
+// An alignment and type specifier.
1574
+template <char TYPE>
1575
+struct AlignTypeSpec : AlignSpec {
1576
+ AlignTypeSpec(unsigned width, wchar_t fill) : AlignSpec(width, fill) {}
1577
+
1578
+ bool flag(unsigned) const { return false; }
1579
+ char type() const { return TYPE; }
1580
+};
1581
+
1582
+// A full format specifier.
1583
+struct FormatSpec : AlignSpec {
1584
+ unsigned flags_;
1585
+ int precision_;
1586
+ char type_;
1587
+
1588
+ FormatSpec(
1589
+ unsigned width = 0, char type = 0, wchar_t fill = ' ')
1590
+ : AlignSpec(width, fill), flags_(0), precision_(-1), type_(type) {}
1591
+
1592
+ bool flag(unsigned f) const { return (flags_ & f) != 0; }
1593
+ int precision() const { return precision_; }
1594
+ char type() const { return type_; }
1595
+};
1596
+
1597
+// An integer format specifier.
1598
+template <typename T, typename SpecT = TypeSpec<0>, typename Char = char>
1599
+class IntFormatSpec : public SpecT {
1600
+ private:
1601
+ T value_;
1602
+
1603
+ public:
1604
+ IntFormatSpec(T val, const SpecT &spec = SpecT())
1605
+ : SpecT(spec), value_(val) {}
1606
+
1607
+ T value() const { return value_; }
1608
+};
1609
+
1610
+// A string format specifier.
1611
+template <typename Char>
1612
+class StrFormatSpec : public AlignSpec {
1613
+ private:
1614
+ const Char *str_;
1615
+
1616
+ public:
1617
+ template <typename FillChar>
1618
+ StrFormatSpec(const Char *str, unsigned width, FillChar fill)
1619
+ : AlignSpec(width, fill), str_(str) {
1620
+ internal::CharTraits<Char>::convert(FillChar());
1621
+ }
1622
+
1623
+ const Char *str() const { return str_; }
1624
+};
1625
+
1626
+/**
1627
+ Returns an integer format specifier to format the value in base 2.
1628
+ */
1629
+IntFormatSpec<int, TypeSpec<'b'> > bin(int value);
1630
+
1631
+/**
1632
+ Returns an integer format specifier to format the value in base 8.
1633
+ */
1634
+IntFormatSpec<int, TypeSpec<'o'> > oct(int value);
1635
+
1636
+/**
1637
+ Returns an integer format specifier to format the value in base 16 using
1638
+ lower-case letters for the digits above 9.
1639
+ */
1640
+IntFormatSpec<int, TypeSpec<'x'> > hex(int value);
1641
+
1642
+/**
1643
+ Returns an integer formatter format specifier to format in base 16 using
1644
+ upper-case letters for the digits above 9.
1645
+ */
1646
+IntFormatSpec<int, TypeSpec<'X'> > hexu(int value);
1647
+
1648
+/**
1649
+ \rst
1650
+ Returns an integer format specifier to pad the formatted argument with the
1651
+ fill character to the specified width using the default (right) numeric
1652
+ alignment.
1653
+
1654
+ **Example**::
1655
+
1656
+ MemoryWriter out;
1657
+ out << pad(hex(0xcafe), 8, '0');
1658
+ // out.str() == "0000cafe"
1659
+
1660
+ \endrst
1661
+ */
1662
+template <char TYPE_CODE, typename Char>
1663
+IntFormatSpec<int, AlignTypeSpec<TYPE_CODE>, Char> pad(
1664
+ int value, unsigned width, Char fill = ' ');
1665
+
1666
+#define FMT_DEFINE_INT_FORMATTERS(TYPE) \
1667
+inline IntFormatSpec<TYPE, TypeSpec<'b'> > bin(TYPE value) { \
1668
+ return IntFormatSpec<TYPE, TypeSpec<'b'> >(value, TypeSpec<'b'>()); \
1669
+} \
1670
+ \
1671
+inline IntFormatSpec<TYPE, TypeSpec<'o'> > oct(TYPE value) { \
1672
+ return IntFormatSpec<TYPE, TypeSpec<'o'> >(value, TypeSpec<'o'>()); \
1673
+} \
1674
+ \
1675
+inline IntFormatSpec<TYPE, TypeSpec<'x'> > hex(TYPE value) { \
1676
+ return IntFormatSpec<TYPE, TypeSpec<'x'> >(value, TypeSpec<'x'>()); \
1677
+} \
1678
+ \
1679
+inline IntFormatSpec<TYPE, TypeSpec<'X'> > hexu(TYPE value) { \
1680
+ return IntFormatSpec<TYPE, TypeSpec<'X'> >(value, TypeSpec<'X'>()); \
1681
+} \
1682
+ \
1683
+template <char TYPE_CODE> \
1684
+inline IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE> > pad( \
1685
+ IntFormatSpec<TYPE, TypeSpec<TYPE_CODE> > f, unsigned width) { \
1686
+ return IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE> >( \
1687
+ f.value(), AlignTypeSpec<TYPE_CODE>(width, ' ')); \
1688
+} \
1689
+ \
1690
+/* For compatibility with older compilers we provide two overloads for pad, */ \
1691
+/* one that takes a fill character and one that doesn't. In the future this */ \
1692
+/* can be replaced with one overload making the template argument Char */ \
1693
+/* default to char (C++11). */ \
1694
+template <char TYPE_CODE, typename Char> \
1695
+inline IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE>, Char> pad( \
1696
+ IntFormatSpec<TYPE, TypeSpec<TYPE_CODE>, Char> f, \
1697
+ unsigned width, Char fill) { \
1698
+ return IntFormatSpec<TYPE, AlignTypeSpec<TYPE_CODE>, Char>( \
1699
+ f.value(), AlignTypeSpec<TYPE_CODE>(width, fill)); \
1700
+} \
1701
+ \
1702
+inline IntFormatSpec<TYPE, AlignTypeSpec<0> > pad( \
1703
+ TYPE value, unsigned width) { \
1704
+ return IntFormatSpec<TYPE, AlignTypeSpec<0> >( \
1705
+ value, AlignTypeSpec<0>(width, ' ')); \
1706
+} \
1707
+ \
1708
+template <typename Char> \
1709
+inline IntFormatSpec<TYPE, AlignTypeSpec<0>, Char> pad( \
1710
+ TYPE value, unsigned width, Char fill) { \
1711
+ return IntFormatSpec<TYPE, AlignTypeSpec<0>, Char>( \
1712
+ value, AlignTypeSpec<0>(width, fill)); \
1713
+}
1714
+
1715
+FMT_DEFINE_INT_FORMATTERS(int)
1716
+FMT_DEFINE_INT_FORMATTERS(long)
1717
+FMT_DEFINE_INT_FORMATTERS(unsigned)
1718
+FMT_DEFINE_INT_FORMATTERS(unsigned long)
1719
+FMT_DEFINE_INT_FORMATTERS(LongLong)
1720
+FMT_DEFINE_INT_FORMATTERS(ULongLong)
1721
+
1722
+/**
1723
+ \rst
1724
+ Returns a string formatter that pads the formatted argument with the fill
1725
+ character to the specified width using the default (left) string alignment.
1726
+
1727
+ **Example**::
1728
+
1729
+ std::string s = str(MemoryWriter() << pad("abc", 8));
1730
+ // s == "abc "
1731
+
1732
+ \endrst
1733
+ */
1734
+template <typename Char>
1735
+inline StrFormatSpec<Char> pad(
1736
+ const Char *str, unsigned width, Char fill = ' ') {
1737
+ return StrFormatSpec<Char>(str, width, fill);
1738
+}
1739
+
1740
+inline StrFormatSpec<wchar_t> pad(
1741
+ const wchar_t *str, unsigned width, char fill = ' ') {
1742
+ return StrFormatSpec<wchar_t>(str, width, fill);
1743
+}
1744
+
1745
+namespace internal {
1746
+
1747
+template <typename Char>
1748
+class ArgMap {
1749
+ private:
1750
+ typedef std::vector<
1751
+ std::pair<fmt::BasicStringRef<Char>, internal::Arg> > MapType;
1752
+ typedef typename MapType::value_type Pair;
1753
+
1754
+ MapType map_;
1755
+
1756
+ public:
1757
+ FMT_API void init(const ArgList &args);
1758
+
1759
+ const internal::Arg* find(const fmt::BasicStringRef<Char> &name) const {
1760
+ // The list is unsorted, so just return the first matching name.
1761
+ for (typename MapType::const_iterator it = map_.begin(), end = map_.end();
1762
+ it != end; ++it) {
1763
+ if (it->first == name)
1764
+ return &it->second;
1765
+ }
1766
+ return 0;
1767
+ }
1768
+};
1769
+
1770
+template <typename Impl, typename Char>
1771
+class ArgFormatterBase : public ArgVisitor<Impl, void> {
1772
+ private:
1773
+ BasicWriter<Char> &writer_;
1774
+ FormatSpec &spec_;
1775
+
1776
+ FMT_DISALLOW_COPY_AND_ASSIGN(ArgFormatterBase);
1777
+
1778
+ void write_pointer(const void *p) {
1779
+ spec_.flags_ = HASH_FLAG;
1780
+ spec_.type_ = 'x';
1781
+ writer_.write_int(reinterpret_cast<uintptr_t>(p), spec_);
1782
+ }
1783
+
1784
+ protected:
1785
+ BasicWriter<Char> &writer() { return writer_; }
1786
+ FormatSpec &spec() { return spec_; }
1787
+
1788
+ void write(bool value) {
1789
+ const char *str_value = value ? "true" : "false";
1790
+ Arg::StringValue<char> str = { str_value, std::strlen(str_value) };
1791
+ writer_.write_str(str, spec_);
1792
+ }
1793
+
1794
+ void write(const char *value) {
1795
+ Arg::StringValue<char> str = {value, value != 0 ? std::strlen(value) : 0};
1796
+ writer_.write_str(str, spec_);
1797
+ }
1798
+
1799
+ public:
1800
+ ArgFormatterBase(BasicWriter<Char> &w, FormatSpec &s)
1801
+ : writer_(w), spec_(s) {}
1802
+
1803
+ template <typename T>
1804
+ void visit_any_int(T value) { writer_.write_int(value, spec_); }
1805
+
1806
+ template <typename T>
1807
+ void visit_any_double(T value) { writer_.write_double(value, spec_); }
1808
+
1809
+ void visit_bool(bool value) {
1810
+ if (spec_.type_)
1811
+ return visit_any_int(value);
1812
+ write(value);
1813
+ }
1814
+
1815
+ void visit_char(int value) {
1816
+ if (spec_.type_ && spec_.type_ != 'c') {
1817
+ spec_.flags_ |= CHAR_FLAG;
1818
+ writer_.write_int(value, spec_);
1819
+ return;
1820
+ }
1821
+ if (spec_.align_ == ALIGN_NUMERIC || spec_.flags_ != 0)
1822
+ FMT_THROW(FormatError("invalid format specifier for char"));
1823
+ typedef typename BasicWriter<Char>::CharPtr CharPtr;
1824
+ Char fill = internal::CharTraits<Char>::cast(spec_.fill());
1825
+ CharPtr out = CharPtr();
1826
+ const unsigned CHAR_WIDTH = 1;
1827
+ if (spec_.width_ > CHAR_WIDTH) {
1828
+ out = writer_.grow_buffer(spec_.width_);
1829
+ if (spec_.align_ == ALIGN_RIGHT) {
1830
+ std::uninitialized_fill_n(out, spec_.width_ - CHAR_WIDTH, fill);
1831
+ out += spec_.width_ - CHAR_WIDTH;
1832
+ } else if (spec_.align_ == ALIGN_CENTER) {
1833
+ out = writer_.fill_padding(out, spec_.width_,
1834
+ internal::check(CHAR_WIDTH), fill);
1835
+ } else {
1836
+ std::uninitialized_fill_n(out + CHAR_WIDTH,
1837
+ spec_.width_ - CHAR_WIDTH, fill);
1838
+ }
1839
+ } else {
1840
+ out = writer_.grow_buffer(CHAR_WIDTH);
1841
+ }
1842
+ *out = internal::CharTraits<Char>::cast(value);
1843
+ }
1844
+
1845
+ void visit_cstring(const char *value) {
1846
+ if (spec_.type_ == 'p')
1847
+ return write_pointer(value);
1848
+ write(value);
1849
+ }
1850
+
1851
+ void visit_string(Arg::StringValue<char> value) {
1852
+ writer_.write_str(value, spec_);
1853
+ }
1854
+
1855
+ using ArgVisitor<Impl, void>::visit_wstring;
1856
+
1857
+ void visit_wstring(Arg::StringValue<Char> value) {
1858
+ writer_.write_str(value, spec_);
1859
+ }
1860
+
1861
+ void visit_pointer(const void *value) {
1862
+ if (spec_.type_ && spec_.type_ != 'p')
1863
+ report_unknown_type(spec_.type_, "pointer");
1864
+ write_pointer(value);
1865
+ }
1866
+};
1867
+
1868
+class FormatterBase {
1869
+ private:
1870
+ ArgList args_;
1871
+ int next_arg_index_;
1872
+
1873
+ // Returns the argument with specified index.
1874
+ FMT_API Arg do_get_arg(unsigned arg_index, const char *&error);
1875
+
1876
+ protected:
1877
+ const ArgList &args() const { return args_; }
1878
+
1879
+ explicit FormatterBase(const ArgList &args) {
1880
+ args_ = args;
1881
+ next_arg_index_ = 0;
1882
+ }
1883
+
1884
+ // Returns the next argument.
1885
+ Arg next_arg(const char *&error) {
1886
+ if (next_arg_index_ >= 0)
1887
+ return do_get_arg(internal::to_unsigned(next_arg_index_++), error);
1888
+ error = "cannot switch from manual to automatic argument indexing";
1889
+ return Arg();
1890
+ }
1891
+
1892
+ // Checks if manual indexing is used and returns the argument with
1893
+ // specified index.
1894
+ Arg get_arg(unsigned arg_index, const char *&error) {
1895
+ return check_no_auto_index(error) ? do_get_arg(arg_index, error) : Arg();
1896
+ }
1897
+
1898
+ bool check_no_auto_index(const char *&error) {
1899
+ if (next_arg_index_ > 0) {
1900
+ error = "cannot switch from automatic to manual argument indexing";
1901
+ return false;
1902
+ }
1903
+ next_arg_index_ = -1;
1904
+ return true;
1905
+ }
1906
+
1907
+ template <typename Char>
1908
+ void write(BasicWriter<Char> &w, const Char *start, const Char *end) {
1909
+ if (start != end)
1910
+ w << BasicStringRef<Char>(start, internal::to_unsigned(end - start));
1911
+ }
1912
+};
1913
+
1914
+// A printf formatter.
1915
+template <typename Char>
1916
+class PrintfFormatter : private FormatterBase {
1917
+ private:
1918
+ void parse_flags(FormatSpec &spec, const Char *&s);
1919
+
1920
+ // Returns the argument with specified index or, if arg_index is equal
1921
+ // to the maximum unsigned value, the next argument.
1922
+ Arg get_arg(const Char *s,
1923
+ unsigned arg_index = (std::numeric_limits<unsigned>::max)());
1924
+
1925
+ // Parses argument index, flags and width and returns the argument index.
1926
+ unsigned parse_header(const Char *&s, FormatSpec &spec);
1927
+
1928
+ public:
1929
+ explicit PrintfFormatter(const ArgList &args) : FormatterBase(args) {}
1930
+ FMT_API void format(BasicWriter<Char> &writer,
1931
+ BasicCStringRef<Char> format_str);
1932
+};
1933
+} // namespace internal
1934
+
1935
+/**
1936
+ \rst
1937
+ An argument formatter based on the `curiously recurring template pattern
1938
+ <http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern>`_.
1939
+
1940
+ To use `~fmt::BasicArgFormatter` define a subclass that implements some or
1941
+ all of the visit methods with the same signatures as the methods in
1942
+ `~fmt::ArgVisitor`, for example, `~fmt::ArgVisitor::visit_int()`.
1943
+ Pass the subclass as the *Impl* template parameter. When a formatting
1944
+ function processes an argument, it will dispatch to a visit method
1945
+ specific to the argument type. For example, if the argument type is
1946
+ ``double`` then the `~fmt::ArgVisitor::visit_double()` method of a subclass
1947
+ will be called. If the subclass doesn't contain a method with this signature,
1948
+ then a corresponding method of `~fmt::BasicArgFormatter` or its superclass
1949
+ will be called.
1950
+ \endrst
1951
+ */
1952
+template <typename Impl, typename Char>
1953
+class BasicArgFormatter : public internal::ArgFormatterBase<Impl, Char> {
1954
+ private:
1955
+ BasicFormatter<Char, Impl> &formatter_;
1956
+ const Char *format_;
1957
+
1958
+ public:
1959
+ /**
1960
+ \rst
1961
+ Constructs an argument formatter object.
1962
+ *formatter* is a reference to the main formatter object, *spec* contains
1963
+ format specifier information for standard argument types, and *fmt* points
1964
+ to the part of the format string being parsed for custom argument types.
1965
+ \endrst
1966
+ */
1967
+ BasicArgFormatter(BasicFormatter<Char, Impl> &formatter,
1968
+ FormatSpec &spec, const Char *fmt)
1969
+ : internal::ArgFormatterBase<Impl, Char>(formatter.writer(), spec),
1970
+ formatter_(formatter), format_(fmt) {}
1971
+
1972
+ /** Formats argument of a custom (user-defined) type. */
1973
+ void visit_custom(internal::Arg::CustomValue c) {
1974
+ c.format(&formatter_, c.value, &format_);
1975
+ }
1976
+};
1977
+
1978
+/** The default argument formatter. */
1979
+template <typename Char>
1980
+class ArgFormatter : public BasicArgFormatter<ArgFormatter<Char>, Char> {
1981
+ public:
1982
+ /** Constructs an argument formatter object. */
1983
+ ArgFormatter(BasicFormatter<Char> &formatter,
1984
+ FormatSpec &spec, const Char *fmt)
1985
+ : BasicArgFormatter<ArgFormatter<Char>, Char>(formatter, spec, fmt) {}
1986
+};
1987
+
1988
+/** This template formats data and writes the output to a writer. */
1989
+template <typename CharType, typename ArgFormatter>
1990
+class BasicFormatter : private internal::FormatterBase {
1991
+ public:
1992
+ /** The character type for the output. */
1993
+ typedef CharType Char;
1994
+
1995
+ private:
1996
+ BasicWriter<Char> &writer_;
1997
+ internal::ArgMap<Char> map_;
1998
+
1999
+ FMT_DISALLOW_COPY_AND_ASSIGN(BasicFormatter);
2000
+
2001
+ using internal::FormatterBase::get_arg;
2002
+
2003
+ // Checks if manual indexing is used and returns the argument with
2004
+ // specified name.
2005
+ internal::Arg get_arg(BasicStringRef<Char> arg_name, const char *&error);
2006
+
2007
+ // Parses argument index and returns corresponding argument.
2008
+ internal::Arg parse_arg_index(const Char *&s);
2009
+
2010
+ // Parses argument name and returns corresponding argument.
2011
+ internal::Arg parse_arg_name(const Char *&s);
2012
+
2013
+ public:
2014
+ /**
2015
+ \rst
2016
+ Constructs a ``BasicFormatter`` object. References to the arguments and
2017
+ the writer are stored in the formatter object so make sure they have
2018
+ appropriate lifetimes.
2019
+ \endrst
2020
+ */
2021
+ BasicFormatter(const ArgList &args, BasicWriter<Char> &w)
2022
+ : internal::FormatterBase(args), writer_(w) {}
2023
+
2024
+ /** Returns a reference to the writer associated with this formatter. */
2025
+ BasicWriter<Char> &writer() { return writer_; }
2026
+
2027
+ /** Formats stored arguments and writes the output to the writer. */
2028
+ void format(BasicCStringRef<Char> format_str);
2029
+
2030
+ // Formats a single argument and advances format_str, a format string pointer.
2031
+ const Char *format(const Char *&format_str, const internal::Arg &arg);
2032
+};
2033
+
2034
+// Generates a comma-separated list with results of applying f to
2035
+// numbers 0..n-1.
2036
+# define FMT_GEN(n, f) FMT_GEN##n(f)
2037
+# define FMT_GEN1(f) f(0)
2038
+# define FMT_GEN2(f) FMT_GEN1(f), f(1)
2039
+# define FMT_GEN3(f) FMT_GEN2(f), f(2)
2040
+# define FMT_GEN4(f) FMT_GEN3(f), f(3)
2041
+# define FMT_GEN5(f) FMT_GEN4(f), f(4)
2042
+# define FMT_GEN6(f) FMT_GEN5(f), f(5)
2043
+# define FMT_GEN7(f) FMT_GEN6(f), f(6)
2044
+# define FMT_GEN8(f) FMT_GEN7(f), f(7)
2045
+# define FMT_GEN9(f) FMT_GEN8(f), f(8)
2046
+# define FMT_GEN10(f) FMT_GEN9(f), f(9)
2047
+# define FMT_GEN11(f) FMT_GEN10(f), f(10)
2048
+# define FMT_GEN12(f) FMT_GEN11(f), f(11)
2049
+# define FMT_GEN13(f) FMT_GEN12(f), f(12)
2050
+# define FMT_GEN14(f) FMT_GEN13(f), f(13)
2051
+# define FMT_GEN15(f) FMT_GEN14(f), f(14)
2052
+
2053
+namespace internal {
2054
+inline uint64_t make_type() { return 0; }
2055
+
2056
+template <typename T>
2057
+inline uint64_t make_type(const T &arg) {
2058
+ return MakeValue< BasicFormatter<char> >::type(arg);
2059
+}
2060
+
2061
+template <unsigned N, bool/*IsPacked*/= (N < ArgList::MAX_PACKED_ARGS)>
2062
+struct ArgArray;
2063
+
2064
+template <unsigned N>
2065
+struct ArgArray<N, true/*IsPacked*/> {
2066
+ typedef Value Type[N > 0 ? N : 1];
2067
+
2068
+ template <typename Formatter, typename T>
2069
+ static Value make(const T &value) {
2070
+#ifdef __clang__
2071
+ Value result = MakeValue<Formatter>(value);
2072
+ // Workaround a bug in Apple LLVM version 4.2 (clang-425.0.28) of clang:
2073
+ // https://github.com/fmtlib/fmt/issues/276
2074
+ (void)result.custom.format;
2075
+ return result;
2076
+#else
2077
+ return MakeValue<Formatter>(value);
2078
+#endif
2079
+ }
2080
+};
2081
+
2082
+template <unsigned N>
2083
+struct ArgArray<N, false/*IsPacked*/> {
2084
+ typedef Arg Type[N + 1]; // +1 for the list end Arg::NONE
2085
+
2086
+ template <typename Formatter, typename T>
2087
+ static Arg make(const T &value) { return MakeArg<Formatter>(value); }
2088
+};
2089
+
2090
+#if FMT_USE_VARIADIC_TEMPLATES
2091
+template <typename Arg, typename... Args>
2092
+inline uint64_t make_type(const Arg &first, const Args & ... tail) {
2093
+ return make_type(first) | (make_type(tail...) << 4);
2094
+}
2095
+
2096
+#else
2097
+
2098
+struct ArgType {
2099
+ uint64_t type;
2100
+
2101
+ ArgType() : type(0) {}
2102
+
2103
+ template <typename T>
2104
+ ArgType(const T &arg) : type(make_type(arg)) {}
2105
+};
2106
+
2107
+# define FMT_ARG_TYPE_DEFAULT(n) ArgType t##n = ArgType()
2108
+
2109
+inline uint64_t make_type(FMT_GEN15(FMT_ARG_TYPE_DEFAULT)) {
2110
+ return t0.type | (t1.type << 4) | (t2.type << 8) | (t3.type << 12) |
2111
+ (t4.type << 16) | (t5.type << 20) | (t6.type << 24) | (t7.type << 28) |
2112
+ (t8.type << 32) | (t9.type << 36) | (t10.type << 40) | (t11.type << 44) |
2113
+ (t12.type << 48) | (t13.type << 52) | (t14.type << 56);
2114
+}
2115
+#endif
2116
+} // namespace internal
2117
+
2118
+# define FMT_MAKE_TEMPLATE_ARG(n) typename T##n
2119
+# define FMT_MAKE_ARG_TYPE(n) T##n
2120
+# define FMT_MAKE_ARG(n) const T##n &v##n
2121
+# define FMT_ASSIGN_char(n) \
2122
+ arr[n] = fmt::internal::MakeValue< fmt::BasicFormatter<char> >(v##n)
2123
+# define FMT_ASSIGN_wchar_t(n) \
2124
+ arr[n] = fmt::internal::MakeValue< fmt::BasicFormatter<wchar_t> >(v##n)
2125
+
2126
+#if FMT_USE_VARIADIC_TEMPLATES
2127
+// Defines a variadic function returning void.
2128
+# define FMT_VARIADIC_VOID(func, arg_type) \
2129
+ template <typename... Args> \
2130
+ void func(arg_type arg0, const Args & ... args) { \
2131
+ typedef fmt::internal::ArgArray<sizeof...(Args)> ArgArray; \
2132
+ typename ArgArray::Type array{ \
2133
+ ArgArray::template make<fmt::BasicFormatter<Char> >(args)...}; \
2134
+ func(arg0, fmt::ArgList(fmt::internal::make_type(args...), array)); \
2135
+ }
2136
+
2137
+// Defines a variadic constructor.
2138
+# define FMT_VARIADIC_CTOR(ctor, func, arg0_type, arg1_type) \
2139
+ template <typename... Args> \
2140
+ ctor(arg0_type arg0, arg1_type arg1, const Args & ... args) { \
2141
+ typedef fmt::internal::ArgArray<sizeof...(Args)> ArgArray; \
2142
+ typename ArgArray::Type array{ \
2143
+ ArgArray::template make<fmt::BasicFormatter<Char> >(args)...}; \
2144
+ func(arg0, arg1, fmt::ArgList(fmt::internal::make_type(args...), array)); \
2145
+ }
2146
+
2147
+#else
2148
+
2149
+# define FMT_MAKE_REF(n) \
2150
+ fmt::internal::MakeValue< fmt::BasicFormatter<Char> >(v##n)
2151
+# define FMT_MAKE_REF2(n) v##n
2152
+
2153
+// Defines a wrapper for a function taking one argument of type arg_type
2154
+// and n additional arguments of arbitrary types.
2155
+# define FMT_WRAP1(func, arg_type, n) \
2156
+ template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
2157
+ inline void func(arg_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \
2158
+ const fmt::internal::ArgArray<n>::Type array = {FMT_GEN(n, FMT_MAKE_REF)}; \
2159
+ func(arg1, fmt::ArgList( \
2160
+ fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), array)); \
2161
+ }
2162
+
2163
+// Emulates a variadic function returning void on a pre-C++11 compiler.
2164
+# define FMT_VARIADIC_VOID(func, arg_type) \
2165
+ inline void func(arg_type arg) { func(arg, fmt::ArgList()); } \
2166
+ FMT_WRAP1(func, arg_type, 1) FMT_WRAP1(func, arg_type, 2) \
2167
+ FMT_WRAP1(func, arg_type, 3) FMT_WRAP1(func, arg_type, 4) \
2168
+ FMT_WRAP1(func, arg_type, 5) FMT_WRAP1(func, arg_type, 6) \
2169
+ FMT_WRAP1(func, arg_type, 7) FMT_WRAP1(func, arg_type, 8) \
2170
+ FMT_WRAP1(func, arg_type, 9) FMT_WRAP1(func, arg_type, 10)
2171
+
2172
+# define FMT_CTOR(ctor, func, arg0_type, arg1_type, n) \
2173
+ template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
2174
+ ctor(arg0_type arg0, arg1_type arg1, FMT_GEN(n, FMT_MAKE_ARG)) { \
2175
+ const fmt::internal::ArgArray<n>::Type array = {FMT_GEN(n, FMT_MAKE_REF)}; \
2176
+ func(arg0, arg1, fmt::ArgList( \
2177
+ fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), array)); \
2178
+ }
2179
+
2180
+// Emulates a variadic constructor on a pre-C++11 compiler.
2181
+# define FMT_VARIADIC_CTOR(ctor, func, arg0_type, arg1_type) \
2182
+ FMT_CTOR(ctor, func, arg0_type, arg1_type, 1) \
2183
+ FMT_CTOR(ctor, func, arg0_type, arg1_type, 2) \
2184
+ FMT_CTOR(ctor, func, arg0_type, arg1_type, 3) \
2185
+ FMT_CTOR(ctor, func, arg0_type, arg1_type, 4) \
2186
+ FMT_CTOR(ctor, func, arg0_type, arg1_type, 5) \
2187
+ FMT_CTOR(ctor, func, arg0_type, arg1_type, 6) \
2188
+ FMT_CTOR(ctor, func, arg0_type, arg1_type, 7) \
2189
+ FMT_CTOR(ctor, func, arg0_type, arg1_type, 8) \
2190
+ FMT_CTOR(ctor, func, arg0_type, arg1_type, 9) \
2191
+ FMT_CTOR(ctor, func, arg0_type, arg1_type, 10)
2192
+#endif
2193
+
2194
+// Generates a comma-separated list with results of applying f to pairs
2195
+// (argument, index).
2196
+#define FMT_FOR_EACH1(f, x0) f(x0, 0)
2197
+#define FMT_FOR_EACH2(f, x0, x1) \
2198
+ FMT_FOR_EACH1(f, x0), f(x1, 1)
2199
+#define FMT_FOR_EACH3(f, x0, x1, x2) \
2200
+ FMT_FOR_EACH2(f, x0 ,x1), f(x2, 2)
2201
+#define FMT_FOR_EACH4(f, x0, x1, x2, x3) \
2202
+ FMT_FOR_EACH3(f, x0, x1, x2), f(x3, 3)
2203
+#define FMT_FOR_EACH5(f, x0, x1, x2, x3, x4) \
2204
+ FMT_FOR_EACH4(f, x0, x1, x2, x3), f(x4, 4)
2205
+#define FMT_FOR_EACH6(f, x0, x1, x2, x3, x4, x5) \
2206
+ FMT_FOR_EACH5(f, x0, x1, x2, x3, x4), f(x5, 5)
2207
+#define FMT_FOR_EACH7(f, x0, x1, x2, x3, x4, x5, x6) \
2208
+ FMT_FOR_EACH6(f, x0, x1, x2, x3, x4, x5), f(x6, 6)
2209
+#define FMT_FOR_EACH8(f, x0, x1, x2, x3, x4, x5, x6, x7) \
2210
+ FMT_FOR_EACH7(f, x0, x1, x2, x3, x4, x5, x6), f(x7, 7)
2211
+#define FMT_FOR_EACH9(f, x0, x1, x2, x3, x4, x5, x6, x7, x8) \
2212
+ FMT_FOR_EACH8(f, x0, x1, x2, x3, x4, x5, x6, x7), f(x8, 8)
2213
+#define FMT_FOR_EACH10(f, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9) \
2214
+ FMT_FOR_EACH9(f, x0, x1, x2, x3, x4, x5, x6, x7, x8), f(x9, 9)
2215
+
2216
+/**
2217
+ An error returned by an operating system or a language runtime,
2218
+ for example a file opening error.
2219
+*/
2220
+class SystemError : public internal::RuntimeError {
2221
+ private:
2222
+ void init(int err_code, CStringRef format_str, ArgList args);
2223
+
2224
+ protected:
2225
+ int error_code_;
2226
+
2227
+ typedef char Char; // For FMT_VARIADIC_CTOR.
2228
+
2229
+ SystemError() {}
2230
+
2231
+ public:
2232
+ /**
2233
+ \rst
2234
+ Constructs a :class:`fmt::SystemError` object with the description
2235
+ of the form
2236
+
2237
+ .. parsed-literal::
2238
+ *<message>*: *<system-message>*
2239
+
2240
+ where *<message>* is the formatted message and *<system-message>* is
2241
+ the system message corresponding to the error code.
2242
+ *error_code* is a system error code as given by ``errno``.
2243
+ If *error_code* is not a valid error code such as -1, the system message
2244
+ may look like "Unknown error -1" and is platform-dependent.
2245
+
2246
+ **Example**::
2247
+
2248
+ // This throws a SystemError with the description
2249
+ // cannot open file 'madeup': No such file or directory
2250
+ // or similar (system message may vary).
2251
+ const char *filename = "madeup";
2252
+ std::FILE *file = std::fopen(filename, "r");
2253
+ if (!file)
2254
+ throw fmt::SystemError(errno, "cannot open file '{}'", filename);
2255
+ \endrst
2256
+ */
2257
+ SystemError(int error_code, CStringRef message) {
2258
+ init(error_code, message, ArgList());
2259
+ }
2260
+ FMT_VARIADIC_CTOR(SystemError, init, int, CStringRef)
2261
+
2262
+ int error_code() const { return error_code_; }
2263
+};
2264
+
2265
+/**
2266
+ \rst
2267
+ This template provides operations for formatting and writing data into
2268
+ a character stream. The output is stored in a buffer provided by a subclass
2269
+ such as :class:`fmt::BasicMemoryWriter`.
2270
+
2271
+ You can use one of the following typedefs for common character types:
2272
+
2273
+ +---------+----------------------+
2274
+ | Type | Definition |
2275
+ +=========+======================+
2276
+ | Writer | BasicWriter<char> |
2277
+ +---------+----------------------+
2278
+ | WWriter | BasicWriter<wchar_t> |
2279
+ +---------+----------------------+
2280
+
2281
+ \endrst
2282
+ */
2283
+template <typename Char>
2284
+class BasicWriter {
2285
+ private:
2286
+ // Output buffer.
2287
+ Buffer<Char> &buffer_;
2288
+
2289
+ FMT_DISALLOW_COPY_AND_ASSIGN(BasicWriter);
2290
+
2291
+ typedef typename internal::CharTraits<Char>::CharPtr CharPtr;
2292
+
2293
+#if FMT_SECURE_SCL
2294
+ // Returns pointer value.
2295
+ static Char *get(CharPtr p) { return p.base(); }
2296
+#else
2297
+ static Char *get(Char *p) { return p; }
2298
+#endif
2299
+
2300
+ // Fills the padding around the content and returns the pointer to the
2301
+ // content area.
2302
+ static CharPtr fill_padding(CharPtr buffer,
2303
+ unsigned total_size, std::size_t content_size, wchar_t fill);
2304
+
2305
+ // Grows the buffer by n characters and returns a pointer to the newly
2306
+ // allocated area.
2307
+ CharPtr grow_buffer(std::size_t n) {
2308
+ std::size_t size = buffer_.size();
2309
+ buffer_.resize(size + n);
2310
+ return internal::make_ptr(&buffer_[size], n);
2311
+ }
2312
+
2313
+ // Writes an unsigned decimal integer.
2314
+ template <typename UInt>
2315
+ Char *write_unsigned_decimal(UInt value, unsigned prefix_size = 0) {
2316
+ unsigned num_digits = internal::count_digits(value);
2317
+ Char *ptr = get(grow_buffer(prefix_size + num_digits));
2318
+ internal::format_decimal(ptr + prefix_size, value, num_digits);
2319
+ return ptr;
2320
+ }
2321
+
2322
+ // Writes a decimal integer.
2323
+ template <typename Int>
2324
+ void write_decimal(Int value) {
2325
+ typedef typename internal::IntTraits<Int>::MainType MainType;
2326
+ MainType abs_value = static_cast<MainType>(value);
2327
+ if (internal::is_negative(value)) {
2328
+ abs_value = 0 - abs_value;
2329
+ *write_unsigned_decimal(abs_value, 1) = '-';
2330
+ } else {
2331
+ write_unsigned_decimal(abs_value, 0);
2332
+ }
2333
+ }
2334
+
2335
+ // Prepare a buffer for integer formatting.
2336
+ CharPtr prepare_int_buffer(unsigned num_digits,
2337
+ const EmptySpec &, const char *prefix, unsigned prefix_size) {
2338
+ unsigned size = prefix_size + num_digits;
2339
+ CharPtr p = grow_buffer(size);
2340
+ std::uninitialized_copy(prefix, prefix + prefix_size, p);
2341
+ return p + size - 1;
2342
+ }
2343
+
2344
+ template <typename Spec>
2345
+ CharPtr prepare_int_buffer(unsigned num_digits,
2346
+ const Spec &spec, const char *prefix, unsigned prefix_size);
2347
+
2348
+ // Formats an integer.
2349
+ template <typename T, typename Spec>
2350
+ void write_int(T value, Spec spec);
2351
+
2352
+ // Formats a floating-point number (double or long double).
2353
+ template <typename T>
2354
+ void write_double(T value, const FormatSpec &spec);
2355
+
2356
+ // Writes a formatted string.
2357
+ template <typename StrChar>
2358
+ CharPtr write_str(const StrChar *s, std::size_t size, const AlignSpec &spec);
2359
+
2360
+ template <typename StrChar>
2361
+ void write_str(const internal::Arg::StringValue<StrChar> &str,
2362
+ const FormatSpec &spec);
2363
+
2364
+ // This following methods are private to disallow writing wide characters
2365
+ // and strings to a char stream. If you want to print a wide string as a
2366
+ // pointer as std::ostream does, cast it to const void*.
2367
+ // Do not implement!
2368
+ void operator<<(typename internal::WCharHelper<wchar_t, Char>::Unsupported);
2369
+ void operator<<(
2370
+ typename internal::WCharHelper<const wchar_t *, Char>::Unsupported);
2371
+
2372
+ // Appends floating-point length specifier to the format string.
2373
+ // The second argument is only used for overload resolution.
2374
+ void append_float_length(Char *&format_ptr, long double) {
2375
+ *format_ptr++ = 'L';
2376
+ }
2377
+
2378
+ template<typename T>
2379
+ void append_float_length(Char *&, T) {}
2380
+
2381
+ template <typename Impl, typename Char_>
2382
+ friend class internal::ArgFormatterBase;
2383
+
2384
+ friend class internal::PrintfArgFormatter<Char>;
2385
+
2386
+ protected:
2387
+ /**
2388
+ Constructs a ``BasicWriter`` object.
2389
+ */
2390
+ explicit BasicWriter(Buffer<Char> &b) : buffer_(b) {}
2391
+
2392
+ public:
2393
+ /**
2394
+ \rst
2395
+ Destroys a ``BasicWriter`` object.
2396
+ \endrst
2397
+ */
2398
+ virtual ~BasicWriter() {}
2399
+
2400
+ /**
2401
+ Returns the total number of characters written.
2402
+ */
2403
+ std::size_t size() const { return buffer_.size(); }
2404
+
2405
+ /**
2406
+ Returns a pointer to the output buffer content. No terminating null
2407
+ character is appended.
2408
+ */
2409
+ const Char *data() const FMT_NOEXCEPT { return &buffer_[0]; }
2410
+
2411
+ /**
2412
+ Returns a pointer to the output buffer content with terminating null
2413
+ character appended.
2414
+ */
2415
+ const Char *c_str() const {
2416
+ std::size_t size = buffer_.size();
2417
+ buffer_.reserve(size + 1);
2418
+ buffer_[size] = '\0';
2419
+ return &buffer_[0];
2420
+ }
2421
+
2422
+ /**
2423
+ \rst
2424
+ Returns the content of the output buffer as an `std::string`.
2425
+ \endrst
2426
+ */
2427
+ std::basic_string<Char> str() const {
2428
+ return std::basic_string<Char>(&buffer_[0], buffer_.size());
2429
+ }
2430
+
2431
+ /**
2432
+ \rst
2433
+ Writes formatted data.
2434
+
2435
+ *args* is an argument list representing arbitrary arguments.
2436
+
2437
+ **Example**::
2438
+
2439
+ MemoryWriter out;
2440
+ out.write("Current point:\n");
2441
+ out.write("({:+f}, {:+f})", -3.14, 3.14);
2442
+
2443
+ This will write the following output to the ``out`` object:
2444
+
2445
+ .. code-block:: none
2446
+
2447
+ Current point:
2448
+ (-3.140000, +3.140000)
2449
+
2450
+ The output can be accessed using :func:`data()`, :func:`c_str` or
2451
+ :func:`str` methods.
2452
+
2453
+ See also :ref:`syntax`.
2454
+ \endrst
2455
+ */
2456
+ void write(BasicCStringRef<Char> format, ArgList args) {
2457
+ BasicFormatter<Char>(args, *this).format(format);
2458
+ }
2459
+ FMT_VARIADIC_VOID(write, BasicCStringRef<Char>)
2460
+
2461
+ BasicWriter &operator<<(int value) {
2462
+ write_decimal(value);
2463
+ return *this;
2464
+ }
2465
+ BasicWriter &operator<<(unsigned value) {
2466
+ return *this << IntFormatSpec<unsigned>(value);
2467
+ }
2468
+ BasicWriter &operator<<(long value) {
2469
+ write_decimal(value);
2470
+ return *this;
2471
+ }
2472
+ BasicWriter &operator<<(unsigned long value) {
2473
+ return *this << IntFormatSpec<unsigned long>(value);
2474
+ }
2475
+ BasicWriter &operator<<(LongLong value) {
2476
+ write_decimal(value);
2477
+ return *this;
2478
+ }
2479
+
2480
+ /**
2481
+ \rst
2482
+ Formats *value* and writes it to the stream.
2483
+ \endrst
2484
+ */
2485
+ BasicWriter &operator<<(ULongLong value) {
2486
+ return *this << IntFormatSpec<ULongLong>(value);
2487
+ }
2488
+
2489
+ BasicWriter &operator<<(double value) {
2490
+ write_double(value, FormatSpec());
2491
+ return *this;
2492
+ }
2493
+
2494
+ /**
2495
+ \rst
2496
+ Formats *value* using the general format for floating-point numbers
2497
+ (``'g'``) and writes it to the stream.
2498
+ \endrst
2499
+ */
2500
+ BasicWriter &operator<<(long double value) {
2501
+ write_double(value, FormatSpec());
2502
+ return *this;
2503
+ }
2504
+
2505
+ /**
2506
+ Writes a character to the stream.
2507
+ */
2508
+ BasicWriter &operator<<(char value) {
2509
+ buffer_.push_back(value);
2510
+ return *this;
2511
+ }
2512
+
2513
+ BasicWriter &operator<<(
2514
+ typename internal::WCharHelper<wchar_t, Char>::Supported value) {
2515
+ buffer_.push_back(value);
2516
+ return *this;
2517
+ }
2518
+
2519
+ /**
2520
+ \rst
2521
+ Writes *value* to the stream.
2522
+ \endrst
2523
+ */
2524
+ BasicWriter &operator<<(fmt::BasicStringRef<Char> value) {
2525
+ const Char *str = value.data();
2526
+ buffer_.append(str, str + value.size());
2527
+ return *this;
2528
+ }
2529
+
2530
+ BasicWriter &operator<<(
2531
+ typename internal::WCharHelper<StringRef, Char>::Supported value) {
2532
+ const char *str = value.data();
2533
+ buffer_.append(str, str + value.size());
2534
+ return *this;
2535
+ }
2536
+
2537
+ template <typename T, typename Spec, typename FillChar>
2538
+ BasicWriter &operator<<(IntFormatSpec<T, Spec, FillChar> spec) {
2539
+ internal::CharTraits<Char>::convert(FillChar());
2540
+ write_int(spec.value(), spec);
2541
+ return *this;
2542
+ }
2543
+
2544
+ template <typename StrChar>
2545
+ BasicWriter &operator<<(const StrFormatSpec<StrChar> &spec) {
2546
+ const StrChar *s = spec.str();
2547
+ write_str(s, std::char_traits<Char>::length(s), spec);
2548
+ return *this;
2549
+ }
2550
+
2551
+ void clear() FMT_NOEXCEPT { buffer_.clear(); }
2552
+
2553
+ Buffer<Char> &buffer() FMT_NOEXCEPT { return buffer_; }
2554
+};
2555
+
2556
+template <typename Char>
2557
+template <typename StrChar>
2558
+typename BasicWriter<Char>::CharPtr BasicWriter<Char>::write_str(
2559
+ const StrChar *s, std::size_t size, const AlignSpec &spec) {
2560
+ CharPtr out = CharPtr();
2561
+ if (spec.width() > size) {
2562
+ out = grow_buffer(spec.width());
2563
+ Char fill = internal::CharTraits<Char>::cast(spec.fill());
2564
+ if (spec.align() == ALIGN_RIGHT) {
2565
+ std::uninitialized_fill_n(out, spec.width() - size, fill);
2566
+ out += spec.width() - size;
2567
+ } else if (spec.align() == ALIGN_CENTER) {
2568
+ out = fill_padding(out, spec.width(), size, fill);
2569
+ } else {
2570
+ std::uninitialized_fill_n(out + size, spec.width() - size, fill);
2571
+ }
2572
+ } else {
2573
+ out = grow_buffer(size);
2574
+ }
2575
+ std::uninitialized_copy(s, s + size, out);
2576
+ return out;
2577
+}
2578
+
2579
+template <typename Char>
2580
+template <typename StrChar>
2581
+void BasicWriter<Char>::write_str(
2582
+ const internal::Arg::StringValue<StrChar> &s, const FormatSpec &spec) {
2583
+ // Check if StrChar is convertible to Char.
2584
+ internal::CharTraits<Char>::convert(StrChar());
2585
+ if (spec.type_ && spec.type_ != 's')
2586
+ internal::report_unknown_type(spec.type_, "string");
2587
+ const StrChar *str_value = s.value;
2588
+ std::size_t str_size = s.size;
2589
+ if (str_size == 0) {
2590
+ if (!str_value) {
2591
+ FMT_THROW(FormatError("string pointer is null"));
2592
+ return;
2593
+ }
2594
+ }
2595
+ std::size_t precision = static_cast<std::size_t>(spec.precision_);
2596
+ if (spec.precision_ >= 0 && precision < str_size)
2597
+ str_size = precision;
2598
+ write_str(str_value, str_size, spec);
2599
+}
2600
+
2601
+template <typename Char>
2602
+typename BasicWriter<Char>::CharPtr
2603
+ BasicWriter<Char>::fill_padding(
2604
+ CharPtr buffer, unsigned total_size,
2605
+ std::size_t content_size, wchar_t fill) {
2606
+ std::size_t padding = total_size - content_size;
2607
+ std::size_t left_padding = padding / 2;
2608
+ Char fill_char = internal::CharTraits<Char>::cast(fill);
2609
+ std::uninitialized_fill_n(buffer, left_padding, fill_char);
2610
+ buffer += left_padding;
2611
+ CharPtr content = buffer;
2612
+ std::uninitialized_fill_n(buffer + content_size,
2613
+ padding - left_padding, fill_char);
2614
+ return content;
2615
+}
2616
+
2617
+template <typename Char>
2618
+template <typename Spec>
2619
+typename BasicWriter<Char>::CharPtr
2620
+ BasicWriter<Char>::prepare_int_buffer(
2621
+ unsigned num_digits, const Spec &spec,
2622
+ const char *prefix, unsigned prefix_size) {
2623
+ unsigned width = spec.width();
2624
+ Alignment align = spec.align();
2625
+ Char fill = internal::CharTraits<Char>::cast(spec.fill());
2626
+ if (spec.precision() > static_cast<int>(num_digits)) {
2627
+ // Octal prefix '0' is counted as a digit, so ignore it if precision
2628
+ // is specified.
2629
+ if (prefix_size > 0 && prefix[prefix_size - 1] == '0')
2630
+ --prefix_size;
2631
+ unsigned number_size =
2632
+ prefix_size + internal::to_unsigned(spec.precision());
2633
+ AlignSpec subspec(number_size, '0', ALIGN_NUMERIC);
2634
+ if (number_size >= width)
2635
+ return prepare_int_buffer(num_digits, subspec, prefix, prefix_size);
2636
+ buffer_.reserve(width);
2637
+ unsigned fill_size = width - number_size;
2638
+ if (align != ALIGN_LEFT) {
2639
+ CharPtr p = grow_buffer(fill_size);
2640
+ std::uninitialized_fill(p, p + fill_size, fill);
2641
+ }
2642
+ CharPtr result = prepare_int_buffer(
2643
+ num_digits, subspec, prefix, prefix_size);
2644
+ if (align == ALIGN_LEFT) {
2645
+ CharPtr p = grow_buffer(fill_size);
2646
+ std::uninitialized_fill(p, p + fill_size, fill);
2647
+ }
2648
+ return result;
2649
+ }
2650
+ unsigned size = prefix_size + num_digits;
2651
+ if (width <= size) {
2652
+ CharPtr p = grow_buffer(size);
2653
+ std::uninitialized_copy(prefix, prefix + prefix_size, p);
2654
+ return p + size - 1;
2655
+ }
2656
+ CharPtr p = grow_buffer(width);
2657
+ CharPtr end = p + width;
2658
+ if (align == ALIGN_LEFT) {
2659
+ std::uninitialized_copy(prefix, prefix + prefix_size, p);
2660
+ p += size;
2661
+ std::uninitialized_fill(p, end, fill);
2662
+ } else if (align == ALIGN_CENTER) {
2663
+ p = fill_padding(p, width, size, fill);
2664
+ std::uninitialized_copy(prefix, prefix + prefix_size, p);
2665
+ p += size;
2666
+ } else {
2667
+ if (align == ALIGN_NUMERIC) {
2668
+ if (prefix_size != 0) {
2669
+ p = std::uninitialized_copy(prefix, prefix + prefix_size, p);
2670
+ size -= prefix_size;
2671
+ }
2672
+ } else {
2673
+ std::uninitialized_copy(prefix, prefix + prefix_size, end - size);
2674
+ }
2675
+ std::uninitialized_fill(p, end - size, fill);
2676
+ p = end;
2677
+ }
2678
+ return p - 1;
2679
+}
2680
+
2681
+template <typename Char>
2682
+template <typename T, typename Spec>
2683
+void BasicWriter<Char>::write_int(T value, Spec spec) {
2684
+ unsigned prefix_size = 0;
2685
+ typedef typename internal::IntTraits<T>::MainType UnsignedType;
2686
+ UnsignedType abs_value = static_cast<UnsignedType>(value);
2687
+ char prefix[4] = "";
2688
+ if (internal::is_negative(value)) {
2689
+ prefix[0] = '-';
2690
+ ++prefix_size;
2691
+ abs_value = 0 - abs_value;
2692
+ } else if (spec.flag(SIGN_FLAG)) {
2693
+ prefix[0] = spec.flag(PLUS_FLAG) ? '+' : ' ';
2694
+ ++prefix_size;
2695
+ }
2696
+ switch (spec.type()) {
2697
+ case 0: case 'd': {
2698
+ unsigned num_digits = internal::count_digits(abs_value);
2699
+ CharPtr p = prepare_int_buffer(num_digits, spec, prefix, prefix_size) + 1;
2700
+ internal::format_decimal(get(p), abs_value, 0);
2701
+ break;
2702
+ }
2703
+ case 'x': case 'X': {
2704
+ UnsignedType n = abs_value;
2705
+ if (spec.flag(HASH_FLAG)) {
2706
+ prefix[prefix_size++] = '0';
2707
+ prefix[prefix_size++] = spec.type();
2708
+ }
2709
+ unsigned num_digits = 0;
2710
+ do {
2711
+ ++num_digits;
2712
+ } while ((n >>= 4) != 0);
2713
+ Char *p = get(prepare_int_buffer(
2714
+ num_digits, spec, prefix, prefix_size));
2715
+ n = abs_value;
2716
+ const char *digits = spec.type() == 'x' ?
2717
+ "0123456789abcdef" : "0123456789ABCDEF";
2718
+ do {
2719
+ *p-- = digits[n & 0xf];
2720
+ } while ((n >>= 4) != 0);
2721
+ break;
2722
+ }
2723
+ case 'b': case 'B': {
2724
+ UnsignedType n = abs_value;
2725
+ if (spec.flag(HASH_FLAG)) {
2726
+ prefix[prefix_size++] = '0';
2727
+ prefix[prefix_size++] = spec.type();
2728
+ }
2729
+ unsigned num_digits = 0;
2730
+ do {
2731
+ ++num_digits;
2732
+ } while ((n >>= 1) != 0);
2733
+ Char *p = get(prepare_int_buffer(num_digits, spec, prefix, prefix_size));
2734
+ n = abs_value;
2735
+ do {
2736
+ *p-- = static_cast<Char>('0' + (n & 1));
2737
+ } while ((n >>= 1) != 0);
2738
+ break;
2739
+ }
2740
+ case 'o': {
2741
+ UnsignedType n = abs_value;
2742
+ if (spec.flag(HASH_FLAG))
2743
+ prefix[prefix_size++] = '0';
2744
+ unsigned num_digits = 0;
2745
+ do {
2746
+ ++num_digits;
2747
+ } while ((n >>= 3) != 0);
2748
+ Char *p = get(prepare_int_buffer(num_digits, spec, prefix, prefix_size));
2749
+ n = abs_value;
2750
+ do {
2751
+ *p-- = static_cast<Char>('0' + (n & 7));
2752
+ } while ((n >>= 3) != 0);
2753
+ break;
2754
+ }
2755
+ case 'n': {
2756
+ unsigned num_digits = internal::count_digits(abs_value);
2757
+ fmt::StringRef sep = std::localeconv()->thousands_sep;
2758
+ unsigned size = static_cast<unsigned>(
2759
+ num_digits + sep.size() * (num_digits - 1) / 3);
2760
+ CharPtr p = prepare_int_buffer(size, spec, prefix, prefix_size) + 1;
2761
+ internal::format_decimal(get(p), abs_value, 0, internal::ThousandsSep(sep));
2762
+ break;
2763
+ }
2764
+ default:
2765
+ internal::report_unknown_type(
2766
+ spec.type(), spec.flag(CHAR_FLAG) ? "char" : "integer");
2767
+ break;
2768
+ }
2769
+}
2770
+
2771
+template <typename Char>
2772
+template <typename T>
2773
+void BasicWriter<Char>::write_double(T value, const FormatSpec &spec) {
2774
+ // Check type.
2775
+ char type = spec.type();
2776
+ bool upper = false;
2777
+ switch (type) {
2778
+ case 0:
2779
+ type = 'g';
2780
+ break;
2781
+ case 'e': case 'f': case 'g': case 'a':
2782
+ break;
2783
+ case 'F':
2784
+#ifdef _MSC_VER
2785
+ // MSVC's printf doesn't support 'F'.
2786
+ type = 'f';
2787
+#endif
2788
+ // Fall through.
2789
+ case 'E': case 'G': case 'A':
2790
+ upper = true;
2791
+ break;
2792
+ default:
2793
+ internal::report_unknown_type(type, "double");
2794
+ break;
2795
+ }
2796
+
2797
+ char sign = 0;
2798
+ // Use isnegative instead of value < 0 because the latter is always
2799
+ // false for NaN.
2800
+ if (internal::FPUtil::isnegative(static_cast<double>(value))) {
2801
+ sign = '-';
2802
+ value = -value;
2803
+ } else if (spec.flag(SIGN_FLAG)) {
2804
+ sign = spec.flag(PLUS_FLAG) ? '+' : ' ';
2805
+ }
2806
+
2807
+ if (internal::FPUtil::isnotanumber(value)) {
2808
+ // Format NaN ourselves because sprintf's output is not consistent
2809
+ // across platforms.
2810
+ std::size_t nan_size = 4;
2811
+ const char *nan = upper ? " NAN" : " nan";
2812
+ if (!sign) {
2813
+ --nan_size;
2814
+ ++nan;
2815
+ }
2816
+ CharPtr out = write_str(nan, nan_size, spec);
2817
+ if (sign)
2818
+ *out = sign;
2819
+ return;
2820
+ }
2821
+
2822
+ if (internal::FPUtil::isinfinity(value)) {
2823
+ // Format infinity ourselves because sprintf's output is not consistent
2824
+ // across platforms.
2825
+ std::size_t inf_size = 4;
2826
+ const char *inf = upper ? " INF" : " inf";
2827
+ if (!sign) {
2828
+ --inf_size;
2829
+ ++inf;
2830
+ }
2831
+ CharPtr out = write_str(inf, inf_size, spec);
2832
+ if (sign)
2833
+ *out = sign;
2834
+ return;
2835
+ }
2836
+
2837
+ std::size_t offset = buffer_.size();
2838
+ unsigned width = spec.width();
2839
+ if (sign) {
2840
+ buffer_.reserve(buffer_.size() + (width > 1u ? width : 1u));
2841
+ if (width > 0)
2842
+ --width;
2843
+ ++offset;
2844
+ }
2845
+
2846
+ // Build format string.
2847
+ enum { MAX_FORMAT_SIZE = 10}; // longest format: %#-*.*Lg
2848
+ Char format[MAX_FORMAT_SIZE];
2849
+ Char *format_ptr = format;
2850
+ *format_ptr++ = '%';
2851
+ unsigned width_for_sprintf = width;
2852
+ if (spec.flag(HASH_FLAG))
2853
+ *format_ptr++ = '#';
2854
+ if (spec.align() == ALIGN_CENTER) {
2855
+ width_for_sprintf = 0;
2856
+ } else {
2857
+ if (spec.align() == ALIGN_LEFT)
2858
+ *format_ptr++ = '-';
2859
+ if (width != 0)
2860
+ *format_ptr++ = '*';
2861
+ }
2862
+ if (spec.precision() >= 0) {
2863
+ *format_ptr++ = '.';
2864
+ *format_ptr++ = '*';
2865
+ }
2866
+
2867
+ append_float_length(format_ptr, value);
2868
+ *format_ptr++ = type;
2869
+ *format_ptr = '\0';
2870
+
2871
+ // Format using snprintf.
2872
+ Char fill = internal::CharTraits<Char>::cast(spec.fill());
2873
+ unsigned n = 0;
2874
+ Char *start = 0;
2875
+ for (;;) {
2876
+ std::size_t buffer_size = buffer_.capacity() - offset;
2877
+#ifdef _MSC_VER
2878
+ // MSVC's vsnprintf_s doesn't work with zero size, so reserve
2879
+ // space for at least one extra character to make the size non-zero.
2880
+ // Note that the buffer's capacity will increase by more than 1.
2881
+ if (buffer_size == 0) {
2882
+ buffer_.reserve(offset + 1);
2883
+ buffer_size = buffer_.capacity() - offset;
2884
+ }
2885
+#endif
2886
+ start = &buffer_[offset];
2887
+ int result = internal::CharTraits<Char>::format_float(
2888
+ start, buffer_size, format, width_for_sprintf, spec.precision(), value);
2889
+ if (result >= 0) {
2890
+ n = internal::to_unsigned(result);
2891
+ if (offset + n < buffer_.capacity())
2892
+ break; // The buffer is large enough - continue with formatting.
2893
+ buffer_.reserve(offset + n + 1);
2894
+ } else {
2895
+ // If result is negative we ask to increase the capacity by at least 1,
2896
+ // but as std::vector, the buffer grows exponentially.
2897
+ buffer_.reserve(buffer_.capacity() + 1);
2898
+ }
2899
+ }
2900
+ if (sign) {
2901
+ if ((spec.align() != ALIGN_RIGHT && spec.align() != ALIGN_DEFAULT) ||
2902
+ *start != ' ') {
2903
+ *(start - 1) = sign;
2904
+ sign = 0;
2905
+ } else {
2906
+ *(start - 1) = fill;
2907
+ }
2908
+ ++n;
2909
+ }
2910
+ if (spec.align() == ALIGN_CENTER && spec.width() > n) {
2911
+ width = spec.width();
2912
+ CharPtr p = grow_buffer(width);
2913
+ std::memmove(get(p) + (width - n) / 2, get(p), n * sizeof(Char));
2914
+ fill_padding(p, spec.width(), n, fill);
2915
+ return;
2916
+ }
2917
+ if (spec.fill() != ' ' || sign) {
2918
+ while (*start == ' ')
2919
+ *start++ = fill;
2920
+ if (sign)
2921
+ *(start - 1) = sign;
2922
+ }
2923
+ grow_buffer(n);
2924
+}
2925
+
2926
+/**
2927
+ \rst
2928
+ This class template provides operations for formatting and writing data
2929
+ into a character stream. The output is stored in a memory buffer that grows
2930
+ dynamically.
2931
+
2932
+ You can use one of the following typedefs for common character types
2933
+ and the standard allocator:
2934
+
2935
+ +---------------+-----------------------------------------------------+
2936
+ | Type | Definition |
2937
+ +===============+=====================================================+
2938
+ | MemoryWriter | BasicMemoryWriter<char, std::allocator<char>> |
2939
+ +---------------+-----------------------------------------------------+
2940
+ | WMemoryWriter | BasicMemoryWriter<wchar_t, std::allocator<wchar_t>> |
2941
+ +---------------+-----------------------------------------------------+
2942
+
2943
+ **Example**::
2944
+
2945
+ MemoryWriter out;
2946
+ out << "The answer is " << 42 << "\n";
2947
+ out.write("({:+f}, {:+f})", -3.14, 3.14);
2948
+
2949
+ This will write the following output to the ``out`` object:
2950
+
2951
+ .. code-block:: none
2952
+
2953
+ The answer is 42
2954
+ (-3.140000, +3.140000)
2955
+
2956
+ The output can be converted to an ``std::string`` with ``out.str()`` or
2957
+ accessed as a C string with ``out.c_str()``.
2958
+ \endrst
2959
+ */
2960
+template <typename Char, typename Allocator = std::allocator<Char> >
2961
+class BasicMemoryWriter : public BasicWriter<Char> {
2962
+ private:
2963
+ internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE, Allocator> buffer_;
2964
+
2965
+ public:
2966
+ explicit BasicMemoryWriter(const Allocator& alloc = Allocator())
2967
+ : BasicWriter<Char>(buffer_), buffer_(alloc) {}
2968
+
2969
+#if FMT_USE_RVALUE_REFERENCES
2970
+ /**
2971
+ \rst
2972
+ Constructs a :class:`fmt::BasicMemoryWriter` object moving the content
2973
+ of the other object to it.
2974
+ \endrst
2975
+ */
2976
+ BasicMemoryWriter(BasicMemoryWriter &&other)
2977
+ : BasicWriter<Char>(buffer_), buffer_(std::move(other.buffer_)) {
2978
+ }
2979
+
2980
+ /**
2981
+ \rst
2982
+ Moves the content of the other ``BasicMemoryWriter`` object to this one.
2983
+ \endrst
2984
+ */
2985
+ BasicMemoryWriter &operator=(BasicMemoryWriter &&other) {
2986
+ buffer_ = std::move(other.buffer_);
2987
+ return *this;
2988
+ }
2989
+#endif
2990
+};
2991
+
2992
+typedef BasicMemoryWriter<char> MemoryWriter;
2993
+typedef BasicMemoryWriter<wchar_t> WMemoryWriter;
2994
+
2995
+/**
2996
+ \rst
2997
+ This class template provides operations for formatting and writing data
2998
+ into a fixed-size array. For writing into a dynamically growing buffer
2999
+ use :class:`fmt::BasicMemoryWriter`.
3000
+
3001
+ Any write method will throw ``std::runtime_error`` if the output doesn't fit
3002
+ into the array.
3003
+
3004
+ You can use one of the following typedefs for common character types:
3005
+
3006
+ +--------------+---------------------------+
3007
+ | Type | Definition |
3008
+ +==============+===========================+
3009
+ | ArrayWriter | BasicArrayWriter<char> |
3010
+ +--------------+---------------------------+
3011
+ | WArrayWriter | BasicArrayWriter<wchar_t> |
3012
+ +--------------+---------------------------+
3013
+ \endrst
3014
+ */
3015
+template <typename Char>
3016
+class BasicArrayWriter : public BasicWriter<Char> {
3017
+ private:
3018
+ internal::FixedBuffer<Char> buffer_;
3019
+
3020
+ public:
3021
+ /**
3022
+ \rst
3023
+ Constructs a :class:`fmt::BasicArrayWriter` object for *array* of the
3024
+ given size.
3025
+ \endrst
3026
+ */
3027
+ BasicArrayWriter(Char *array, std::size_t size)
3028
+ : BasicWriter<Char>(buffer_), buffer_(array, size) {}
3029
+
3030
+ /**
3031
+ \rst
3032
+ Constructs a :class:`fmt::BasicArrayWriter` object for *array* of the
3033
+ size known at compile time.
3034
+ \endrst
3035
+ */
3036
+ template <std::size_t SIZE>
3037
+ explicit BasicArrayWriter(Char (&array)[SIZE])
3038
+ : BasicWriter<Char>(buffer_), buffer_(array, SIZE) {}
3039
+};
3040
+
3041
+typedef BasicArrayWriter<char> ArrayWriter;
3042
+typedef BasicArrayWriter<wchar_t> WArrayWriter;
3043
+
3044
+// Reports a system error without throwing an exception.
3045
+// Can be used to report errors from destructors.
3046
+FMT_API void report_system_error(int error_code,
3047
+ StringRef message) FMT_NOEXCEPT;
3048
+
3049
+#if FMT_USE_WINDOWS_H
3050
+
3051
+/** A Windows error. */
3052
+class WindowsError : public SystemError {
3053
+ private:
3054
+ FMT_API void init(int error_code, CStringRef format_str, ArgList args);
3055
+
3056
+ public:
3057
+ /**
3058
+ \rst
3059
+ Constructs a :class:`fmt::WindowsError` object with the description
3060
+ of the form
3061
+
3062
+ .. parsed-literal::
3063
+ *<message>*: *<system-message>*
3064
+
3065
+ where *<message>* is the formatted message and *<system-message>* is the
3066
+ system message corresponding to the error code.
3067
+ *error_code* is a Windows error code as given by ``GetLastError``.
3068
+ If *error_code* is not a valid error code such as -1, the system message
3069
+ will look like "error -1".
3070
+
3071
+ **Example**::
3072
+
3073
+ // This throws a WindowsError with the description
3074
+ // cannot open file 'madeup': The system cannot find the file specified.
3075
+ // or similar (system message may vary).
3076
+ const char *filename = "madeup";
3077
+ LPOFSTRUCT of = LPOFSTRUCT();
3078
+ HFILE file = OpenFile(filename, &of, OF_READ);
3079
+ if (file == HFILE_ERROR) {
3080
+ throw fmt::WindowsError(GetLastError(),
3081
+ "cannot open file '{}'", filename);
3082
+ }
3083
+ \endrst
3084
+ */
3085
+ WindowsError(int error_code, CStringRef message) {
3086
+ init(error_code, message, ArgList());
3087
+ }
3088
+ FMT_VARIADIC_CTOR(WindowsError, init, int, CStringRef)
3089
+};
3090
+
3091
+// Reports a Windows error without throwing an exception.
3092
+// Can be used to report errors from destructors.
3093
+FMT_API void report_windows_error(int error_code,
3094
+ StringRef message) FMT_NOEXCEPT;
3095
+
3096
+#endif
3097
+
3098
+enum Color { BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE };
3099
+
3100
+/**
3101
+ Formats a string and prints it to stdout using ANSI escape sequences
3102
+ to specify color (experimental).
3103
+ Example:
3104
+ print_colored(fmt::RED, "Elapsed time: {0:.2f} seconds", 1.23);
3105
+ */
3106
+FMT_API void print_colored(Color c, CStringRef format, ArgList args);
3107
+
3108
+/**
3109
+ \rst
3110
+ Formats arguments and returns the result as a string.
3111
+
3112
+ **Example**::
3113
+
3114
+ std::string message = format("The answer is {}", 42);
3115
+ \endrst
3116
+*/
3117
+inline std::string format(CStringRef format_str, ArgList args) {
3118
+ MemoryWriter w;
3119
+ w.write(format_str, args);
3120
+ return w.str();
3121
+}
3122
+
3123
+inline std::wstring format(WCStringRef format_str, ArgList args) {
3124
+ WMemoryWriter w;
3125
+ w.write(format_str, args);
3126
+ return w.str();
3127
+}
3128
+
3129
+/**
3130
+ \rst
3131
+ Prints formatted data to the file *f*.
3132
+
3133
+ **Example**::
3134
+
3135
+ print(stderr, "Don't {}!", "panic");
3136
+ \endrst
3137
+ */
3138
+FMT_API void print(std::FILE *f, CStringRef format_str, ArgList args);
3139
+
3140
+/**
3141
+ \rst
3142
+ Prints formatted data to ``stdout``.
3143
+
3144
+ **Example**::
3145
+
3146
+ print("Elapsed time: {0:.2f} seconds", 1.23);
3147
+ \endrst
3148
+ */
3149
+FMT_API void print(CStringRef format_str, ArgList args);
3150
+
3151
+template <typename Char>
3152
+void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args) {
3153
+ internal::PrintfFormatter<Char>(args).format(w, format);
3154
+}
3155
+
3156
+/**
3157
+ \rst
3158
+ Formats arguments and returns the result as a string.
3159
+
3160
+ **Example**::
3161
+
3162
+ std::string message = fmt::sprintf("The answer is %d", 42);
3163
+ \endrst
3164
+*/
3165
+inline std::string sprintf(CStringRef format, ArgList args) {
3166
+ MemoryWriter w;
3167
+ printf(w, format, args);
3168
+ return w.str();
3169
+}
3170
+
3171
+inline std::wstring sprintf(WCStringRef format, ArgList args) {
3172
+ WMemoryWriter w;
3173
+ printf(w, format, args);
3174
+ return w.str();
3175
+}
3176
+
3177
+/**
3178
+ \rst
3179
+ Prints formatted data to the file *f*.
3180
+
3181
+ **Example**::
3182
+
3183
+ fmt::fprintf(stderr, "Don't %s!", "panic");
3184
+ \endrst
3185
+ */
3186
+FMT_API int fprintf(std::FILE *f, CStringRef format, ArgList args);
3187
+
3188
+/**
3189
+ \rst
3190
+ Prints formatted data to ``stdout``.
3191
+
3192
+ **Example**::
3193
+
3194
+ fmt::printf("Elapsed time: %.2f seconds", 1.23);
3195
+ \endrst
3196
+ */
3197
+inline int printf(CStringRef format, ArgList args) {
3198
+ return fprintf(stdout, format, args);
3199
+}
3200
+
3201
+/**
3202
+ Fast integer formatter.
3203
+ */
3204
+class FormatInt {
3205
+ private:
3206
+ // Buffer should be large enough to hold all digits (digits10 + 1),
3207
+ // a sign and a null character.
3208
+ enum {BUFFER_SIZE = std::numeric_limits<ULongLong>::digits10 + 3};
3209
+ mutable char buffer_[BUFFER_SIZE];
3210
+ char *str_;
3211
+
3212
+ // Formats value in reverse and returns the number of digits.
3213
+ char *format_decimal(ULongLong value) {
3214
+ char *buffer_end = buffer_ + BUFFER_SIZE - 1;
3215
+ while (value >= 100) {
3216
+ // Integer division is slow so do it for a group of two digits instead
3217
+ // of for every digit. The idea comes from the talk by Alexandrescu
3218
+ // "Three Optimization Tips for C++". See speed-test for a comparison.
3219
+ unsigned index = static_cast<unsigned>((value % 100) * 2);
3220
+ value /= 100;
3221
+ *--buffer_end = internal::Data::DIGITS[index + 1];
3222
+ *--buffer_end = internal::Data::DIGITS[index];
3223
+ }
3224
+ if (value < 10) {
3225
+ *--buffer_end = static_cast<char>('0' + value);
3226
+ return buffer_end;
3227
+ }
3228
+ unsigned index = static_cast<unsigned>(value * 2);
3229
+ *--buffer_end = internal::Data::DIGITS[index + 1];
3230
+ *--buffer_end = internal::Data::DIGITS[index];
3231
+ return buffer_end;
3232
+ }
3233
+
3234
+ void FormatSigned(LongLong value) {
3235
+ ULongLong abs_value = static_cast<ULongLong>(value);
3236
+ bool negative = value < 0;
3237
+ if (negative)
3238
+ abs_value = 0 - abs_value;
3239
+ str_ = format_decimal(abs_value);
3240
+ if (negative)
3241
+ *--str_ = '-';
3242
+ }
3243
+
3244
+ public:
3245
+ explicit FormatInt(int value) { FormatSigned(value); }
3246
+ explicit FormatInt(long value) { FormatSigned(value); }
3247
+ explicit FormatInt(LongLong value) { FormatSigned(value); }
3248
+ explicit FormatInt(unsigned value) : str_(format_decimal(value)) {}
3249
+ explicit FormatInt(unsigned long value) : str_(format_decimal(value)) {}
3250
+ explicit FormatInt(ULongLong value) : str_(format_decimal(value)) {}
3251
+
3252
+ /** Returns the number of characters written to the output buffer. */
3253
+ std::size_t size() const {
3254
+ return internal::to_unsigned(buffer_ - str_ + BUFFER_SIZE - 1);
3255
+ }
3256
+
3257
+ /**
3258
+ Returns a pointer to the output buffer content. No terminating null
3259
+ character is appended.
3260
+ */
3261
+ const char *data() const { return str_; }
3262
+
3263
+ /**
3264
+ Returns a pointer to the output buffer content with terminating null
3265
+ character appended.
3266
+ */
3267
+ const char *c_str() const {
3268
+ buffer_[BUFFER_SIZE - 1] = '\0';
3269
+ return str_;
3270
+ }
3271
+
3272
+ /**
3273
+ \rst
3274
+ Returns the content of the output buffer as an ``std::string``.
3275
+ \endrst
3276
+ */
3277
+ std::string str() const { return std::string(str_, size()); }
3278
+};
3279
+
3280
+// Formats a decimal integer value writing into buffer and returns
3281
+// a pointer to the end of the formatted string. This function doesn't
3282
+// write a terminating null character.
3283
+template <typename T>
3284
+inline void format_decimal(char *&buffer, T value) {
3285
+ typedef typename internal::IntTraits<T>::MainType MainType;
3286
+ MainType abs_value = static_cast<MainType>(value);
3287
+ if (internal::is_negative(value)) {
3288
+ *buffer++ = '-';
3289
+ abs_value = 0 - abs_value;
3290
+ }
3291
+ if (abs_value < 100) {
3292
+ if (abs_value < 10) {
3293
+ *buffer++ = static_cast<char>('0' + abs_value);
3294
+ return;
3295
+ }
3296
+ unsigned index = static_cast<unsigned>(abs_value * 2);
3297
+ *buffer++ = internal::Data::DIGITS[index];
3298
+ *buffer++ = internal::Data::DIGITS[index + 1];
3299
+ return;
3300
+ }
3301
+ unsigned num_digits = internal::count_digits(abs_value);
3302
+ internal::format_decimal(buffer, abs_value, num_digits);
3303
+ buffer += num_digits;
3304
+}
3305
+
3306
+/**
3307
+ \rst
3308
+ Returns a named argument for formatting functions.
3309
+
3310
+ **Example**::
3311
+
3312
+ print("Elapsed time: {s:.2f} seconds", arg("s", 1.23));
3313
+
3314
+ \endrst
3315
+ */
3316
+template <typename T>
3317
+inline internal::NamedArg<char> arg(StringRef name, const T &arg) {
3318
+ return internal::NamedArg<char>(name, arg);
3319
+}
3320
+
3321
+template <typename T>
3322
+inline internal::NamedArg<wchar_t> arg(WStringRef name, const T &arg) {
3323
+ return internal::NamedArg<wchar_t>(name, arg);
3324
+}
3325
+
3326
+// The following two functions are deleted intentionally to disable
3327
+// nested named arguments as in ``format("{}", arg("a", arg("b", 42)))``.
3328
+template <typename Char>
3329
+void arg(StringRef, const internal::NamedArg<Char>&) FMT_DELETED_OR_UNDEFINED;
3330
+template <typename Char>
3331
+void arg(WStringRef, const internal::NamedArg<Char>&) FMT_DELETED_OR_UNDEFINED;
3332
+}
3333
+
3334
+#if FMT_GCC_VERSION
3335
+// Use the system_header pragma to suppress warnings about variadic macros
3336
+// because suppressing -Wvariadic-macros with the diagnostic pragma doesn't
3337
+// work. It is used at the end because we want to suppress as little warnings
3338
+// as possible.
3339
+# pragma GCC system_header
3340
+#endif
3341
+
3342
+// This is used to work around VC++ bugs in handling variadic macros.
3343
+#define FMT_EXPAND(args) args
3344
+
3345
+// Returns the number of arguments.
3346
+// Based on https://groups.google.com/forum/#!topic/comp.std.c/d-6Mj5Lko_s.
3347
+#define FMT_NARG(...) FMT_NARG_(__VA_ARGS__, FMT_RSEQ_N())
3348
+#define FMT_NARG_(...) FMT_EXPAND(FMT_ARG_N(__VA_ARGS__))
3349
+#define FMT_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
3350
+#define FMT_RSEQ_N() 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
3351
+
3352
+#define FMT_CONCAT(a, b) a##b
3353
+#define FMT_FOR_EACH_(N, f, ...) \
3354
+ FMT_EXPAND(FMT_CONCAT(FMT_FOR_EACH, N)(f, __VA_ARGS__))
3355
+#define FMT_FOR_EACH(f, ...) \
3356
+ FMT_EXPAND(FMT_FOR_EACH_(FMT_NARG(__VA_ARGS__), f, __VA_ARGS__))
3357
+
3358
+#define FMT_ADD_ARG_NAME(type, index) type arg##index
3359
+#define FMT_GET_ARG_NAME(type, index) arg##index
3360
+
3361
+#if FMT_USE_VARIADIC_TEMPLATES
3362
+# define FMT_VARIADIC_(Char, ReturnType, func, call, ...) \
3363
+ template <typename... Args> \
3364
+ ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
3365
+ const Args & ... args) { \
3366
+ typedef fmt::internal::ArgArray<sizeof...(Args)> ArgArray; \
3367
+ typename ArgArray::Type array{ \
3368
+ ArgArray::template make<fmt::BasicFormatter<Char> >(args)...}; \
3369
+ call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), \
3370
+ fmt::ArgList(fmt::internal::make_type(args...), array)); \
3371
+ }
3372
+#else
3373
+// Defines a wrapper for a function taking __VA_ARGS__ arguments
3374
+// and n additional arguments of arbitrary types.
3375
+# define FMT_WRAP(Char, ReturnType, func, call, n, ...) \
3376
+ template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
3377
+ inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
3378
+ FMT_GEN(n, FMT_MAKE_ARG)) { \
3379
+ fmt::internal::ArgArray<n>::Type arr; \
3380
+ FMT_GEN(n, FMT_ASSIGN_##Char); \
3381
+ call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList( \
3382
+ fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), arr)); \
3383
+ }
3384
+
3385
+# define FMT_VARIADIC_(Char, ReturnType, func, call, ...) \
3386
+ inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__)) { \
3387
+ call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList()); \
3388
+ } \
3389
+ FMT_WRAP(Char, ReturnType, func, call, 1, __VA_ARGS__) \
3390
+ FMT_WRAP(Char, ReturnType, func, call, 2, __VA_ARGS__) \
3391
+ FMT_WRAP(Char, ReturnType, func, call, 3, __VA_ARGS__) \
3392
+ FMT_WRAP(Char, ReturnType, func, call, 4, __VA_ARGS__) \
3393
+ FMT_WRAP(Char, ReturnType, func, call, 5, __VA_ARGS__) \
3394
+ FMT_WRAP(Char, ReturnType, func, call, 6, __VA_ARGS__) \
3395
+ FMT_WRAP(Char, ReturnType, func, call, 7, __VA_ARGS__) \
3396
+ FMT_WRAP(Char, ReturnType, func, call, 8, __VA_ARGS__) \
3397
+ FMT_WRAP(Char, ReturnType, func, call, 9, __VA_ARGS__) \
3398
+ FMT_WRAP(Char, ReturnType, func, call, 10, __VA_ARGS__) \
3399
+ FMT_WRAP(Char, ReturnType, func, call, 11, __VA_ARGS__) \
3400
+ FMT_WRAP(Char, ReturnType, func, call, 12, __VA_ARGS__) \
3401
+ FMT_WRAP(Char, ReturnType, func, call, 13, __VA_ARGS__) \
3402
+ FMT_WRAP(Char, ReturnType, func, call, 14, __VA_ARGS__) \
3403
+ FMT_WRAP(Char, ReturnType, func, call, 15, __VA_ARGS__)
3404
+#endif // FMT_USE_VARIADIC_TEMPLATES
3405
+
3406
+/**
3407
+ \rst
3408
+ Defines a variadic function with the specified return type, function name
3409
+ and argument types passed as variable arguments to this macro.
3410
+
3411
+ **Example**::
3412
+
3413
+ void print_error(const char *file, int line, const char *format,
3414
+ fmt::ArgList args) {
3415
+ fmt::print("{}: {}: ", file, line);
3416
+ fmt::print(format, args);
3417
+ }
3418
+ FMT_VARIADIC(void, print_error, const char *, int, const char *)
3419
+
3420
+ ``FMT_VARIADIC`` is used for compatibility with legacy C++ compilers that
3421
+ don't implement variadic templates. You don't have to use this macro if
3422
+ you don't need legacy compiler support and can use variadic templates
3423
+ directly::
3424
+
3425
+ template <typename... Args>
3426
+ void print_error(const char *file, int line, const char *format,
3427
+ const Args & ... args) {
3428
+ fmt::print("{}: {}: ", file, line);
3429
+ fmt::print(format, args...);
3430
+ }
3431
+ \endrst
3432
+ */
3433
+#define FMT_VARIADIC(ReturnType, func, ...) \
3434
+ FMT_VARIADIC_(char, ReturnType, func, return func, __VA_ARGS__)
3435
+
3436
+#define FMT_VARIADIC_W(ReturnType, func, ...) \
3437
+ FMT_VARIADIC_(wchar_t, ReturnType, func, return func, __VA_ARGS__)
3438
+
3439
+#define FMT_CAPTURE_ARG_(id, index) ::fmt::arg(#id, id)
3440
+
3441
+#define FMT_CAPTURE_ARG_W_(id, index) ::fmt::arg(L###id, id)
3442
+
3443
+/**
3444
+ \rst
3445
+ Convenient macro to capture the arguments' names and values into several
3446
+ ``fmt::arg(name, value)``.
3447
+
3448
+ **Example**::
3449
+
3450
+ int x = 1, y = 2;
3451
+ print("point: ({x}, {y})", FMT_CAPTURE(x, y));
3452
+ // same as:
3453
+ // print("point: ({x}, {y})", arg("x", x), arg("y", y));
3454
+
3455
+ \endrst
3456
+ */
3457
+#define FMT_CAPTURE(...) FMT_FOR_EACH(FMT_CAPTURE_ARG_, __VA_ARGS__)
3458
+
3459
+#define FMT_CAPTURE_W(...) FMT_FOR_EACH(FMT_CAPTURE_ARG_W_, __VA_ARGS__)
3460
+
3461
+namespace fmt {
3462
+FMT_VARIADIC(std::string, format, CStringRef)
3463
+FMT_VARIADIC_W(std::wstring, format, WCStringRef)
3464
+FMT_VARIADIC(void, print, CStringRef)
3465
+FMT_VARIADIC(void, print, std::FILE *, CStringRef)
3466
+
3467
+FMT_VARIADIC(void, print_colored, Color, CStringRef)
3468
+FMT_VARIADIC(std::string, sprintf, CStringRef)
3469
+FMT_VARIADIC_W(std::wstring, sprintf, WCStringRef)
3470
+FMT_VARIADIC(int, printf, CStringRef)
3471
+FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef)
3472
+
3473
+namespace internal {
3474
+template <typename Char>
3475
+inline bool is_name_start(Char c) {
3476
+ return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || '_' == c;
3477
+}
3478
+
3479
+// Parses an unsigned integer advancing s to the end of the parsed input.
3480
+// This function assumes that the first character of s is a digit.
3481
+template <typename Char>
3482
+unsigned parse_nonnegative_int(const Char *&s) {
3483
+ assert('0' <= *s && *s <= '9');
3484
+ unsigned value = 0;
3485
+ do {
3486
+ unsigned new_value = value * 10 + (*s++ - '0');
3487
+ // Check if value wrapped around.
3488
+ if (new_value < value) {
3489
+ value = (std::numeric_limits<unsigned>::max)();
3490
+ break;
3491
+ }
3492
+ value = new_value;
3493
+ } while ('0' <= *s && *s <= '9');
3494
+ // Convert to unsigned to prevent a warning.
3495
+ unsigned max_int = (std::numeric_limits<int>::max)();
3496
+ if (value > max_int)
3497
+ FMT_THROW(FormatError("number is too big"));
3498
+ return value;
3499
+}
3500
+
3501
+inline void require_numeric_argument(const Arg &arg, char spec) {
3502
+ if (arg.type > Arg::LAST_NUMERIC_TYPE) {
3503
+ std::string message =
3504
+ fmt::format("format specifier '{}' requires numeric argument", spec);
3505
+ FMT_THROW(fmt::FormatError(message));
3506
+ }
3507
+}
3508
+
3509
+template <typename Char>
3510
+void check_sign(const Char *&s, const Arg &arg) {
3511
+ char sign = static_cast<char>(*s);
3512
+ require_numeric_argument(arg, sign);
3513
+ if (arg.type == Arg::UINT || arg.type == Arg::ULONG_LONG) {
3514
+ FMT_THROW(FormatError(fmt::format(
3515
+ "format specifier '{}' requires signed argument", sign)));
3516
+ }
3517
+ ++s;
3518
+}
3519
+} // namespace internal
3520
+
3521
+template <typename Char, typename AF>
3522
+inline internal::Arg BasicFormatter<Char, AF>::get_arg(
3523
+ BasicStringRef<Char> arg_name, const char *&error) {
3524
+ if (check_no_auto_index(error)) {
3525
+ map_.init(args());
3526
+ const internal::Arg *arg = map_.find(arg_name);
3527
+ if (arg)
3528
+ return *arg;
3529
+ error = "argument not found";
3530
+ }
3531
+ return internal::Arg();
3532
+}
3533
+
3534
+template <typename Char, typename AF>
3535
+inline internal::Arg BasicFormatter<Char, AF>::parse_arg_index(const Char *&s) {
3536
+ const char *error = 0;
3537
+ internal::Arg arg = *s < '0' || *s > '9' ?
3538
+ next_arg(error) : get_arg(internal::parse_nonnegative_int(s), error);
3539
+ if (error) {
3540
+ FMT_THROW(FormatError(
3541
+ *s != '}' && *s != ':' ? "invalid format string" : error));
3542
+ }
3543
+ return arg;
3544
+}
3545
+
3546
+template <typename Char, typename AF>
3547
+inline internal::Arg BasicFormatter<Char, AF>::parse_arg_name(const Char *&s) {
3548
+ assert(internal::is_name_start(*s));
3549
+ const Char *start = s;
3550
+ Char c;
3551
+ do {
3552
+ c = *++s;
3553
+ } while (internal::is_name_start(c) || ('0' <= c && c <= '9'));
3554
+ const char *error = 0;
3555
+ internal::Arg arg = get_arg(BasicStringRef<Char>(start, s - start), error);
3556
+ if (error)
3557
+ FMT_THROW(FormatError(error));
3558
+ return arg;
3559
+}
3560
+
3561
+template <typename Char, typename ArgFormatter>
3562
+const Char *BasicFormatter<Char, ArgFormatter>::format(
3563
+ const Char *&format_str, const internal::Arg &arg) {
3564
+ using internal::Arg;
3565
+ const Char *s = format_str;
3566
+ FormatSpec spec;
3567
+ if (*s == ':') {
3568
+ if (arg.type == Arg::CUSTOM) {
3569
+ arg.custom.format(this, arg.custom.value, &s);
3570
+ return s;
3571
+ }
3572
+ ++s;
3573
+ // Parse fill and alignment.
3574
+ if (Char c = *s) {
3575
+ const Char *p = s + 1;
3576
+ spec.align_ = ALIGN_DEFAULT;
3577
+ do {
3578
+ switch (*p) {
3579
+ case '<':
3580
+ spec.align_ = ALIGN_LEFT;
3581
+ break;
3582
+ case '>':
3583
+ spec.align_ = ALIGN_RIGHT;
3584
+ break;
3585
+ case '=':
3586
+ spec.align_ = ALIGN_NUMERIC;
3587
+ break;
3588
+ case '^':
3589
+ spec.align_ = ALIGN_CENTER;
3590
+ break;
3591
+ }
3592
+ if (spec.align_ != ALIGN_DEFAULT) {
3593
+ if (p != s) {
3594
+ if (c == '}') break;
3595
+ if (c == '{')
3596
+ FMT_THROW(FormatError("invalid fill character '{'"));
3597
+ s += 2;
3598
+ spec.fill_ = c;
3599
+ } else ++s;
3600
+ if (spec.align_ == ALIGN_NUMERIC)
3601
+ require_numeric_argument(arg, '=');
3602
+ break;
3603
+ }
3604
+ } while (--p >= s);
3605
+ }
3606
+
3607
+ // Parse sign.
3608
+ switch (*s) {
3609
+ case '+':
3610
+ check_sign(s, arg);
3611
+ spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
3612
+ break;
3613
+ case '-':
3614
+ check_sign(s, arg);
3615
+ spec.flags_ |= MINUS_FLAG;
3616
+ break;
3617
+ case ' ':
3618
+ check_sign(s, arg);
3619
+ spec.flags_ |= SIGN_FLAG;
3620
+ break;
3621
+ }
3622
+
3623
+ if (*s == '#') {
3624
+ require_numeric_argument(arg, '#');
3625
+ spec.flags_ |= HASH_FLAG;
3626
+ ++s;
3627
+ }
3628
+
3629
+ // Parse zero flag.
3630
+ if (*s == '0') {
3631
+ require_numeric_argument(arg, '0');
3632
+ spec.align_ = ALIGN_NUMERIC;
3633
+ spec.fill_ = '0';
3634
+ ++s;
3635
+ }
3636
+
3637
+ // Parse width.
3638
+ if ('0' <= *s && *s <= '9') {
3639
+ spec.width_ = internal::parse_nonnegative_int(s);
3640
+ } else if (*s == '{') {
3641
+ ++s;
3642
+ Arg width_arg = internal::is_name_start(*s) ?
3643
+ parse_arg_name(s) : parse_arg_index(s);
3644
+ if (*s++ != '}')
3645
+ FMT_THROW(FormatError("invalid format string"));
3646
+ ULongLong value = 0;
3647
+ switch (width_arg.type) {
3648
+ case Arg::INT:
3649
+ if (width_arg.int_value < 0)
3650
+ FMT_THROW(FormatError("negative width"));
3651
+ value = width_arg.int_value;
3652
+ break;
3653
+ case Arg::UINT:
3654
+ value = width_arg.uint_value;
3655
+ break;
3656
+ case Arg::LONG_LONG:
3657
+ if (width_arg.long_long_value < 0)
3658
+ FMT_THROW(FormatError("negative width"));
3659
+ value = width_arg.long_long_value;
3660
+ break;
3661
+ case Arg::ULONG_LONG:
3662
+ value = width_arg.ulong_long_value;
3663
+ break;
3664
+ default:
3665
+ FMT_THROW(FormatError("width is not integer"));
3666
+ }
3667
+ if (value > (std::numeric_limits<int>::max)())
3668
+ FMT_THROW(FormatError("number is too big"));
3669
+ spec.width_ = static_cast<int>(value);
3670
+ }
3671
+
3672
+ // Parse precision.
3673
+ if (*s == '.') {
3674
+ ++s;
3675
+ spec.precision_ = 0;
3676
+ if ('0' <= *s && *s <= '9') {
3677
+ spec.precision_ = internal::parse_nonnegative_int(s);
3678
+ } else if (*s == '{') {
3679
+ ++s;
3680
+ Arg precision_arg = internal::is_name_start(*s) ?
3681
+ parse_arg_name(s) : parse_arg_index(s);
3682
+ if (*s++ != '}')
3683
+ FMT_THROW(FormatError("invalid format string"));
3684
+ ULongLong value = 0;
3685
+ switch (precision_arg.type) {
3686
+ case Arg::INT:
3687
+ if (precision_arg.int_value < 0)
3688
+ FMT_THROW(FormatError("negative precision"));
3689
+ value = precision_arg.int_value;
3690
+ break;
3691
+ case Arg::UINT:
3692
+ value = precision_arg.uint_value;
3693
+ break;
3694
+ case Arg::LONG_LONG:
3695
+ if (precision_arg.long_long_value < 0)
3696
+ FMT_THROW(FormatError("negative precision"));
3697
+ value = precision_arg.long_long_value;
3698
+ break;
3699
+ case Arg::ULONG_LONG:
3700
+ value = precision_arg.ulong_long_value;
3701
+ break;
3702
+ default:
3703
+ FMT_THROW(FormatError("precision is not integer"));
3704
+ }
3705
+ if (value > (std::numeric_limits<int>::max)())
3706
+ FMT_THROW(FormatError("number is too big"));
3707
+ spec.precision_ = static_cast<int>(value);
3708
+ } else {
3709
+ FMT_THROW(FormatError("missing precision specifier"));
3710
+ }
3711
+ if (arg.type <= Arg::LAST_INTEGER_TYPE || arg.type == Arg::POINTER) {
3712
+ FMT_THROW(FormatError(
3713
+ fmt::format("precision not allowed in {} format specifier",
3714
+ arg.type == Arg::POINTER ? "pointer" : "integer")));
3715
+ }
3716
+ }
3717
+
3718
+ // Parse type.
3719
+ if (*s != '}' && *s)
3720
+ spec.type_ = static_cast<char>(*s++);
3721
+ }
3722
+
3723
+ if (*s++ != '}')
3724
+ FMT_THROW(FormatError("missing '}' in format string"));
3725
+
3726
+ // Format argument.
3727
+ ArgFormatter(*this, spec, s - 1).visit(arg);
3728
+ return s;
3729
+}
3730
+
3731
+template <typename Char, typename AF>
3732
+void BasicFormatter<Char, AF>::format(BasicCStringRef<Char> format_str) {
3733
+ const Char *s = format_str.c_str();
3734
+ const Char *start = s;
3735
+ while (*s) {
3736
+ Char c = *s++;
3737
+ if (c != '{' && c != '}') continue;
3738
+ if (*s == c) {
3739
+ write(writer_, start, s);
3740
+ start = ++s;
3741
+ continue;
3742
+ }
3743
+ if (c == '}')
3744
+ FMT_THROW(FormatError("unmatched '}' in format string"));
3745
+ write(writer_, start, s - 1);
3746
+ internal::Arg arg = internal::is_name_start(*s) ?
3747
+ parse_arg_name(s) : parse_arg_index(s);
3748
+ start = s = format(s, arg);
3749
+ }
3750
+ write(writer_, start, s);
3751
+}
3752
+} // namespace fmt
3753
+
3754
+#if FMT_USE_USER_DEFINED_LITERALS
3755
+namespace fmt {
3756
+namespace internal {
3757
+
3758
+template <typename Char>
3759
+struct UdlFormat {
3760
+ const Char *str;
3761
+
3762
+ template <typename... Args>
3763
+ auto operator()(Args && ... args) const
3764
+ -> decltype(format(str, std::forward<Args>(args)...)) {
3765
+ return format(str, std::forward<Args>(args)...);
3766
+ }
3767
+};
3768
+
3769
+template <typename Char>
3770
+struct UdlArg {
3771
+ const Char *str;
3772
+
3773
+ template <typename T>
3774
+ NamedArg<Char> operator=(T &&value) const {
3775
+ return {str, std::forward<T>(value)};
3776
+ }
3777
+};
3778
+
3779
+} // namespace internal
3780
+
3781
+inline namespace literals {
3782
+
3783
+/**
3784
+ \rst
3785
+ C++11 literal equivalent of :func:`fmt::format`.
3786
+
3787
+ **Example**::
3788
+
3789
+ using namespace fmt::literals;
3790
+ std::string message = "The answer is {}"_format(42);
3791
+ \endrst
3792
+ */
3793
+inline internal::UdlFormat<char>
3794
+operator"" _format(const char *s, std::size_t) { return {s}; }
3795
+inline internal::UdlFormat<wchar_t>
3796
+operator"" _format(const wchar_t *s, std::size_t) { return {s}; }
3797
+
3798
+/**
3799
+ \rst
3800
+ C++11 literal equivalent of :func:`fmt::arg`.
3801
+
3802
+ **Example**::
3803
+
3804
+ using namespace fmt::literals;
3805
+ print("Elapsed time: {s:.2f} seconds", "s"_a=1.23);
3806
+ \endrst
3807
+ */
3808
+inline internal::UdlArg<char>
3809
+operator"" _a(const char *s, std::size_t) { return {s}; }
3810
+inline internal::UdlArg<wchar_t>
3811
+operator"" _a(const wchar_t *s, std::size_t) { return {s}; }
3812
+
3813
+} // inline namespace literals
3814
+} // namespace fmt
3815
+#endif // FMT_USE_USER_DEFINED_LITERALS
3816
+
3817
+// Restore warnings.
3818
+#if FMT_GCC_VERSION >= 406
3819
+# pragma GCC diagnostic pop
3820
+#endif
3821
+
3822
+#if defined(__clang__) && !defined(FMT_ICC_VERSION)
3823
+# pragma clang diagnostic pop
3824
+#endif
3825
+
3826
+#ifdef FMT_HEADER_ONLY
3827
+# define FMT_FUNC inline
3828
+# include "format.cc"
3829
+#else
3830
+# define FMT_FUNC
3831
+#endif
3832
+
3833
+#endif // FMT_FORMAT_H_
3834
obs-studio-0.17.0.tar.xz/plugins/obs-browser/obs-browser/apple/browser-manager-mac.h -> obs-studio-17.0.1.tar.xz/plugins/obs-browser/obs-browser/apple/browser-manager-mac.h
Changed
10
1
2
3
void RefreshPageNoCache(int browserIdentifier);
4
5
+ void DispatchJSEvent(const char *eventName, const char *jsonData);
6
+
7
private:
8
std::unique_ptr<CEFIsolationServiceManager> cefIsolationServiceManager;
9
};
10
obs-studio-0.17.0.tar.xz/plugins/obs-browser/obs-browser/apple/browser-manager-mac.mm -> obs-studio-17.0.1.tar.xz/plugins/obs-browser/obs-browser/apple/browser-manager-mac.mm
Changed
25
1
2
pimpl->RefreshPageNoCache(browserIdentifier);
3
}
4
5
+void BrowserManager::DispatchJSEvent(const char *name, const char *jsonData)
6
+{
7
+ pimpl->DispatchJSEvent(name, jsonData);
8
+}
9
+
10
int BrowserManager::CreateBrowser(const BrowserSettings &browserSettings,
11
const std::shared_ptr<BrowserListener> &browserListener)
12
{
13
14
cefIsolationServiceManager->RefreshPageNoCache(browserIdentifier);
15
}
16
17
+void BrowserManager::Impl::DispatchJSEvent(const char *eventName, const char *jsonData)
18
+{
19
+ cefIsolationServiceManager->DispatchJSEvent(eventName, jsonData);
20
+}
21
+
22
static BrowserManager *instance;
23
24
BrowserManager *BrowserManager::Instance()
25
obs-studio-0.17.0.tar.xz/plugins/obs-browser/obs-browser/apple/cef-isolation-service-manager.h -> obs-studio-17.0.1.tar.xz/plugins/obs-browser/obs-browser/apple/cef-isolation-service-manager.h
Changed
25
1
2
3
#include <Foundation/Foundation.h>
4
#include <string>
5
+#include <jansson.h>
6
7
@class CEFIsolationService;
8
@class ClientConnectionDelegate;
9
10
11
void RefreshPageNoCache(int browserIdentifier);
12
13
+ void DispatchJSEvent(const char *eventName, const char *jsonData);
14
+
15
public:
16
NSString *GetUniqueClientName() { return _uniqueClientName; }
17
18
19
CEFIsolationService *_cefIsolationService;
20
NSObject *cefIsolationServiceLock;
21
22
-};
23
\ No newline at end of file
24
+};
25
obs-studio-0.17.0.tar.xz/plugins/obs-browser/obs-browser/apple/cef-isolation-service-manager.mm -> obs-studio-17.0.1.tar.xz/plugins/obs-browser/obs-browser/apple/cef-isolation-service-manager.mm
Changed
25
1
2
******************************************************************************/
3
4
#include <string>
5
+#import <Foundation/Foundation.h>
6
7
// shared
8
#include "browser-listener.hpp"
9
10
@catch (NSException *exception) {}
11
}
12
13
-
14
-
15
-
16
+void CEFIsolationServiceManager::DispatchJSEvent(const char *eventName, const char *jsonData)
17
+{
18
+ id<CEFIsolatedClient> cefIsolatedClient =
19
+ [_cefIsolationService client];
20
+ @try {
21
+ [cefIsolatedClient dispatchJSEvent:eventName data:jsonData];
22
+ }
23
+ @catch (NSException *exception) {}
24
+}
25
obs-studio-0.17.0.tar.xz/plugins/obs-browser/obs-browser/apple/cef-isolation-service.mm -> obs-studio-17.0.1.tar.xz/plugins/obs-browser/obs-browser/apple/cef-isolation-service.mm
Changed
36
1
2
3
#include "browser-listener.hpp"
4
5
+#include <obs-frontend-api.h>
6
+#include "util.hpp"
7
+
8
@implementation CEFIsolationService
9
{
10
std::map<int, std::shared_ptr<BrowserListener> > listenerMap;
11
12
}
13
}
14
15
+- (const char*)getCurrentSceneJSONData
16
+{
17
+ obs_source_t *source = obs_frontend_get_current_scene();
18
+
19
+ const char* jsonString = obsSourceToJSON(source);
20
+
21
+ obs_source_release(source);
22
+
23
+ return jsonString;
24
+}
25
+
26
- (void)invalidateClient:(id)client withException:(NSException *)exception
27
{
28
UNUSED_PARAMETER(client);
29
30
}
31
}
32
33
-@end
34
\ No newline at end of file
35
+@end
36
obs-studio-0.17.0.tar.xz/plugins/obs-browser/obs-browser/browser-manager-base.cpp -> obs-studio-17.0.1.tar.xz/plugins/obs-browser/obs-browser/browser-manager-base.cpp
Changed
66
1
2
#include "browser-client.hpp"
3
#include "browser-render-handler.hpp"
4
#include "browser-load-handler.hpp"
5
+#include "browser-obs-bridge-base.hpp"
6
7
BrowserManager::BrowserManager()
8
: pimpl(new BrowserManager::Impl())
9
10
pimpl->RefreshPageNoCache(browserIdentifier);
11
}
12
13
+/**
14
+ Sends JSON Data about an OBS event to be executed as a DOM event.
15
+ The jsonString is already encoded so that we can pass it across the process boundary that cef-isolation creates.
16
+
17
+ @param eventName the name of the DOM event that we will fire
18
+ @param jsonString A json encoded string that will be accessable from the detail field of the event object
19
+ @return
20
+*/
21
+void BrowserManager::DispatchJSEvent(const char *eventName, const char *jsonString)
22
+{
23
+ pimpl->DispatchJSEvent(eventName, jsonString);
24
+}
25
+
26
BrowserManager::Impl::Impl()
27
{
28
os_event_init(&dispatchEvent, OS_EVENT_TYPE_AUTO);
29
30
os_event_t *createdEvent;
31
os_event_init(&createdEvent, OS_EVENT_TYPE_AUTO);
32
33
+ BrowserOBSBridge *browserOBSBridge = new BrowserOBSBridgeBase();
34
+
35
CefPostTask(TID_UI, BrowserTask::newTask(
36
[&]
37
{
38
39
new BrowserLoadHandler(browserSettings.css));
40
41
CefRefPtr<BrowserClient> browserClient(
42
- new BrowserClient(renderHandler,loadHandler));
43
+ new BrowserClient(renderHandler, loadHandler, browserOBSBridge));
44
45
CefWindowInfo windowInfo;
46
windowInfo.transparent_painting_enabled = true;
47
48
});
49
}
50
51
+void BrowserManager::Impl::DispatchJSEvent(const char *eventName, const char *jsonString)
52
+{
53
+ ExecuteOnAllBrowsers([&](CefRefPtr<CefBrowser> b)
54
+ {
55
+ CefRefPtr<CefProcessMessage> msg = CefProcessMessage::Create("DispatchJSEvent");
56
+ CefRefPtr<CefListValue> args = msg->GetArgumentList();
57
+ args->SetString(0, eventName);
58
+ args->SetString(1, jsonString);
59
+ b->SendProcessMessage(PID_RENDERER, msg);
60
+ });
61
+}
62
+
63
void
64
BrowserManager::Impl::Startup()
65
{
66
obs-studio-0.17.0.tar.xz/plugins/obs-browser/obs-browser/browser-manager-base.hpp -> obs-studio-17.0.1.tar.xz/plugins/obs-browser/obs-browser/browser-manager-base.hpp
Changed
10
1
2
void ExecuteSceneChangeJSCallback(const char *name);
3
4
void RefreshPageNoCache(int browserIdentifier);
5
+
6
+ void DispatchJSEvent(const char *eventName, const char *jsonString);
7
8
private:
9
void ExecuteOnBrowser(int browserIdentifier,
10
obs-studio-17.0.1.tar.xz/plugins/obs-browser/obs-browser/browser-obs-bridge-base.cpp
Added
19
1
2
+#include "browser-obs-bridge-base.hpp"
3
+
4
+#include "util.hpp"
5
+
6
+BrowserOBSBridgeBase::BrowserOBSBridgeBase()
7
+{}
8
+
9
+const char* BrowserOBSBridgeBase::GetCurrentSceneJSONData()
10
+{
11
+ obs_source_t *source = obs_frontend_get_current_scene();
12
+
13
+ const char* jsonString = obsSourceToJSON(source);
14
+
15
+ obs_source_release(source);
16
+
17
+ return jsonString;
18
+}
19
obs-studio-17.0.1.tar.xz/plugins/obs-browser/obs-browser/browser-obs-bridge-base.hpp
Added
13
1
2
+#pragma once
3
+
4
+#include "browser-obs-bridge.hpp"
5
+
6
+class BrowserOBSBridgeBase : public BrowserOBSBridge
7
+{
8
+public:
9
+ BrowserOBSBridgeBase();
10
+
11
+ const char* GetCurrentSceneJSONData() override;
12
+};
13
obs-studio-0.17.0.tar.xz/plugins/obs-browser/obs-browser/main-source.cpp -> obs-studio-17.0.1.tar.xz/plugins/obs-browser/obs-browser/main-source.cpp
Changed
53
1
2
obs_data_set_default_int(settings, "height", 600);
3
obs_data_set_default_int(settings, "fps", 30);
4
obs_data_set_default_bool(settings, "shutdown", false);
5
+ obs_data_set_default_bool(settings, "restart_when_active", false);
6
obs_data_set_default_string(settings, "css", "body { background-color: rgba(0, 0, 0, 0); margin: 0px auto; overflow: hidden; }");
7
}
8
9
10
obs_properties_add_text(props, "css",
11
obs_module_text("CSS"), OBS_TEXT_MULTILINE);
12
obs_properties_add_bool(props, "shutdown",
13
- obs_module_text("Shutdown when not active"));
14
+ obs_module_text("Shutdown source when not visible"));
15
+ obs_properties_add_bool(props, "restart_when_active",
16
+ obs_module_text("Refresh browser when scene becomes active"));
17
18
obs_properties_add_button(props, "refreshnocache",
19
obs_module_text("Refresh cache of current page"), refreshnocache_button_clicked);
20
21
return obs_module_text("BrowserSource");
22
}
23
24
+static void browser_source_activate(void *data)
25
+{
26
+ BrowserSource *bs = static_cast<BrowserSource *>(data);
27
+ obs_data_t *settings = obs_source_get_settings(bs->GetSource());
28
+ bool restart = obs_data_get_bool(settings, "restart_when_active");
29
+
30
+ if (restart)
31
+ BrowserManager::Instance()->RefreshPageNoCache(bs->GetBrowserIdentifier());
32
+}
33
+
34
+static void browser_source_deactivate(void *data)
35
+{
36
+
37
+}
38
+
39
// Called when the source is visible
40
static void browser_source_show(void *data)
41
{
42
43
browser_source_info.video_render = browser_source_render;
44
browser_source_info.show = browser_source_show;
45
browser_source_info.hide = browser_source_hide;
46
+ browser_source_info.activate = browser_source_activate;
47
+ browser_source_info.deactivate = browser_source_deactivate;
48
+
49
50
return browser_source_info;
51
}
52
\ No newline at end of file
53
obs-studio-0.17.0.tar.xz/plugins/obs-browser/obs-browser/main.cpp -> obs-studio-17.0.1.tar.xz/plugins/obs-browser/obs-browser/main.cpp
Changed
80
1
2
3
#include "browser-version.h"
4
#include "browser-manager.hpp"
5
+#include "util.hpp"
6
7
OBS_DECLARE_MODULE()
8
OBS_MODULE_USE_DEFAULT_LOCALE("obs-browser", "en-US")
9
10
// Handle events from the frontend
11
static void handle_obs_frontend_event(enum obs_frontend_event event, void *)
12
{
13
- if (event == OBS_FRONTEND_EVENT_SCENE_CHANGED) {
14
-
15
- obs_source_t *source = obs_frontend_get_current_scene();
16
-
17
- const char *name = obs_source_get_name(source);
18
-
19
- BrowserManager::Instance()->ExecuteSceneChangeJSCallback(name);
20
- obs_source_release(source);
21
+ switch(event)
22
+ {
23
+ case OBS_FRONTEND_EVENT_STREAMING_STARTING:
24
+ BrowserManager::Instance()->DispatchJSEvent("obsStreamingStarting", nullptr);
25
+ break;
26
+ case OBS_FRONTEND_EVENT_STREAMING_STARTED:
27
+ BrowserManager::Instance()->DispatchJSEvent("obsStreamingStarted", nullptr);
28
+ break;
29
+ case OBS_FRONTEND_EVENT_STREAMING_STOPPING:
30
+ BrowserManager::Instance()->DispatchJSEvent("obsStreamingStopping", nullptr);
31
+ break;
32
+ case OBS_FRONTEND_EVENT_STREAMING_STOPPED:
33
+ BrowserManager::Instance()->DispatchJSEvent("obsStreamingStopped", nullptr);
34
+ break;
35
+ case OBS_FRONTEND_EVENT_RECORDING_STARTING:
36
+ BrowserManager::Instance()->DispatchJSEvent("obsRecordingStarting", nullptr);
37
+ break;
38
+ case OBS_FRONTEND_EVENT_RECORDING_STARTED:
39
+ BrowserManager::Instance()->DispatchJSEvent("obsRecordingStarted", nullptr);
40
+ break;
41
+ case OBS_FRONTEND_EVENT_RECORDING_STOPPING:
42
+ BrowserManager::Instance()->DispatchJSEvent("obsRecordingStopping", nullptr);
43
+ break;
44
+ case OBS_FRONTEND_EVENT_RECORDING_STOPPED:
45
+ BrowserManager::Instance()->DispatchJSEvent("obsRecordingStopped", nullptr);
46
+ break;
47
+ case OBS_FRONTEND_EVENT_SCENE_CHANGED:
48
+ {
49
+ obs_source_t *source = obs_frontend_get_current_scene();
50
+
51
+ const char* jsonString = obsSourceToJSON(source);
52
+
53
+ BrowserManager::Instance()->DispatchJSEvent("obsSceneChanged", jsonString);
54
+
55
+ obs_source_release(source);
56
+ break;
57
+ }
58
+ case OBS_FRONTEND_EVENT_SCENE_LIST_CHANGED:
59
+ break;
60
+ case OBS_FRONTEND_EVENT_TRANSITION_CHANGED:
61
+ break;
62
+ case OBS_FRONTEND_EVENT_TRANSITION_STOPPED:
63
+ break;
64
+ case OBS_FRONTEND_EVENT_TRANSITION_LIST_CHANGED:
65
+ break;
66
+ case OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGED:
67
+ break;
68
+ case OBS_FRONTEND_EVENT_SCENE_COLLECTION_LIST_CHANGED:
69
+ break;
70
+ case OBS_FRONTEND_EVENT_PROFILE_CHANGED:
71
+ break;
72
+ case OBS_FRONTEND_EVENT_PROFILE_LIST_CHANGED:
73
+ break;
74
+ case OBS_FRONTEND_EVENT_EXIT:
75
+ BrowserManager::Instance()->DispatchJSEvent("obsExit", nullptr);
76
+ break;
77
}
78
}
79
80
obs-studio-0.17.0.tar.xz/plugins/obs-browser/shared-apple/cef-isolation.h -> obs-studio-17.0.1.tar.xz/plugins/obs-browser/shared-apple/cef-isolation.h
Changed
29
1
2
#pragma once
3
4
#import <Foundation/Foundation.h>
5
+#include <jansson.h>
6
7
#include "browser-types.h"
8
9
10
height:(int)height
11
surfaceHandle:(BrowserSurfaceHandle)surfaceHandle;
12
- (void)invalidateClient:(id)client withException:(NSException *)exception;
13
+- (const char*)getCurrentSceneJSONData;
14
@end
15
16
@protocol CEFIsolatedClient
17
18
- (oneway void)sendFocus:(int)browserIdentifier focus:(BOOL)focus;
19
- (void)sendKeyClick:(int) browserIdentifier
20
event:(bycopy ObsKeyEventBridge *)event keyUp:(BOOL)keyUp;
21
+- (void)refreshPageNoCache:(const int)browserIdentifier;
22
+- (void)executeVisiblityJSCallback:(const int)browserIdentifier
23
+ visible:(BOOL)visible;
24
+- (void)executeSceneChangeJSCallback:(const char *)name;
25
+- (void)dispatchJSEvent:(const char *)eventName data:(const char*) jsonString;
26
@end
27
28
29
obs-studio-0.17.0.tar.xz/plugins/obs-browser/shared/browser-app.cpp -> obs-studio-17.0.1.tar.xz/plugins/obs-browser/shared/browser-app.cpp
Changed
143
1
2
3
#include <iostream>
4
#include <string>
5
+#include <jansson.h>
6
7
-#include "cefsimple/simple_handler.h"
8
+#include "fmt/format.h"
9
#include "include/cef_browser.h"
10
#include "include/cef_command_line.h"
11
#include "include/wrapper/cef_helpers.h"
12
13
{
14
CefRefPtr<CefV8Value> globalObj = context->GetGlobal();
15
16
- CefRefPtr<CefV8Value> obsStudioObj = CefV8Value::CreateObject(0);
17
+ CefRefPtr<CefV8Value> obsStudioObj = CefV8Value::CreateObject(0, 0);
18
globalObj->SetValue("obsstudio", obsStudioObj, V8_PROPERTY_ATTRIBUTE_NONE);
19
20
CefRefPtr<CefV8Value> pluginVersion = CefV8Value::CreateString(OBS_BROWSER_VERSION);
21
obsStudioObj->SetValue("pluginVersion", pluginVersion, V8_PROPERTY_ATTRIBUTE_NONE);
22
+
23
+ CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction("getCurrentScene", this);
24
+ obsStudioObj->SetValue("getCurrentScene", func, V8_PROPERTY_ATTRIBUTE_NONE);
25
}
26
27
void BrowserApp::ExecuteJSFunction(CefRefPtr<CefBrowser> browser,
28
29
30
bool BrowserApp::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
31
CefProcessId source_process,
32
- CefRefPtr<CefProcessMessage> message) {
33
+ CefRefPtr<CefProcessMessage> message)
34
+{
35
DCHECK(source_process == PID_BROWSER);
36
37
CefRefPtr<CefListValue> args = message->GetArgumentList();
38
39
ExecuteJSFunction(browser, "onVisibilityChange", arguments);
40
return true;
41
}
42
- else if (message->GetName() == "SceneChange") {
43
+ else if (message->GetName() == "DispatchJSEvent") {
44
+ CefRefPtr<CefV8Context> context = browser->GetMainFrame()->GetV8Context();
45
+
46
+ context->Enter();
47
+
48
+ CefRefPtr<CefV8Value> globalObj = context->GetGlobal();
49
+
50
+ // Build up a new json object to store the CustomEvent data in.
51
+ json_t *json = json_object();
52
+
53
+ if (args->GetSize() > 1) {
54
+ json_error_t error;
55
+
56
+ json_object_set_new(json, "detail", json_loads(args->GetString(1).ToString().c_str(), 0, &error));
57
+ }
58
+
59
+ char *jsonString = json_dumps(json, 0);
60
+
61
+ std::string script = fmt::format(
62
+ "new CustomEvent('{}', {});",
63
+ args->GetString(0).ToString(),
64
+ jsonString);
65
+
66
+ free(jsonString);
67
+
68
+ CefRefPtr<CefV8Value> returnValue;
69
+ CefRefPtr<CefV8Exception> exception;
70
+
71
+ // Create the CustomEvent object
72
+ // We have to use eval to invoke the new operator
73
+ context->Eval(script, browser->GetMainFrame()->GetURL(), 0, returnValue, exception);
74
+
75
CefV8ValueList arguments;
76
- arguments.push_back(CefV8Value::CreateString(args->GetString(0)));
77
+ arguments.push_back(returnValue);
78
+
79
+ CefRefPtr<CefV8Value> dispatchEvent = globalObj->GetValue("dispatchEvent");
80
+ dispatchEvent->ExecuteFunction(NULL, arguments);
81
+
82
+ context->Exit();
83
+
84
+ return true;
85
+ }
86
+ else if (message->GetName() == "executeCallback") {
87
+ CefRefPtr<CefV8Context> context = browser->GetMainFrame()->GetV8Context();
88
+
89
+ context->Enter();
90
+
91
+ int callbackID = message->GetArgumentList()->GetInt(0);
92
+ CefString jsonString = message->GetArgumentList()->GetString(1);
93
+
94
+ CefRefPtr<CefV8Value> callback = callbackMap[callbackID];
95
+
96
+ CefV8ValueList args;
97
+ args.push_back(CefV8Value::CreateString(jsonString));
98
+
99
+ CefRefPtr<CefV8Value> retval;
100
+ CefRefPtr<CefV8Exception> exception;
101
+ callback->ExecuteFunction(NULL, args);
102
+
103
+ context->Exit();
104
+
105
+ callbackMap.erase(callbackID);
106
+
107
+
108
+ return true;
109
+ }
110
+
111
+ return false;
112
+}
113
+
114
+// CefV8Handler::Execute
115
+bool BrowserApp::Execute(const CefString& name,
116
+ CefRefPtr<CefV8Value> object,
117
+ const CefV8ValueList& arguments,
118
+ CefRefPtr<CefV8Value>& retval,
119
+ CefString& exception)
120
+{
121
+ if (name == "getCurrentScene") {
122
+
123
+ if (arguments.size() == 1 && arguments[0]->IsFunction()) {
124
+ callbackId++;
125
+ callbackMap[callbackId] = arguments[0];
126
+ }
127
+
128
+ CefRefPtr<CefProcessMessage> msg = CefProcessMessage::Create("getCurrentScene");
129
+ CefRefPtr<CefListValue> args = msg->GetArgumentList();
130
+ args->SetInt(0, callbackId);
131
+
132
+ CefRefPtr<CefBrowser> browser =
133
+ CefV8Context::GetCurrentContext()->GetBrowser();
134
+ browser->SendProcessMessage(PID_BROWSER, msg);
135
136
- ExecuteJSFunction(browser , "onSceneChange", arguments);
137
return true;
138
}
139
140
+ // Function does not exist.
141
return false;
142
}
143
obs-studio-0.17.0.tar.xz/plugins/obs-browser/shared/browser-app.hpp -> obs-studio-17.0.1.tar.xz/plugins/obs-browser/shared/browser-app.hpp
Changed
35
1
2
#include <include/cef_render_process_handler.h>
3
4
class BrowserApp : public CefApp,
5
- public CefRenderProcessHandler
6
+ public CefRenderProcessHandler,
7
+ public CefV8Handler
8
{
9
10
public:
11
12
CefProcessId source_process,
13
CefRefPtr<CefProcessMessage> message) OVERRIDE;
14
15
+public: /* CefV8Handler */
16
+ virtual bool Execute(const CefString& name,
17
+ CefRefPtr<CefV8Value> object,
18
+ const CefV8ValueList& arguments,
19
+ CefRefPtr<CefV8Value>& retval,
20
+ CefString& exception) OVERRIDE;
21
+
22
private:
23
virtual void ExecuteJSFunction(CefRefPtr<CefBrowser> browser,
24
const char *functionName,
25
CefV8ValueList arguments);
26
-
27
- IMPLEMENT_REFCOUNTING(BrowserApp);
28
29
+ typedef std::map<int, CefRefPtr<CefV8Value>> CallbackMap;
30
+ int callbackId;
31
+ CallbackMap callbackMap;
32
+
33
+ IMPLEMENT_REFCOUNTING(BrowserApp);
34
};
35
obs-studio-0.17.0.tar.xz/plugins/obs-browser/shared/browser-client.cpp -> obs-studio-17.0.1.tar.xz/plugins/obs-browser/shared/browser-client.cpp
Changed
46
1
2
#include <include/cef_render_handler.h>
3
4
#include "browser-client.hpp"
5
+#include "browser-obs-bridge.hpp"
6
7
BrowserClient::BrowserClient(CefRenderHandler *renderHandler,
8
- CefLoadHandler *loadHandler)
9
- : renderHandler(renderHandler), loadHandler(loadHandler)
10
+ CefLoadHandler *loadHandler, BrowserOBSBridge *browserOBSBridge)
11
+ : renderHandler(renderHandler), loadHandler(loadHandler), browserOBSBridge(browserOBSBridge)
12
{
13
}
14
15
16
17
// remove all context menu contributions
18
model->Clear();
19
-}
20
\ No newline at end of file
21
+}
22
+
23
+bool BrowserClient::OnProcessMessageReceived(
24
+ CefRefPtr<CefBrowser> browser,
25
+ CefProcessId source_process,
26
+ CefRefPtr<CefProcessMessage> message)
27
+{
28
+ const std::string& message_name = message->GetName();
29
+ if (message_name == "getCurrentScene") {
30
+
31
+ int callbackID = message->GetArgumentList()->GetInt(0);
32
+
33
+ const char* jsonString = browserOBSBridge->GetCurrentSceneJSONData();
34
+
35
+ CefRefPtr<CefProcessMessage> msg = CefProcessMessage::Create("executeCallback");
36
+ CefRefPtr<CefListValue> args = msg->GetArgumentList();
37
+ args->SetInt(0, callbackID);
38
+ args->SetString(1, jsonString);
39
+
40
+ browser->SendProcessMessage(PID_RENDERER, msg);
41
+
42
+ return true;
43
+ }
44
+ return false;
45
+}
46
obs-studio-0.17.0.tar.xz/plugins/obs-browser/shared/browser-client.hpp -> obs-studio-17.0.1.tar.xz/plugins/obs-browser/shared/browser-client.hpp
Changed
45
1
2
#pragma once
3
4
#include <include/cef_client.h>
5
+#include "browser-obs-bridge.hpp"
6
7
class BrowserSource;
8
class BrowserRenderHandler;
9
10
{
11
public:
12
BrowserClient(CefRenderHandler *renderHandler,
13
- CefLoadHandler *loadHandler);
14
+ CefLoadHandler *loadHandler,
15
+ BrowserOBSBridge *browserOBSBridge);
16
17
public: /* CefClient overrides */
18
virtual CefRefPtr<CefRenderHandler> GetRenderHandler() OVERRIDE;
19
20
virtual CefRefPtr<CefContextMenuHandler> GetContextMenuHandler()
21
OVERRIDE;
22
virtual CefRefPtr<CefLoadHandler> GetLoadHandler() OVERRIDE;
23
+ virtual bool OnProcessMessageReceived(
24
+ CefRefPtr<CefBrowser> browser,
25
+ CefProcessId source_process,
26
+ CefRefPtr<CefProcessMessage> message) OVERRIDE;
27
28
public: /* CefLifeSpanHandler overrides */
29
virtual bool OnBeforePopup(CefRefPtr<CefBrowser> browser,
30
31
CefRefPtr<CefFrame> frame,
32
CefRefPtr<CefContextMenuParams> params,
33
CefRefPtr<CefMenuModel> model);
34
+
35
private:
36
CefRefPtr<CefRenderHandler> renderHandler;
37
CefRefPtr<CefLoadHandler> loadHandler;
38
+ BrowserOBSBridge *browserOBSBridge;
39
40
public:
41
IMPLEMENT_REFCOUNTING(BrowserClient);
42
-};
43
\ No newline at end of file
44
+};
45
obs-studio-0.17.0.tar.xz/plugins/obs-browser/shared/browser-listener.hpp -> obs-studio-17.0.1.tar.xz/plugins/obs-browser/shared/browser-listener.hpp
Changed
9
1
2
BrowserSurfaceHandle *surfaceHandle) = 0;
3
virtual void DestroySurface(BrowserSurfaceHandle surfaceHandle) = 0;
4
virtual void Invalidated() = 0;
5
-
6
};
7
8
class BrowserListener : public BrowserListenerBase
9
obs-studio-0.17.0.tar.xz/plugins/obs-browser/shared/browser-manager.hpp -> obs-studio-17.0.1.tar.xz/plugins/obs-browser/shared/browser-manager.hpp
Changed
18
1
2
#pragma once
3
4
#include <memory>
5
+#include <jansson.h>
6
7
class BrowserListener;
8
struct BrowserSettings;
9
10
11
void RefreshPageNoCache(int browserIdentifier);
12
13
+ void DispatchJSEvent(const char *eventName, const char *jsonString);
14
+
15
private:
16
class Impl;
17
std::unique_ptr<Impl> pimpl;
18
obs-studio-17.0.1.tar.xz/plugins/obs-browser/shared/browser-obs-bridge.hpp
Added
10
1
2
+#pragma once
3
+
4
+class BrowserOBSBridge
5
+{
6
+public:
7
+ virtual const char* GetCurrentSceneJSONData() = 0;
8
+};
9
\ No newline at end of file
10
obs-studio-0.17.0.tar.xz/plugins/obs-browser/shared/browser-source.hpp -> obs-studio-17.0.1.tar.xz/plugins/obs-browser/shared/browser-source.hpp
Changed
9
1
2
uint32_t height;
3
uint32_t fps;
4
bool shutdown;
5
+ bool restart_when_active;
6
7
int browserIdentifier;
8
9
obs-studio-0.17.0.tar.xz/plugins/obs-browser/shared/browser-version.h -> obs-studio-17.0.1.tar.xz/plugins/obs-browser/shared/browser-version.h
Changed
8
1
2
#pragma once
3
4
-#define OBS_BROWSER_VERSION "1.25.0"
5
\ No newline at end of file
6
+#define OBS_BROWSER_VERSION "1.27.0"
7
\ No newline at end of file
8
obs-studio-17.0.1.tar.xz/plugins/obs-browser/shared/util.cpp
Added
24
1
2
+#include "util.hpp"
3
+
4
+/**
5
+ Takes an OBS source and generates a JSON encoded string representing information about the source.
6
+
7
+ @param source is the OBS source that we want to turn into json data
8
+ @return json encoded string
9
+*/
10
+const char* obsSourceToJSON(obs_source_t *source)
11
+{
12
+ const char *name = obs_source_get_name(source);
13
+
14
+ json_t *obj = json_object();
15
+ json_object_set_new(obj, "name", json_string(name));
16
+ json_object_set_new(obj, "width", json_integer(obs_source_get_width(source)));
17
+ json_object_set_new(obj, "height", json_integer(obs_source_get_height(source)));
18
+ const char *jsonString = json_dumps(obj, 0);
19
+ free(obj);
20
+
21
+ return jsonString;
22
+}
23
\ No newline at end of file
24
obs-studio-17.0.1.tar.xz/plugins/obs-browser/shared/util.hpp
Added
9
1
2
+#pragma once
3
+
4
+#include <jansson.h>
5
+#include <obs-frontend-api.h>
6
+
7
+extern const char* obsSourceToJSON(obs_source_t *source);
8
\ No newline at end of file
9
obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/ca-ES.ini -> obs-studio-17.0.1.tar.xz/plugins/obs-ffmpeg/data/locale/ca-ES.ini
Changed
16
1
2
KeyframeIntervalSec="Interval de fotograma clau (en segons, 0 = automàtic)"
3
Lossless="Sense pèrdues"
4
5
+BFrames="B-frames"
6
7
NVENC.Use2Pass="Utilitza codificació en dues passades"
8
NVENC.Preset.default="Per defecte"
9
10
MediaFileFilter.AudioFiles="Arxius d'àudio"
11
MediaFileFilter.AllFiles="Tots els fitxers"
12
13
+ReplayBuffer="Memòria intermèdia de reproducció"
14
+ReplayBuffer.Save="Desa la repetició"
15
16
obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/cs-CZ.ini -> obs-studio-17.0.1.tar.xz/plugins/obs-ffmpeg/data/locale/cs-CZ.ini
Changed
9
1
2
KeyframeIntervalSec="Interval klíč. snímků (vteřiny, 0=auto)"
3
Lossless="Lossless"
4
5
+BFrames="B-frames"
6
7
NVENC.Use2Pass="Použít dvoustupňové enkódování"
8
NVENC.Preset.default="Výchozí"
9
obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/hu-HU.ini -> obs-studio-17.0.1.tar.xz/plugins/obs-ffmpeg/data/locale/hu-HU.ini
Changed
9
1
2
FFmpegOutput="FFmpeg kimenet"
3
FFmpegAAC="FFmpeg alapértelmezett AAC kódoló"
4
-Bitrate="Bitráta"
5
+Bitrate="Bitsebesség"
6
Preset="Készlet"
7
RateControl="Sebesség Vezérlés"
8
KeyframeIntervalSec="Kulcsképkocka időköze (másodperc, 0=auto)"
9
obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/it-IT.ini -> obs-studio-17.0.1.tar.xz/plugins/obs-ffmpeg/data/locale/it-IT.ini
Changed
16
1
2
KeyframeIntervalSec="Intervallo Keyframe (secondi, 0=automatico)"
3
Lossless="Lossless"
4
5
+BFrames="B-frames"
6
7
NVENC.Use2Pass="Usa codifica in due passaggi"
8
NVENC.Preset.default="Predefinito"
9
10
MediaFileFilter.AudioFiles="File audio"
11
MediaFileFilter.AllFiles="Tutti i file"
12
13
+ReplayBuffer="Buffer di Replay"
14
+ReplayBuffer.Save="Salva Replay"
15
16
obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/ru-RU.ini -> obs-studio-17.0.1.tar.xz/plugins/obs-ffmpeg/data/locale/ru-RU.ini
Changed
16
1
2
KeyframeIntervalSec="Интервал ключевых кадров (сек, 0=авто)"
3
Lossless="Без потерь"
4
5
+BFrames="B-Кадры"
6
7
NVENC.Use2Pass="Использовать двухпроходное кодирование"
8
NVENC.Preset.default="По умолчанию"
9
10
MediaFileFilter.AudioFiles="Аудиофайлы"
11
MediaFileFilter.AllFiles="Все файлы"
12
13
+ReplayBuffer="Буфер повтора"
14
ReplayBuffer.Save="Сохранить повтор"
15
16
obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/sv-SE.ini -> obs-studio-17.0.1.tar.xz/plugins/obs-ffmpeg/data/locale/sv-SE.ini
Changed
16
1
2
KeyframeIntervalSec="Intervall för keyframes (sekunder, 0=automatisk)"
3
Lossless="Förlustfri"
4
5
+BFrames="B-bildrutor"
6
7
NVENC.Use2Pass="Använd tvåpassavkodning"
8
NVENC.Preset.default="Standard"
9
10
MediaFileFilter.AudioFiles="Ljudfiler"
11
MediaFileFilter.AllFiles="Alla filer"
12
13
+ReplayBuffer="Reprisbuffert"
14
+ReplayBuffer.Save="Spara repris"
15
16
obs-studio-0.17.0.tar.xz/plugins/obs-ffmpeg/data/locale/tr-TR.ini -> obs-studio-17.0.1.tar.xz/plugins/obs-ffmpeg/data/locale/tr-TR.ini
Changed
29
1
2
FFmpegAAC="FFmpeg Varsayılan AAC Kodlayıcı"
3
Bitrate="Bit hızı"
4
Preset="Ön Tanımlı"
5
+RateControl="Oran Kontrolü"
6
KeyframeIntervalSec="Anahtarkare Aralığı (saniye, 0=otomatik)"
7
Lossless="Kayıpsız"
8
9
+BFrames="B-frame'leri"
10
11
+NVENC.Use2Pass="İki Taramalı Kodlama Kullan"
12
NVENC.Preset.default="Varsayılan"
13
NVENC.Preset.hq="Yüksek Kalite"
14
NVENC.Preset.hp="Yüksek Performans"
15
16
DiscardNonIntra="Intra Olmayan Kareler"
17
DiscardNonKey="Anahtar Olmayan Kareler"
18
DiscardAll="Tüm Kareler (Dikkatli Olun!)"
19
+RestartWhenActivated="Yeniden oynatmayı kaynak etkin olduğunda yeniden başlat"
20
ColorRange="YUV Renk Aralığı"
21
ColorRange.Auto="Otomatik"
22
ColorRange.Partial="Kısmi"
23
24
MediaFileFilter.AllFiles="Tüm Dosyalar"
25
26
ReplayBuffer="Tekrar Oynatma Arabelleği"
27
+ReplayBuffer.Save="Yeniden Oynatmayı Kaydet"
28
29
obs-studio-0.17.0.tar.xz/plugins/obs-filters/color-correction-filter.c -> obs-studio-17.0.1.tar.xz/plugins/obs-filters/color-correction-filter.c
Changed
37
1
2
};
3
4
const static float root3 = 0.57735f;
5
+const static float red_weight = 0.299f;
6
+const static float green_weight = 0.587f;
7
+const static float blue_weight = 0.114f;
8
+
9
10
/*
11
* As the functions' namesake, this provides the internal name of your Filter,
12
13
SETTING_SATURATION) + 1.0f;
14
15
/* Factor in the selected color weights. */
16
- float one_minus_sat = (1.0f - filter->saturation) / 3.0f;
17
- float sat_val = one_minus_sat + filter->saturation;
18
+ float one_minus_sat_red = (1.0f - filter->saturation) * red_weight;
19
+ float one_minus_sat_green = (1.0f - filter->saturation) * green_weight;
20
+ float one_minus_sat_blue = (1.0f - filter->saturation) * blue_weight;
21
+ float sat_val_red = one_minus_sat_red + filter->saturation;
22
+ float sat_val_green = one_minus_sat_green + filter->saturation;
23
+ float sat_val_blue = one_minus_sat_blue + filter->saturation;
24
25
/* Now we build our Saturation matrix. */
26
filter->sat_matrix = (struct matrix4)
27
{
28
- sat_val, one_minus_sat, one_minus_sat, 0.0f,
29
- one_minus_sat, sat_val, one_minus_sat, 0.0f,
30
- one_minus_sat, one_minus_sat, sat_val, 0.0f,
31
+ sat_val_red, one_minus_sat_red, one_minus_sat_red, 0.0f,
32
+ one_minus_sat_green, sat_val_green, one_minus_sat_green, 0.0f,
33
+ one_minus_sat_blue, one_minus_sat_blue, sat_val_blue, 0.0f,
34
0.0f, 0.0f, 0.0f, 1.0f
35
};
36
37
obs-studio-0.17.0.tar.xz/plugins/obs-filters/data/color_correction_filter.effect -> obs-studio-17.0.1.tar.xz/plugins/obs-filters/data/color_correction_filter.effect
Changed
40
1
2
float2 uv : TEXCOORD0;
3
};
4
5
-struct CurrentPixel {
6
- float4 current_pixel;
7
-};
8
-
9
VertData VSDefault(VertData vert_in)
10
{
11
VertData vert_out;
12
13
14
float4 PSColorFilterRGBA(VertData vert_in) : TARGET
15
{
16
- /* Realize the struct. */
17
- CurrentPixel pixel = (CurrentPixel) 0;
18
-
19
/* Grab the current pixel to perform operations on. */
20
- pixel.current_pixel = image.Sample(textureSampler, vert_in.uv);
21
+ float4 currentPixel = image.Sample(textureSampler, vert_in.uv);
22
23
/* Always address the gamma first. */
24
- pixel.current_pixel.rgb = pow(pixel.current_pixel.rgb, gamma);
25
+ currentPixel.rgb = pow(currentPixel.rgb, gamma);
26
27
/* Much easier to manipulate pixels for these types of operations
28
* when in a matrix such as the below. See
29
* http://www.graficaobscura.com/matrix/index.html and
30
* https://docs.rainmeter.net/tips/colormatrix-guide/for more info.
31
*/
32
- pixel.current_pixel = mul(color_matrix, pixel.current_pixel);
33
+ currentPixel = mul(color_matrix, currentPixel);
34
35
- return pixel.current_pixel;
36
+ return currentPixel;
37
}
38
39
technique Draw
40
obs-studio-0.17.0.tar.xz/plugins/obs-filters/data/locale/ca-ES.ini -> obs-studio-17.0.1.tar.xz/plugins/obs-filters/data/locale/ca-ES.ini
Changed
8
1
2
ScaleFiltering.Bicubic="Bicúbic"
3
ScaleFiltering.Lanczos="Lanczos"
4
NoiseSuppress.SuppressLevel="Nivell de supressió (dB)"
5
+Saturation="Saturació"
6
+HueShift="Cavi de tonalitat"
7
8
obs-studio-0.17.0.tar.xz/plugins/obs-filters/data/locale/cs-CZ.ini -> obs-studio-17.0.1.tar.xz/plugins/obs-filters/data/locale/cs-CZ.ini
Changed
8
1
2
ScaleFiltering.Bicubic="Bikubický"
3
ScaleFiltering.Lanczos="Lanczos"
4
NoiseSuppress.SuppressLevel="Úroveň potlačení (dB)"
5
+Saturation="Saturace"
6
+HueShift="Posun odstínu"
7
8
obs-studio-0.17.0.tar.xz/plugins/obs-filters/data/locale/eu-ES.ini -> obs-studio-17.0.1.tar.xz/plugins/obs-filters/data/locale/eu-ES.ini
Changed
8
1
2
ScaleFiltering.Bicubic="Bikubikoa"
3
ScaleFiltering.Lanczos="Lanczos"
4
NoiseSuppress.SuppressLevel="Kenketaren maila (dB)"
5
+Saturation="Margoasetasuna"
6
+HueShift="Nabardura Aldaketa"
7
8
obs-studio-0.17.0.tar.xz/plugins/obs-filters/data/locale/fi-FI.ini -> obs-studio-17.0.1.tar.xz/plugins/obs-filters/data/locale/fi-FI.ini
Changed
8
1
2
ScaleFiltering.Bicubic="Bicubic"
3
ScaleFiltering.Lanczos="Lanczos"
4
NoiseSuppress.SuppressLevel="Vaimennustaso (dB)"
5
+Saturation="Värikylläisyys"
6
+HueShift="Värisävy"
7
8
obs-studio-0.17.0.tar.xz/plugins/obs-filters/data/locale/it-IT.ini -> obs-studio-17.0.1.tar.xz/plugins/obs-filters/data/locale/it-IT.ini
Changed
8
1
2
ScaleFiltering.Bicubic="Bicubico"
3
ScaleFiltering.Lanczos="Lanczos"
4
NoiseSuppress.SuppressLevel="Livello di soppressione (dB)"
5
+Saturation="Saturazione"
6
+HueShift="Cambio di tonalità"
7
8
obs-studio-0.17.0.tar.xz/plugins/obs-filters/data/locale/ru-RU.ini -> obs-studio-17.0.1.tar.xz/plugins/obs-filters/data/locale/ru-RU.ini
Changed
8
1
2
ScaleFiltering.Bicubic="Бикубическая"
3
ScaleFiltering.Lanczos="Метод Ланцоша"
4
NoiseSuppress.SuppressLevel="Уровень подавления (дБ)"
5
+Saturation="Насыщенность"
6
+HueShift="Сдвиг оттенка"
7
8
obs-studio-0.17.0.tar.xz/plugins/obs-filters/data/locale/sv-SE.ini -> obs-studio-17.0.1.tar.xz/plugins/obs-filters/data/locale/sv-SE.ini
Changed
7
1
2
ScaleFiltering.Bicubic="Bikubisk"
3
ScaleFiltering.Lanczos="Lanczos"
4
NoiseSuppress.SuppressLevel="Brusreduceringsnivå (dB)"
5
+Saturation="Mättnad"
6
7
obs-studio-0.17.0.tar.xz/plugins/obs-filters/data/locale/tr-TR.ini -> obs-studio-17.0.1.tar.xz/plugins/obs-filters/data/locale/tr-TR.ini
Changed
30
1
2
ColorFilter="Renk Düzeltme"
3
MaskFilter="Görüntü Maskesi/Blend"
4
AsyncDelayFilter="Görüntü Gecikmesi (Async)"
5
+CropFilter="Kes/Kaydır"
6
ScrollFilter="Kaydır"
7
ChromaKeyFilter="Chroma Anahtarı"
8
ColorKeyFilter="Renk Anahtarı"
9
SharpnessFilter="Keskinleştirme"
10
+ScaleFilter="Ölçeklendirme/Boy Oranı"
11
NoiseGate="Gürültü Filtresi"
12
NoiseSuppress="Gürültü Bastırma"
13
Gain="Kazanç"
14
15
NoiseGate.HoldTime="Kavrama Süresi (milisaniye)"
16
NoiseGate.ReleaseTime="Bırakma Süresi (milisaniye)"
17
Gain.GainDB="Kazanç (dB)"
18
+StretchImage="Görüntüyü Uzat (görüntü boy oranını görmezden gelir)"
19
Resolution="Çözünürlük"
20
None="Hiçbiri"
21
ScaleFiltering="Ölçek Filtreleme"
22
23
ScaleFiltering.Bilinear="Bilinear"
24
ScaleFiltering.Bicubic="Bicubic"
25
ScaleFiltering.Lanczos="Lanczos"
26
+NoiseSuppress.SuppressLevel="Bastırma Düzeyi (dB)"
27
+Saturation="Renk Doygunluğu"
28
+HueShift="Ton Kayması"
29
30
obs-studio-0.17.0.tar.xz/plugins/obs-filters/data/locale/uk-UA.ini -> obs-studio-17.0.1.tar.xz/plugins/obs-filters/data/locale/uk-UA.ini
Changed
8
1
2
ScaleFiltering.Bicubic="Бікубічний"
3
ScaleFiltering.Lanczos="Ланцош"
4
NoiseSuppress.SuppressLevel="Рівень подавлення (дБ)"
5
+Saturation="Насиченість"
6
+HueShift="Відтінок"
7
8
obs-studio-0.17.0.tar.xz/plugins/obs-libfdk/data/locale/hu-HU.ini -> obs-studio-17.0.1.tar.xz/plugins/obs-libfdk/data/locale/hu-HU.ini
Changed
7
1
2
LibFDK="libfdk AAC kódoló"
3
-Bitrate="Bitráta"
4
+Bitrate="Bitsebesség"
5
Afterburner="AAC Afterburner engedélyezése"
6
7
obs-studio-0.17.0.tar.xz/plugins/obs-outputs/net-if.h -> obs-studio-17.0.1.tar.xz/plugins/obs-outputs/net-if.h
Changed
9
1
2
# ifdef __linux__
3
# include <linux/if_link.h>
4
# elif __FreeBSD__
5
+# include <netinet/in.h>
6
# ifndef _GNU_SOURCE
7
# define _GNU_SOURCE
8
# define __NET_IF_GNU_SOURCE__
9
obs-studio-0.17.0.tar.xz/plugins/obs-qsv11/data/locale/hu-HU.ini -> obs-studio-17.0.1.tar.xz/plugins/obs-qsv11/data/locale/hu-HU.ini
Changed
10
1
2
TargetUsage="Felhasználási cél"
3
-Bitrate="Bitráta"
4
-MaxBitrate="Max bitráta"
5
+Bitrate="Bitsebesség"
6
+MaxBitrate="Max bitsebesség"
7
RateControl="Sebesség Vezérlés"
8
KeyframeIntervalSec="Kulcsképkocka időköze (másodperc, 0=auto)"
9
Profile="Profil"
10
obs-studio-0.17.0.tar.xz/plugins/obs-qsv11/data/locale/tr-TR.ini -> obs-studio-17.0.1.tar.xz/plugins/obs-qsv11/data/locale/tr-TR.ini
Changed
14
1
2
TargetUsage="Hedef Kullanımı"
3
Bitrate="Bit hızı"
4
MaxBitrate="Maks Bit hızı"
5
+RateControl="Oran Kontrolü"
6
KeyframeIntervalSec="Anahtarkare Aralığı (saniye, 0=otomatik)"
7
Profile="Profil"
8
+AsyncDepth="Eşzamansız Derinlik"
9
Accuracy="Doğruluk"
10
+Convergence="Yakınsama"
11
ICQQuality="ICQ Kalitesi"
12
+LookAheadDepth="İleri Yönlü Derinlik"
13
14
obs-studio-0.17.0.tar.xz/plugins/obs-text/data/locale/tr-TR.ini -> obs-studio-17.0.1.tar.xz/plugins/obs-text/data/locale/tr-TR.ini
Changed
9
1
2
Outline.Color="Anahat Rengi"
3
Outline.Opacity="Anahat Saydamlığı"
4
UseCustomExtents="İsteğe Bağlı Metin Boyutu Kullan"
5
+UseCustomExtents.Wrap="Metni Kaydır"
6
Width="Genişlik"
7
Height="Yükseklik"
8
9
obs-studio-0.17.0.tar.xz/plugins/obs-transitions/data/locale/tr-TR.ini -> obs-studio-17.0.1.tar.xz/plugins/obs-transitions/data/locale/tr-TR.ini
Changed
10
1
2
Direction.Down="Aşağı"
3
SwipeIn="İçeri Kaydır"
4
Color="Renk"
5
+SwitchPoint="En yüksek Renk Noktası (yüzde)"
6
+LumaWipeTransition="Luma Wipe"
7
LumaWipe.Image="Görüntü"
8
LumaWipe.Invert="Ters Çevir"
9
LumaWipe.Softness="Yumuşaklık"
10
obs-studio-0.17.0.tar.xz/plugins/obs-x264/data/locale/hu-HU.ini -> obs-studio-17.0.1.tar.xz/plugins/obs-x264/data/locale/hu-HU.ini
Changed
7
1
2
-Bitrate="Bitráta"
3
+Bitrate="Bitsebesség"
4
CustomBufsize="Egyéni pufferméret használata"
5
BufferSize="Pufferméret"
6
RateControl="Sebesség Vezérlés"
7
obs-studio-0.17.0.tar.xz/plugins/obs-x264/data/locale/tr-TR.ini -> obs-studio-17.0.1.tar.xz/plugins/obs-x264/data/locale/tr-TR.ini
Changed
9
1
2
Bitrate="Bit hızı"
3
CustomBufsize="İsteğe Bağlı Arabellek Boyutu Kullan"
4
BufferSize="Arabellek Boyutu"
5
+RateControl="Oran Kontrolü"
6
CRF="CRF"
7
KeyframeIntervalSec="Anahtarkare Aralığı (saniye, 0=otomatik)"
8
CPUPreset="CPU Kullanım Önayarı (yüksek = az CPU kullanımı)"
9
obs-studio-0.17.0.tar.xz/plugins/obs-x264/obs-x264.c -> obs-studio-17.0.1.tar.xz/plugins/obs-x264/obs-x264.c
Changed
22
1
2
preset, profile, tune);
3
}
4
5
+#define OPENCL_ALIAS "opencl_is_experimental_and_potentially_unstable"
6
+
7
static inline void set_param(struct obs_x264 *obsx264, const char *param)
8
{
9
char *name;
10
11
strcmp(name, "fps") != 0 &&
12
strcmp(name, "force-cfr") != 0 &&
13
strcmp(name, "width") != 0 &&
14
- strcmp(name, "height") != 0) {
15
+ strcmp(name, "height") != 0 &&
16
+ strcmp(name, "opencl") != 0) {
17
+ if (strcmp(name, OPENCL_ALIAS) == 0)
18
+ strcpy(name, "opencl");
19
if (x264_param_parse(&obsx264->params, name, val) != 0)
20
warn("x264 param: %s failed", param);
21
}
22
obs-studio-0.17.0.tar.xz/plugins/rtmp-services/data/package.json -> obs-studio-17.0.1.tar.xz/plugins/rtmp-services/data/package.json
Changed
14
1
2
{
3
"url": "https://obsproject.com/obs2_update/rtmp-services",
4
- "version": 43,
5
+ "version": 44,
6
"files": [
7
{
8
"name": "services.json",
9
- "version": 43
10
+ "version": 44
11
}
12
]
13
}
14
obs-studio-0.17.0.tar.xz/plugins/rtmp-services/data/services.json -> obs-studio-17.0.1.tar.xz/plugins/rtmp-services/data/services.json
Changed
10
1
2
"recommended": {
3
"keyint": 2,
4
"profile": "main",
5
- "max video bitrate": 18000,
6
+ "max video bitrate": 51000,
7
"max audio bitrate": 160
8
}
9
},
10
obs-studio-0.17.0.tar.xz/plugins/vlc-video/data/locale/tr-TR.ini -> obs-studio-17.0.1.tar.xz/plugins/vlc-video/data/locale/tr-TR.ini
Changed
10
1
2
VLCSource="VLC Video Kaynağı"
3
Playlist="Oynatma Listesi"
4
+LoopPlaylist="Oynatma Listesini Yinele"
5
+PlaybackBehavior="Görünürlük davranışı"
6
+PlaybackBehavior.StopRestart="Görünür değilken durdur, görünür olunca yeniden başlat"
7
+PlaybackBehavior.PauseUnpause="Görünür değilken duraklat, görünür olunca oynat"
8
+PlaybackBehavior.AlwaysPlay="Görünür değilken bile oynat"
9
10
obs-studio-0.17.0.tar.xz/plugins/win-capture/data/locale/tr-TR.ini -> obs-studio-17.0.1.tar.xz/plugins/win-capture/data/locale/tr-TR.ini
Changed
16
1
2
PrimaryMonitor="Birincil Ekran"
3
GameCapture="Oyun Yakalama"
4
GameCapture.AnyFullscreen="Tam ekran herhangi bir uygulamayı yakala"
5
+GameCapture.CaptureWindow="Belirli bir pencereyi yakala"
6
+GameCapture.UseHotkey="Ön plandaki pencereyi kısayol ile yakala"
7
GameCapture.ForceScaling="Zorla Ölçekle"
8
GameCapture.ScaleRes="Ölçekleme Çözünürlüğü"
9
GameCapture.LimitFramerate="Yakalama kare hızını sınırlandır"
10
GameCapture.CaptureOverlays="Üçüncü taraf katmanları yakala (steam vb.)"
11
GameCapture.AntiCheatHook="Anti-hile uyumluluğunu kullan"
12
+GameCapture.HotkeyStart="Ön plandaki pencereyi yakala"
13
+GameCapture.HotkeyStop="Yakalamayı devre dışı bırak"
14
Mode="Mod"
15
16
obs-studio-0.17.0.tar.xz/plugins/win-capture/game-capture.c -> obs-studio-17.0.1.tar.xz/plugins/win-capture/game-capture.c
Changed
130
1
2
ipc_pipe_server_t pipe;
3
gs_texture_t *texture;
4
struct hook_info *global_hook_info;
5
- HANDLE keepalive_thread;
6
- DWORD keepalive_thread_id;
7
+ HANDLE keepalive_mutex;
8
HANDLE hook_init;
9
HANDLE hook_restart;
10
HANDLE hook_stop;
11
12
gc->data = NULL;
13
}
14
15
- if (gc->keepalive_thread) {
16
- PostThreadMessage(gc->keepalive_thread_id, WM_QUIT, 0, 0);
17
- WaitForSingleObject(gc->keepalive_thread, 300);
18
- close_handle(&gc->keepalive_thread);
19
- }
20
-
21
if (gc->app_sid) {
22
LocalFree(gc->app_sid);
23
gc->app_sid = NULL;
24
25
close_handle(&gc->hook_exit);
26
close_handle(&gc->hook_init);
27
close_handle(&gc->hook_data_map);
28
+ close_handle(&gc->keepalive_mutex);
29
close_handle(&gc->global_hook_info_map);
30
close_handle(&gc->target_process);
31
close_handle(&gc->texture_mutexes[0]);
32
33
return true;
34
}
35
36
-struct keepalive_data {
37
- struct game_capture *gc;
38
- HANDLE initialized;
39
-};
40
-
41
-#define DEF_FLAGS (WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS)
42
-
43
-static DWORD WINAPI keepalive_window_thread(struct keepalive_data *data)
44
-{
45
- HANDLE initialized = data->initialized;
46
- struct game_capture *gc = data->gc;
47
- wchar_t new_name[64];
48
- WNDCLASSW wc;
49
- HWND window;
50
- MSG msg;
51
-
52
- _snwprintf(new_name, sizeof(new_name), L"%s%lu",
53
- WINDOW_HOOK_KEEPALIVE, gc->process_id);
54
-
55
- memset(&wc, 0, sizeof(wc));
56
- wc.style = CS_OWNDC;
57
- wc.hInstance = GetModuleHandleW(NULL);
58
- wc.lpfnWndProc = (WNDPROC)DefWindowProc;
59
- wc.lpszClassName = new_name;
60
-
61
- if (!RegisterClass(&wc)) {
62
- warn("Failed to create keepalive window class: %lu",
63
- GetLastError());
64
- return 0;
65
- }
66
-
67
- window = CreateWindowExW(0, new_name, NULL, DEF_FLAGS, 0, 0, 1, 1,
68
- NULL, NULL, wc.hInstance, NULL);
69
- if (!window) {
70
- warn("Failed to create keepalive window: %lu",
71
- GetLastError());
72
- return 0;
73
- }
74
-
75
- SetEvent(initialized);
76
-
77
- while (GetMessage(&msg, NULL, 0, 0)) {
78
- TranslateMessage(&msg);
79
- DispatchMessage(&msg);
80
- }
81
-
82
- DestroyWindow(window);
83
- UnregisterClassW(new_name, wc.hInstance);
84
-
85
- return 0;
86
-}
87
-
88
static inline bool init_keepalive(struct game_capture *gc)
89
{
90
- struct keepalive_data data;
91
- HANDLE initialized = CreateEvent(NULL, false, false, NULL);
92
-
93
- data.gc = gc;
94
- data.initialized = initialized;
95
+ wchar_t new_name[64];
96
+ _snwprintf(new_name, 64, L"%s%lu", WINDOW_HOOK_KEEPALIVE,
97
+ gc->process_id);
98
99
- gc->keepalive_thread = CreateThread(NULL, 0,
100
- (LPTHREAD_START_ROUTINE)keepalive_window_thread,
101
- &data, 0, &gc->keepalive_thread_id);
102
- if (!gc->keepalive_thread) {
103
- warn("Failed to create keepalive window thread: %lu",
104
- GetLastError());
105
+ gc->keepalive_mutex = CreateMutexW(NULL, false, new_name);
106
+ if (!gc->keepalive_mutex) {
107
+ warn("Failed to create keepalive mutex: %lu", GetLastError());
108
return false;
109
}
110
111
- WaitForSingleObject(initialized, INFINITE);
112
- CloseHandle(initialized);
113
-
114
return true;
115
}
116
117
118
gc->global_hook_info->capture_overlay = gc->config.capture_overlays;
119
gc->global_hook_info->force_shmem = gc->config.force_shmem;
120
gc->global_hook_info->use_scale = gc->config.force_scaling;
121
- gc->global_hook_info->cx = gc->config.scale_cx;
122
- gc->global_hook_info->cy = gc->config.scale_cy;
123
+ if (gc->config.scale_cx)
124
+ gc->global_hook_info->cx = gc->config.scale_cx;
125
+ if (gc->config.scale_cy)
126
+ gc->global_hook_info->cy = gc->config.scale_cy;
127
reset_frame_interval(gc);
128
129
obs_enter_graphics();
130
obs-studio-0.17.0.tar.xz/plugins/win-capture/graphics-hook/graphics-hook.h -> obs-studio-17.0.1.tar.xz/plugins/win-capture/graphics-hook/graphics-hook.h
Changed
16
1
2
3
static inline bool capture_alive(void)
4
{
5
- return !!FindWindowW(keepalive_name, NULL);
6
+ HANDLE handle = OpenMutexW(SYNCHRONIZE, false, keepalive_name);
7
+ CloseHandle(handle);
8
+
9
+ if (handle)
10
+ return true;
11
+
12
+ return GetLastError() != ERROR_FILE_NOT_FOUND;
13
}
14
15
static inline bool capture_active(void)
16
obs-studio-0.17.0.tar.xz/plugins/win-capture/window-helpers.c -> obs-studio-17.0.1.tar.xz/plugins/win-capture/window-helpers.c
Changed
37
1
2
HWND child;
3
4
GetWindowThreadProcessId(parent, &parent_id);
5
- child = FindWindowEx(parent, NULL, NULL, NULL);
6
+ child = GetWindow(parent, GW_CHILD);
7
8
while (child) {
9
DWORD child_id = 0;
10
11
if (child_id != parent_id)
12
return child;
13
14
- child = FindWindowEx(parent, child, NULL, NULL);
15
+ child = GetNextWindow(child, GW_HWNDNEXT);
16
}
17
18
return NULL;
19
20
}
21
22
while (true) {
23
- window = FindWindowEx(GetDesktopWindow(), window, NULL, NULL);
24
+ window = GetNextWindow(window, GW_HWNDNEXT);
25
if (!window || check_window_valid(window, mode))
26
break;
27
}
28
29
30
static inline HWND first_window(enum window_search_mode mode, HWND *parent)
31
{
32
- HWND window = FindWindowEx(GetDesktopWindow(), NULL, NULL, NULL);
33
+ HWND window = GetWindow(GetDesktopWindow(), GW_CHILD);
34
35
*parent = NULL;
36
37
obs-studio-0.17.0.tar.xz/plugins/win-dshow/data/locale/hu-HU.ini -> obs-studio-17.0.1.tar.xz/plugins/win-dshow/data/locale/hu-HU.ini
Changed
10
1
2
FlipVertically="Függőleges tükrözés"
3
DeactivateWhenNotShowing="Kikapcsolás, ha nem jelenik meg"
4
5
-Bitrate="Bitráta"
6
+Bitrate="Bitsebesség"
7
Encoder.C985="AVerMedia H.264 kódoló (c985)"
8
Encoder.C353="AVerMedia H.264 kódoló"
9
10
obs-studio-0.17.0.tar.xz/plugins/win-dshow/data/locale/tr-TR.ini -> obs-studio-17.0.1.tar.xz/plugins/win-dshow/data/locale/tr-TR.ini
Changed
9
1
2
Activate="Etkinleştir"
3
Deactivate="Devredışı Bırak"
4
FlipVertically="Dikey Çevir"
5
+DeactivateWhenNotShowing="Gösterilmediğinde devre dışı bırak"
6
7
Bitrate="Bit hızı"
8
Encoder.C985="AVerMedia H.264 Kodlayıcısı (c985)"
9
obs-studio-0.17.0.tar.xz/plugins/win-mf/data/locale/hu-HU.ini -> obs-studio-17.0.1.tar.xz/plugins/win-mf/data/locale/hu-HU.ini
Changed
27
1
2
MFAACEnc="Media Foundation AAC kódoló"
3
-Bitrate="Bitráta"
4
+Bitrate="Bitsebesség"
5
6
MF.H264.EncoderName="Media Foundation H264 kódoló"
7
MF.H264.Encoder="Kódoló név"
8
9
MF.H264.BFrames="Egymást követő B-Frame szám"
10
MF.H264.CustomBufsize="Egyéni pufferméret használata"
11
MF.H264.BufferSize="Pufferméret"
12
-MF.H264.CustomMaxBitrate="Egyéni maximális bitráta használata"
13
-MF.H264.Bitrate="Bitráta"
14
-MF.H264.MaxBitrate="Max bitráta"
15
+MF.H264.CustomMaxBitrate="Egyéni maximális bitsebesség használata"
16
+MF.H264.Bitrate="Bitsebesség"
17
+MF.H264.MaxBitrate="Max bitsebesség"
18
MF.H264.KeyframeIntervalSec="Kulcsképkocka időköze (másodperc, 0=auto)"
19
MF.H264.RateControl="Sebesség vezérlés"
20
-MF.H264.CBR="CBR (állandó bitráta)"
21
-MF.H264.VBR="VBR (változó bitráta)"
22
+MF.H264.CBR="CBR (állandó bitsebesség)"
23
+MF.H264.VBR="VBR (változó bitsebesség)"
24
MF.H264.CQP="CQP (állandó minőség)"
25
MF.H264.MinQP="Minimális QP"
26
MF.H264.MaxQP="Maximális QP"
27
obs-studio-0.17.0.tar.xz/plugins/win-mf/data/locale/tr-TR.ini -> obs-studio-17.0.1.tar.xz/plugins/win-mf/data/locale/tr-TR.ini
Changed
31
1
2
3
MF.H264.EncoderName="Medya Vakfı H264 Kodlayıcısı"
4
MF.H264.Encoder="Kodlayıcı Adı"
5
+MF.H264.LowLatency="Düşük Gecikme Süresi (Çerçeve yeniden sıralamasını devre dışı bırak)"
6
+MF.H264.BFrames="Ardışık B-Frame sayısı"
7
MF.H264.CustomBufsize="İsteğe Bağlı Arabellek Boyutu Kullan"
8
MF.H264.BufferSize="Arabellek Boyutu"
9
+MF.H264.CustomMaxBitrate="Özel En Yüksek Bit Hızı Kullan"
10
MF.H264.Bitrate="Bithızı"
11
-MF.H264.MaxBitrate="Maks Bit hızı"
12
+MF.H264.MaxBitrate="En Yüksek Bit Hızı"
13
MF.H264.KeyframeIntervalSec="Anahtarkare Aralığı (saniye, 0=otomatik)"
14
+MF.H264.RateControl="Oran Kontrolü"
15
+MF.H264.CBR="CBR (Sabit bit hızı)"
16
MF.H264.VBR="VBR (Değişken Bit Hızı)"
17
+MF.H264.CQP="CQP (Sabit Kalite)"
18
MF.H264.MinQP="Minimum QP"
19
MF.H264.MaxQP="Maksimum QP"
20
+MF.H264.QPI="QP I-Frame"
21
+MF.H264.QPP="QP P-Frame"
22
+MF.H264.QPB="QP B-Frame"
23
MF.H264.Profile="Profil"
24
MF.H264.Advanced="Gelişmiş"
25
26
+MF.H264.EncoderSWMicrosoft="Microsoft Software H.264 Kodlayıcısı"
27
+MF.H264.EncoderHWAMD="AMD Video Coding Engine H.264 Kodlayıcısı (Media Foundation)"
28
+MF.H264.EncoderHWIntel="Intel Quick Sync H.264 Kodlayıcısı (Media Foundation)"
29
+MF.H264.EncoderHWNVIDIA="NVIDIA NVENC H.264 Kodlayıcısı (Media Foundation)"
30
31
obs-studio-0.17.0.tar.xz/plugins/win-wasapi/data/locale/hu-HU.ini -> obs-studio-17.0.1.tar.xz/plugins/win-wasapi/data/locale/hu-HU.ini
Changed
9
1
2
-AudioInput="Bemeneti hangrögzítés"
3
-AudioOutput="Kimeneti hangrögzítés"
4
+AudioInput="Bemeneti hangrögzítő"
5
+AudioOutput="Kimeneti hangrögzítő"
6
Device="Eszköz"
7
Default="Alapértelmezett"
8
UseDeviceTiming="Eszköz időbélyegzőinek használata"
9